Android对国际化与多语言切换已经做得不错了,一个应用只要命名相应语系的values-[language]文件夹,通过“设置”→“语言&键盘”→“选择语言”即可实现应用多种语言的切换。

但如何在应用里自己实现?搜索过发现网上有如下的做法:

Resources res = getResources();

Configuration config = res.getConfiguration();

config.locale = locale;

DisplayMetrics dm = res.getDisplayMetrics();

res.updateConfiguration(config, dm);

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

先上效果图:

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

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)。参照源码,应用的工程结构图及代码模拟如下:

工程结构图:

代码:

ActivityManagerNative.java

packageandroid.app;

/**

* @author Sodino E-mail:sodinoopen@hotmail.com

* @version Time:2011-7-10 上午11:37:01

*/

publicabstractclassActivityManagerNative {

publicstaticIActivityManager getDefault() {

returnnull;

}

}

IActivityManager.java

packageandroid.app;

importandroid.content.res.Configuration;

importandroid.os.RemoteException;

/**

* @author Sodino E-mail:sodinoopen@hotmail.com

* @version Time:2011-7-10 上午11:37:46

*/

publicabstractinterfaceIActivityManager {

publicabstractConfiguration getConfiguration()throwsRemoteException;

publicabstractvoidupdateConfiguration(Configuration paramConfiguration)

throwsRemoteException;

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

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

直接上代码:

privatevoidupdateLanguage(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是这个的格式:

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

publicstaticfinalclassstring {

publicstaticfinalintapp_name=0x7f050001;

}

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

Resources res = context.getResources();

String pkg = context.getPackageName();

String tag = "app_name";

intidTag = res.getIdentifier(tag,"string", pkg);     3.2 解析XML

这儿要用到一个新的工具了:XmlResourceParser,解析过程有点绕,但比SAX简单些。具体细节见LanguageApp_Sodino工程中的代码吧。

3.3 手动刷新界面。

要获取所有涉及到语系更新组件的索引逐一更新,体力活儿,细心点花点力气也可实现。

详细实现过程见下面三个工程中:

LanguageApp_APICheat

LanguageApp_Reflection

LanguageApp_Sodino     (PS:不要问我为什么下载的工程在IDE中为什么无法直接使用,为什么打开是乱码红叉一大堆,既然是程序员,遇到问题是不是也该自己多思考思考呢。) 本文内容归CSDN博客博主Sodino 所有

java中语言转换方法_语言切换的三种方法相关推荐

  1. java中如何启动一个新的线程三种方法

    java开启新线程的三种方法: 方法1:继承Thread类 1):定义bai一个继承自Java.lang.Thread类的du类A. 2):覆盖zhiA类Thread类中的run方法. 3):我们编写 ...

  2. java中判断字符串是否为数字的三种方法

    1用JAVA自带的函数 public static boolean isNumeric(String str){for (int i = str.length();--i>=0;){ if (! ...

  3. JAVA中几种循环结构的表示_本文通过实例讲解给大家介绍Java中for、while、do while三种循环语句的区别,具体详情如下所示:第一种:for循环 循环结构for语句的格式...

    本文通过实例讲解给大家介绍Java中for.while.do while三种循环语句的区别,具体详情如下所示: 第一种:for循环 循环结构for语句的格式: for(初始化表达式;条件表达式;循环后 ...

  4. java中char类型转换成int类型的两种方法

    java中char类型转换成int类型的两种方法 方法一: 第一种利用Integer包装类的方法Integer.parseInt Copychar ch = '9'; if (Character.is ...

  5. 计算机怎么删除表格,电脑中删除Excel2010表格多余图片的三种方法

    为了让表格看起来更加直观,很多朋友都会在Excel中插入图片.那么,当我们大批量插入图片时,如果想要删除的话,应该怎么办呢?以下是系统城小编为您带来的电脑中删除Excel2010表格多余图片的三种方法 ...

  6. Altium designer 在原理图及PCB中高亮某一条网络的三种方法

    1. alt 键+鼠标左键 2. 利用原理图界面右下角的"笔"一样的工具 3 .Navigator(在原理图界面右下角,Designe Compiler 选项中),选择如图所示的n ...

  7. linux下dd做优盘启动_Linux中制作U盘启动盘的三种方法,使用启动盘创建器/dd命令和Etcher...

    本文介绍在Linux系统中制作U盘启动盘的三种方法:使用启动盘创建器.dd命令和Etcher,以下以优麒麟Ubuntu Kylin 19.04为例,为你介绍这三种方法.如果要在Windows中制作U盘 ...

  8. Java | Java语言在Eclipse控制台输入的三种方法

    写在前面的内容,java控制台输入浅尝辄止即可 >>> 文章目录 三种方法比较一览图 方法一:in/out public static final InputStream in//静 ...

  9. cad画直角命令_在cad中怎么画角度?cad画角度三种方法介绍

    cad是应用最广泛的计算机辅助设计软件,学会使用cad怎么画角度是必不可少的,尤其是对于新手来说,更应该学习.那么在cad中怎么画角度?下面小编就为大家介绍三种cad画角度方法,希望对大家有所帮助! ...

  10. c语言实现求最大公约数的三种方法

    一.最大公约数 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约数记为(a,b,c),多个整数的最大公约数也 ...

最新文章

  1. 1126 Eulerian Path
  2. linux中普通文件和块设备文件的区别
  3. (转)Android 使用com.j256.ormlite
  4. MySQL系列:性能优化
  5. hibernate学习笔记二
  6. grafana—— worldPing APP 中文
  7. 最强鸿蒙系统txt_鸿蒙OS最新进展,余承东将亲自解说,是时候对谷歌“亮剑”了...
  8. 准备 LVM Volume Provider - 每天5分钟玩转 OpenStack(49)
  9. JAVA程序员面试总结,高手整理加强版
  10. java从hbase增量导出到,Hbase实用技巧:全量+增量数据的迁移方法
  11. linux命令大全私房菜,linux命令大全(自己制作,基于鸟书私房菜以及man)-D
  12. 【服务器代理跨域】---测试网络上一些接口是否可以被调用
  13. 「leetcode」93.复原IP地址【回溯算法】详解!
  14. 钢结构节点输出软件_BIM技术助力桥梁钢结构设计施工一体化建设
  15. 电脑上网前必须要安装的四个补丁
  16. python用实现FGO自动挂机战斗思路
  17. Hibernate事务与并发问题处理(乐观锁与悲观锁)【转】
  18. 华为机试:VLAN资源池
  19. 又一个奇葩要求,Python是如何将“中文”转“拼音”的?
  20. 【科普】中医药治疗重症肌无力的独特优势

热门文章

  1. 【数据统计】移动端数据可视化模板、数据统计、Axure移动端图表数据统计设计
  2. 【2022最新Java面试宝典】—— 多线程面试(60道含答案)
  3. 点云数据实时在线浏览共享与逆向建模应用
  4. 实用工具软件远古大神Nir Sofer,数百款短小精悍便携工具,从Win2000到Win10通吃
  5. 我的听歌神器--网易云
  6. C语言 输出乘法口诀表
  7. STM32CubeMX系列TIM
  8. 利用计算机本地文档重装系统,本地模式怎么进入PE系统对电脑进行重装
  9. (7)公众号开发-自定义菜单
  10. 测试用例--测试大纲(提纲)法