首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android的语言设立

2012-07-28 
Android的语言设置原始出处为http://blog.csdn.net/seker_xinjian/archive/2011/03/30/6288957.aspx.本文

Android的语言设置

原始出处为http://blog.csdn.net/seker_xinjian/archive/2011/03/30/6288957.aspx.

本文中涉及的代码所对应的Android Source版本为2.3.3,代号Gingerbread.

?

?? ?这两天在调查Android系统Setting程序中对于语言设置这块的内容。具体位置有以下两处:

?? ? ? ?1)、设置显示语言:Settings -> Language & keyboard -> Select language?

?? ? ? ?2)、设置输入语言:Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages

?

?? ?Settings工程中,Settings -> Language & keyboard界面所对应的Java代码和Preference布局如下:

?? ? ? ?<android_root>/packages/apps/Settings/src/com/android/settings/LanguageSettings.java

?? ? ? ?<android_root>/packages/apps/Settings/res/xml/language_settings.xml

?

?

1、Settings -> Language & keyboard -> Select language

?? ?在<android_root>/packages/apps/Settings/res/xml/language_settings.xml中,该模块的Preference布局为:

<PreferenceScreen android:key="phone_language" android:title="@string/phone_language"> <intent android:action="android.intent.action.MAIN" android:targetPackage="com.android.settings" android:targetstyle="display: none;"> @Override protected void onListItemClick(ListView l, View v, int position, long id) { try { IActivityManager am = ActivityManagerNative.getDefault(); Configuration config = am.getConfiguration(); Loc loc = mLocales[position]; config.locale = loc.locale; // indicate this isn't some passing default - the user wants this remembered config.userSetLocale = true; am.updateConfiguration(config); // Trigger the dirty bit for the Settings Provider. BackupManager.dataChanged("com.android.providers.settings"); } catch (RemoteException e) { // Intentionally left blank } finish(); }

?

2、Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages

?? ?在<android_root>/packages/apps/Settings/res/xml/language_settings.xml中,找不到输入法相关的布局内容。但是,可以在<android_root>/packages/apps/Settings/src/com/android/settings/LanguageSettings.java中找到一个onCreateIMM()函数,它在onCreate()回调中被调用。它的作用就是通过InputMethodManager类的getInputMethodList() API获得当前系统已安装的输入法列表,然后逐个地动态生成Preference布局,追加加到设置界面上。

?

?? ?事实上,Gingerbread默认的有三种输入法:英文,中文,日文。对应的工程代码路径为:

?? ? ? ?<android_root>/packages/inputmethods/LatinIME/

?? ? ? ?<android_root>/packages/inputmethods/OpenWnn/

?? ? ? ?<android_root>/packages/inputmethods/PinyinIME/

?

?? ?通过Log,可以发现,当点击 Android keyboard [settings] 菜单项时,将会启动一个Activity:com.android.inputmethod.latin/com.android.inputmethod.latin.LatinIMESettings。因此可以断定<android_root>/packages/inputmethods/LatinIME/就是我们要找的Android keyboard [settings]输入法的源代码工程。

?

?? ?通过<android_root>/packages/inputmethods/LatinIME/java/AndroidManifest.xml,可以找到这个Activity和布局是:

?? ? ? ?<android_root>/packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIMESettings.java

?? ? ? ?<android_root>/packages/inputmethods/LatinIME/java/res/xml/prefs.xml

?

?? ?最后综合可以判定Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages对应的代码是:

?? ? ? ?<android_root>/packages/inputmethods/LatinIME/java/src/.../latin/InputLanguageSelection.java

?

?? ?InputLanguageSelection继承自PreferenceActivity,它有一个getUniqueLocales()函数,在这个函数中,它如同<android_root>/packages/apps/Settings/src/com/android/settings/LocalePicker.java一样,调用了下面的语句:

?? ? ? ?String[] locales = getAssets().getLocales(); ?

?

?? ?然后InputLanguageSelection Activity将取得的locale字符串进行了一些处理,然后循环最终的Locale列表,逐个的为每种语言动态生成CheckBoxPreference加载到InputLanguageSelection的画面上。当用户选中语言,退出InputLanguageSelection Activity时,这些选中的语言就会被保存到SharedPreferences中去。

?

?? ?到此,可以看到以上这两处的做法都是使用Activity的getAssets()方法取得AssetManager的实例,然后调用AssetManager的getLocales()函数取得系统所支持的语言。然后经过自己的一些过滤办法,最终显示在UI界面。

?

?这两天在调查Android系统Setting程序中对于语言设置这块的内容。具体位置有以下两处:

?? ? ? ? ? ? ? ?1)、设置显示语言:Settings -> Language & keyboard -> Select language?

?? ? ? ? ? ? ? ?2)、设置输入语言:Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages

