MyException - 我的异常网
当前位置:我的异常网» Android » Android的语言设立

Android的语言设立

www.MyException.Cn  网友分享于:2013-07-29  浏览:49次
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布局为:

view plain print ?
  1. <PreferenceScreen    
  2.     android:key="phone_language"     
  3.     android:title="@string/phone_language" >    
  4.     <intent android:action="android.intent.action.MAIN"     
  5.         android:targetPackage="com.android.settings"     
  6.         android:targetClass="com.android.settings.LocalePicker" />    
  7. </PreferenceScreen>    

 

    所以,当用户点击“Settings -> Language & keyboard -> Select language”时,将启动“com.android.settings.LocalePicker”的Activity。其对应的源代码为:

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

 

    LocalePicker Activity继承自ListActivity。在它的onCreate()回调中,调用了下面一条语句:

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

 

    LocalePicker Activity将取得的locale字符串进行了一些处理,然后创建了ArrayAdapter<Loc> adapter,并绑定到ListActivity的ListView上。当用户点击ListView上的Item时,再将选中的locale信息设置到 Android系统中。

view plain print ?
  1. @Override     
  2. protected   void  onListItemClick(ListView l, View v,  int  position,  long  id) {    
  3.     try  {    
  4.         IActivityManager am = ActivityManagerNative.getDefault();    
  5.         Configuration config = am.getConfiguration();    
  6.         Loc loc = mLocales[position];    
  7.         config.locale = loc.locale;    
  8.         // indicate this isn't some passing default - the user wants this remembered     
  9.         config.userSetLocale = true ;    
  10.         am.updateConfiguration(config);    
  11.         // Trigger the dirty bit for the Settings Provider.     
  12.         BackupManager.dataChanged("com.android.providers.settings" );    
  13.     } catch  (RemoteException e) {    
  14.         // Intentionally left blank     
  15.     }    
  16.     finish();    
  17. }    

 

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定义如下:

view plain print ?
  1. /**  
  2. * Get the locales that this asset manager contains data for.  
  3. */   
  4. public   native   final  String[] getLocales();  

 

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

 

        2)、JNI层

        JNI层的代码路径为:

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

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

view plain print ?
  1. static  jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz);  
  2. "getLocales" "()[Ljava/lang/String;" , ( void *) android_content_AssetManager_getLocales },  
  3. 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

        函数声明和定义如下:

view plain print ?
  1. /**  
  2. * Get the known locales for this asset manager object.  
  3. */   
  4. void  getLocales(Vector<String8>* locales)  const ;  
  5. void  AssetManager::getLocales(Vector<String8>* locales)  const   
  6. {  
  7.     ResTable* res = mResources;  
  8.     if  (res != NULL) {  
  9.         res->getLocales(locales);  
  10.     }  
  11. }  

 

 

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

        ResTable类的代码路径如下:

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

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

 

        相关的函数有四个:

 

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

 

 

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

文章评论

 程序员的样子
程序员的样子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员都该阅读的书
程序员都该阅读的书
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员必看的十大电影
程序员必看的十大电影
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
老程序员的下场
老程序员的下场
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
一个程序员的时间管理
一个程序员的时间管理
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
那些争议最大的编程观点
那些争议最大的编程观点
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员应该关注的一些事儿
程序员应该关注的一些事儿
中美印日四国程序员比较
中美印日四国程序员比较
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
如何成为一名黑客
如何成为一名黑客
为什么程序员都是夜猫子
为什么程序员都是夜猫子
编程语言是女人
编程语言是女人
我是如何打败拖延症的
我是如何打败拖延症的
10个调试和排错的小建议
10个调试和排错的小建议
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员的鄙视链
程序员的鄙视链
鲜为人知的编程真相
鲜为人知的编程真相
代码女神横空出世
代码女神横空出世
总结2014中国互联网十大段子
总结2014中国互联网十大段子
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
每天工作4小时的程序员
每天工作4小时的程序员
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
Java程序员必看电影
Java程序员必看电影
漫画:程序员的工作
漫画:程序员的工作
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
我的丈夫是个程序员
我的丈夫是个程序员
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有