Android对国际化与多语言切换已经做得不错了,一个应用只要命名相应语系的values-[language]文件夹,通过“设置”→“语言&键盘”→“选择语言”即可实现应用多种语言的切换。        但如何在应用里自己实现?搜索过发现网上有如下的做法:

[java] view plaincopyprint?
  1. Resources res = getResources();
  2. Configuration config = res.getConfiguration();
  3. config.locale = locale;
  4. DisplayMetrics dm = res.getDisplayMetrics();
  5. res.updateConfiguration(config, dm);
         Resources res = getResources();Configuration config = res.getConfiguration();config.locale = locale;DisplayMetrics dm = res.getDisplayMetrics();res.updateConfiguration(config, dm);

亲测,不成功。好吧,程序员又到了自力更生的时候了。下面开始讲应用多语言切换的三种方法。          先上效果图:

 

前两种方法的原理即在应用里实现“选择语言”。通过查看源码,其核心代码为:

[java] view plaincopyprint?
  1. IActivityManager iActMag = ActivityManagerNative.getDefault();
  2. try {
  3. Configuration config = iActMag.getConfiguration();
  4. config.locale = locale;
  5. // 此处需要声明权限:android.permission.CHANGE_CONFIGURATION
  6. // 会重新调用 onCreate();
  7. iActMag.updateConfiguration(config);
  8. } catch (RemoteException e) {
  9. e.printStackTrace();
  10. }
  11. PS:感谢 曾阳 的帮助。
       IActivityManager iActMag = ActivityManagerNative.getDefault();try {Configuration config = iActMag.getConfiguration();config.locale = locale;// 此处需要声明权限:android.permission.CHANGE_CONFIGURATION// 会重新调用 onCreate();iActMag.updateConfiguration(config);} catch (RemoteException e) {e.printStackTrace();}PS:感谢 曾阳 的帮助。

可以发现IActivityManager与ActivityManagerNative都是非公开类。如何调用?第一种是API欺骗,第二种是使用Java反射机制。     1. API欺骗     烧制到手机中的android.jar包含了Android所需的各种类与方法;而供开发者使用的android.jar只是其中的一部分。API欺骗是指在应用中去模拟未公开的类和方法让应用编译通过并生成APK,然而在应用实际运行中调用的却仍是烧制到手机中真实的android.jar。          通过核心代码可以看到我们要模拟的是ActivityManagerNative中的一个方法getDefault()和IActivityManager中的两个方法getConfiguration()与updateConfiguration(config)。参照源码,应用的工程结构图及代码模拟如下:          工程结构图:

代码:

[java] view plaincopyprint?
  1. ActivityManagerNative.java
  2. package android.app;
  3. /**
  4. * @author Sodino E-mail:sodinoopen@hotmail.com
  5. * @version Time:2011-7-10 上午11:37:01
  6. */
  7. public abstract class ActivityManagerNative {
  8. public static IActivityManager getDefault() {
  9. return null;
  10. }
  11. }
  12. IActivityManager.java
  13. package android.app;
  14. import android.content.res.Configuration;
  15. import android.os.RemoteException;
  16. /**
  17. * @author Sodino E-mail:sodinoopen@hotmail.com
  18. * @version Time:2011-7-10 上午11:37:46
  19. */
  20. public abstract interface IActivityManager {
  21. public abstract Configuration getConfiguration() throws RemoteException;
  22. public abstract void updateConfiguration(Configuration paramConfiguration)
  23. throws RemoteException;
  24. }
ActivityManagerNative.java
package android.app;/*** @author Sodino E-mail:sodinoopen@hotmail.com* @version Time:2011-7-10 上午11:37:01*/
public abstract class ActivityManagerNative {public static IActivityManager getDefault() {return null;}
}IActivityManager.java
package android.app;import android.content.res.Configuration;
import android.os.RemoteException;/*** @author Sodino E-mail:sodinoopen@hotmail.com* @version Time:2011-7-10 上午11:37:46*/
public abstract interface IActivityManager {public abstract Configuration getConfiguration() throws RemoteException;public abstract void updateConfiguration(Configuration paramConfiguration)throws RemoteException;
}

实现模拟了这两个类后,即可正常使用上面提到的转换语系的核心代码了。

2. Java反射机制     不多说了,Java反射机制入门教程:     http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html     之前写过的几个使用Java反射的例子:     [Android]获取未安装的APK图标(原创非转帖)     http://blog.csdn.net/sodino/article/details/6215224     [Android]挂断、接听电话     http://blog.csdn.net/sodino/article/details/6181610          直接上代码:

[java] view plaincopyprint?
  1. private void updateLanguage(Locale locale) {
  2. Log.d("ANDROID_LAB", locale.toString());
  3. try {
  4. Object objIActMag, objActMagNative;
  5. Class clzIActMag = Class.forName("android.app.IActivityManager");
  6. Class clzActMagNative = Class.forName("android.app.ActivityManagerNative");
  7. Method mtdActMagNative$getDefault = clzActMagNative.getDeclaredMethod("getDefault");
  8. // IActivityManager iActMag = ActivityManagerNative.getDefault();
  9. objIActMag = mtdActMagNative$getDefault.invoke(clzActMagNative);
  10. // Configuration config = iActMag.getConfiguration();
  11. Method mtdIActMag$getConfiguration = clzIActMag.getDeclaredMethod("getConfiguration");
  12. Configuration config = (Configuration) mtdIActMag$getConfiguration.invoke(objIActMag);
  13. config.locale = locale;
  14. // iActMag.updateConfiguration(config);
  15. // 此处需要声明权限:android.permission.CHANGE_CONFIGURATION
  16. // 会重新调用 onCreate();
  17. Class[] clzParams = { Configuration.class };
  18. Method mtdIActMag$updateConfiguration = clzIActMag.getDeclaredMethod(
  19. "updateConfiguration", clzParams);
  20. mtdIActMag$updateConfiguration.invoke(objIActMag, config);
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
 private void updateLanguage(Locale locale) {Log.d("ANDROID_LAB", locale.toString());try {Object objIActMag, objActMagNative;Class clzIActMag = Class.forName("android.app.IActivityManager");Class clzActMagNative = Class.forName("android.app.ActivityManagerNative");Method mtdActMagNative$getDefault = clzActMagNative.getDeclaredMethod("getDefault");// IActivityManager iActMag = ActivityManagerNative.getDefault();objIActMag = mtdActMagNative$getDefault.invoke(clzActMagNative);// Configuration config = iActMag.getConfiguration();Method mtdIActMag$getConfiguration = clzIActMag.getDeclaredMethod("getConfiguration");Configuration config = (Configuration) mtdIActMag$getConfiguration.invoke(objIActMag);config.locale = locale;// iActMag.updateConfiguration(config);// 此处需要声明权限:android.permission.CHANGE_CONFIGURATION// 会重新调用 onCreate();Class[] clzParams = { Configuration.class };Method mtdIActMag$updateConfiguration = clzIActMag.getDeclaredMethod("updateConfiguration", clzParams);mtdIActMag$updateConfiguration.invoke(objIActMag, config);} catch (Exception e) {e.printStackTrace();}}

实际运行后,发现对当前系统设置了新的Locale后,不单自己的应用语系改变了,系统所有的应用语系都改变了。这肯定是不合理的。有一个解决办法是在应用界面退出前再次对系统设置成碑的Locale,不过个人不喜欢这样的办法,加之调用updateConfiguration()方法后,整个Activity会重新onCreate(),这个考虑Activity的生命周期可有点费劲了。于是有了下面这第三种方法。          3. 自己转换语系(哈哈,这个名字很现实啊)     动手实现嘛,啥都系统弄好了,那程序员的存在还有什么意义呢。     自己转换语系有点麻烦,先看工程结构图:

values/strings.xml与xml/english.xml的内容是相同的;values-zh-rCN/strings.xml与xml/chinese.xml的内容也是相同的。出现这样的冗余是因为生成APK时values下的内容都打到rasc去了,读取不了了。          自己实现语系的转换需要考虑到:     3.1  R.xxxxx.id与对应语系中文本串的对应(需要特别考虑到R.array.string字符串数组)。     3.2 解析xml。     3.3 设置语系后,所有界面元素的手动刷新。          在xml中声明一个string是这个的格式:

[html] view plaincopyprint?
  1. <string name="app_name">语言应用</string>
    <string name="app_name">语言应用</string>

对应R文件会生成一个id指代该string

[java] view plaincopyprint?
  1. public static final class string {
  2. public static final int app_name=0x7f050001;
  3. }
    public static final class string {public static final int app_name=0x7f050001;}

3.1的问题就是如何实现id与string的匹配,解决方法为:

[java] view plaincopyprint?
  1. Resources res = context.getResources();
  2. String pkg = context.getPackageName();
  3. String tag = "app_name";
  4. int idTag = res.getIdentifier(tag, "string", pkg);
    Resources res = context.getResources();String pkg = context.getPackageName();String tag = "app_name";int idTag = res.getIdentifier(tag, "string", pkg);

3.2 解析XML     这儿要用到一个新的工具了:XmlResourceParser,解析过程有点绕,但比SAX简单些。具体细节见LanguageApp_Sodino工程中的代码吧。          3.3 手动刷新界面。     要获取所有涉及到语系更新组件的索引逐一更新,体力活儿,细心点花点力气也可实现。          详细实现过程见下面三个工程中:     LanguageApp_APICheat     LanguageApp_Reflection     LanguageApp_Sodino     (PS:不要问我为什么下载的工程在IDE中为什么无法直接使用,为什么打开是乱码红叉一大堆,既然是程序员,遇到问题是不是也该自己多思考思考呢。)

本文内容归CSDN博客博主Sodino 所有 转载请注明出处:http://blog.csdn.net/sodino/article/details/6596709

[Android]应用语言切换的三种方法相关推荐

  1. c语言编程非线性方程求解,c语言计算机编程三种方法求解非线性方程

    c语言计算机编程三种方法求解非线性方程 本 科 专 业 学 年 论 文题 目:非线性方程求解比较姓 名: 何 娟 专 业: 计算机科学技术系 班 级: 08 级本科(2)班 指 导 老 师: 刘 晓 ...

  2. c语言编程非线性方程求解,c语言计算机编程三种方法求解非线性方程.doc

    c语言计算机编程三种方法求解非线性方程.doc 本 科 专 业 学 年 论 文题 目非线性方程求解比较姓 名 何 娟 专 业 计算机科学技术系 班 级 08 级本科(2)班 指 导 老 师 刘 晓 娜 ...

  3. android写入文件方法,Android 追加写入文件的三种方法

    一.使用FileOutputStream 使用FileOutputStream,在构造FileOutputStream时,把第二个参数设为true public static void method1 ...

  4. 查找android studio版本号,Android studio版本号查看的三种方法

    Android studio版本号查看的三种方法 发布于 2016-04-10 22:50:17 | 688 次阅读 | 评论: 0 | 来源: 网友投递 Android Studio Android ...

  5. CSS实现导航条Tab切换的三种方法

    前面的话 导航条Tab在页面中非常常见,本文说详细介绍CSS实现导航条Tab的三种方法 布局   根据上图所示,先规定几个定义,上图的模块整体叫做导航,由导航标题和导航内容组成.要实现上图所示的布局效 ...

  6. 【网页前端实现多张图片轮播或者切换】三种方法实现

    多张图片轮播 今天我们主要用三种方式实现多张图片轮播,运用的语言是web中的html,使用软件是HBuilder. 达到以下这种效果:![可以通过下方原点点击或者左右两侧点击进行图片的切换](http ...

  7. Android中获取网络图片的三种方法

    android中获取网络图片是一件耗时的操作,如果直接获取有可能会出现应用程序无响应(ANR:Application Not Responding)对话框的情况.对于这种情况,一般的方法就是耗时操作用 ...

  8. Android中图片圆形设置三种方法介绍

    Android开发中经常会用到圆形图片,比如在用户头像设置,现在提供三种主要实现方式: 方案一:使用第三方图像框架 Fresco 1.添加依赖 dependencies {compile 'com.f ...

  9. android调用音乐播放器,三种方法

    小弟想请问一下,如何在自己写的程序中调用系统的音乐播放器呢. 我在google上搜索了,主要是有两种方法,但是都不是我想要的. 第一种是,使用mp3音乐文件的uri,和intent,进行调用,但是这种 ...

  10. android中onclick事件失效,Android中OnClick事件的三种方法

    //第一种方式 Button Btn1 = (Button)findViewById(R.id.button1);//获取按钮资源 Btn1.setOnClickListener(new Button ...

最新文章

  1. centos下设置node.js开机启动(并且启动自己的项目js)
  2. 使用工作集(Working Set)整理项目
  3. Docker 最初的2小时(Docker从入门到入门)
  4. 嵌套 思维导图_工作小Tips:如何用思维导图来整理你的汇报
  5. 360 您访问的是存在未经证实信息的网站
  6. securecrt切换会话(session)的显示方式
  7. mac 系统新功能体验-根据时间变化的动态桌面背景,看壁纸演绎风景大片中的日出与日落
  8. S/4HANA Product master OData
  9. c语言 函数调用 传值调用 引用调用 传地址调用,C语言中的传值调用和引用调用...
  10. Win10调试ssd_tensorflow的目标检测
  11. 最长公共子序列(信息学奥赛一本通-T1265)
  12. C#中Invoke 和 BeginInvoke 的区别
  13. 《超级女声》新增 9月4日 娱乐无极限 回顾超女专辑(都是超女) [共39G的精品]
  14. SpringBoot系列之使用自定义注解校验用户是否登录
  15. python学习手册 第7章 字符串
  16. Acid-PEG2000-Pyrene,羧基和芘丁酸修饰的PEG,HOOC-PEG2000-Pyrene
  17. 启明云端分享|IDO-SOM3022-V1.0:可适用于物联网等多个领域
  18. u大师u盘启动盘制作教程 教你怎么装系统(超微版)
  19. 散粉在哪个步骤用_【散粉怎么用】正确的散粉用法_方法步骤顺序-她时代-女性时尚生活宝典...
  20. 一篇博客带你熟悉Eclipse、AndroidStudio下搭建NDK环境(内有Demo)

热门文章

  1. 周期T与频率f数量级对应关系(MHz--μs)
  2. pie函数--Matplotlib
  3. 皕杰报表使用技巧:竖排文字如何输入
  4. 双11当天,淘宝搜索如何让CPU使用率降45%,GMV提1% | 论文
  5. 使用pumysql 查询数据插入另外一张表
  6. 从有限状态机(FSM)到行为树(Behavior Tree)(2)
  7. mvc表单Form提交 --实体
  8. html5 figure 标签
  9. USACO习题:Your Ride Is Here
  10. QT + OSG实现触屏旋转和双指缩放