?

?? ? ? ?这两处都是使用Activity的getAssets()方法取得AssetManager的实例,然后调用AssetManager的getLocales()函数取得系统所支持的语言。然后经过自己的一些特殊的过滤办法,最终显示到UI界面。

?? ? ? ?然而,对于AssetManager究竟是如何取得系统所支持的语言的呢?这需要追究AssetManager更底层的实现了。本文主要是追踪用AssetManager类的getLocales() API的底层实现。

?

?? ? ? ?1)、Java Framework层

?? ? ? ?AssetManager类的代码路径为:

?? ? ? ? ? ? ? ?<android_root>/frameworks/base/core/java/android/content/res/AssetManager.java

?? ? ? ?它的getLocales() API定义如下:

/** * Get the locales that this asset manager contains data for. */ public native final String[] getLocales();

?

?? ? ? ?可见这个API虽然定义在Java Framework层,但是它的实现是有Native层的代码实现的。

?

?? ? ? ?2)、JNI层

?? ? ? ?JNI层的代码路径为:

?? ? ? ? ? ? ? ?<android_root>/frameworks/base/core/jni/android_util_AssetManager.cpp

?? ? ? ?函数定义,?JNINativeMethod 定义,JNI函数注册分别如下:

static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz); { "getLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getLocales }, AndroidRuntime::registerNativeMethods(env, "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));

?

?

?? ? ? ?从android_content_AssetManager_getLocales()函数的定义中看出 获取系统系统所支持的语言的功能是由AssetManager类来实现的

?

?? ? ? ?3)、Native lib层

?? ? ? ?AssetManager类的代码路径如下:

?? ? ? ? ? ? ? ? <android_root>/frameworks/base/include/utils/AssetManager.h

?? ? ? ? ? ? ? ? <android_root>/frameworks/base/libs/utils/AssetManager.cpp

?? ? ? ?函数声明和定义如下:

/** * Get the known locales for this asset manager object. */ void getLocales(Vector<String8>* locales) const; void AssetManager::getLocales(Vector<String8>* locales) const { ResTable* res = mResources; if (res != NULL) { res->getLocales(locales); } }

?

?

?? ? ? ?可见,真正的实现部分由更底层的ResTable类来实现的。

?? ? ? ?ResTable类的代码路径如下:

?? ? ? ? ? ? ? ?<android_root>/frameworks/base/include/utils/ResourceTypes.h

?? ? ? ? ? ? ? ?<android_root>/frameworks/base/libs/utils/ResourceTypes.cpp

?

?? ? ? ?相关的函数有四个:

?

void getLocales(Vector<String8>* locales) const; void getConfigurations(Vector<ResTable_config>* configs) const; // 这两个函数从一个Vector<PackageGroup*>的数据结构中解析出系统支持的语言的code。 status_t parsePackage(const ResTable_package* const pkg, const Header* const header); status_t add(const void* data, size_t size, void* cookie, Asset* asset, bool copyData=false); // 这两个函数初始化好Vector<PackageGroup*>的数据结构。

?

?

?? ? ? ?到此,已经可以看到了AssetManager.java类在底层是如何一步步的实现的。但是最终我们的问题的落在了ResTable类何时被初始化,何时调用它的add()函数的问题上。

热点排行