android语言切换

来源:互联网 发布:ugcam数控编程教材 编辑:程序博客网 时间:2024/06/05 20:54

转载请注明:http://blog.csdn.net/ytmfdw/article/details/36669059

android语言切换,网上有很多文章,我看了不下于二十来篇,但内容都是千遍一律的,没有一篇能解决我实质的问题。但手头的项目,需要能切换系统语言,网上的代码一般都是通过

public static void updateLocale(Locale locale) {try {IActivityManager am = ActivityManagerNative.getDefault();Configuration config = am.getConfiguration();// Will set userSetLocale to indicate this isn't some passing default - the user// wants this rememberedconfig.setLocale(locale);am.updateConfiguration(config);// Trigger the dirty bit for the Settings Provider.BackupManager.dataChanged("com.android.providers.settings");} catch (RemoteException e) {// Intentionally left blank}}
这样的方式,其实这段代码只是通过代理服务来实现locale设置的,真正实现的,是在

/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

这个类里,以上的那种方法切换语言,会让电视卡屏3秒,用户体验太差了,(本项目是TV相关的),我看了下康佳的做法,设置系统语言时,要求重启电视,这也太狠了,经过本人几天的钻研,总算是弄出了些眉目,终于使语言切换,不卡屏,还能更新系统语言。

以下是我个人整理的一些相关代码,

(这些资料全是本人手打的,请尊重下程序员的劳动成果)

framework层语言设置,添加方法,不刷新界面


1、实现语言切换的代码在:
/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
方法:
updateConfiguration();
a.该方法实现了保存语言设置结果,通过调用updateConfigurationLocked(values, null, false, false);来实现
updateConfigurationLocked(values, null, false, false);是个私有的方法,
它通过调用
saveLocaleLocked(values.locale,
                                     !values.locale.equals(mConfiguration.locale),
                                     values.userSetLocale);
这个方法,来实现保存结果,实现代码:SystemProperties.set("user.language", l.getLanguage());
最终结果保存在  /data/property/persist.sys.language   文件中,国家也一样

b.保存结果后,通知所有应用,语言设置更新
通过发送消息,告知所注册的应用,也是在 updateConfigurationLocked(values, null, false, false);
if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                    Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
                    msg.obj = new Configuration(configCopy);
                    mHandler.sendMessage(msg);
                }

c.对所有应用进行更新,同样在 updateConfigurationLocked(values, null, false, false);

 for (int i=mLruProcesses.size()-1; i>=0; i--) {
                    ProcessRecord app = mLruProcesses.get(i);
                    try {
                        if (app.thread != null) {
                            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
                                    + app.processName + " new config " + mConfiguration);
                            app.thread.scheduleConfigurationChanged(configCopy);
                        }
                    } catch (Exception e) {
                    }
                }

后面的就不详细说了


2、现在我们要实现的目的是:

语言切换时,只保存设置的结果,而不更新界面
1、修改:/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
添加一个公开方法

public void updateLanguage(Configuration values) {if (mHeadless)return;int changes = 0;boolean kept = true;if (values != null) {Configuration newConfig = new Configuration(mConfiguration);changes = newConfig.updateFrom(values);if (changes != 0) {if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {Slog.i(TAG, "Updating configuration to: " + values);}EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);if (values.locale != null) {saveLocaleLocked(values.locale,!values.locale.equals(mConfiguration.locale),values.userSetLocale);Slog.i("ytmfdw", "update language::" + values.toString());}}}}



这个方法,只会把结果保存到 /data/property/persist.sys.language   文件中,如果有国家,也会保存,这个执行过程非常快,不会卡
但界面不会更新,只有重启系统才会更新,因此,更新界面的方法,还得用原来的 updateConfiguration(Configuration values)

2、修改代理接口:
/frameworks/base/core/java/android/app/ActivityManagerNative.java
a.添加updateLanguage方法:
public void updateLanguage(Configuration values) throws RemoteException{Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);values.writeToParcel(data, 0);mRemote.transact(UPDATE_LANGUAGE_TRANSACTION, data, reply, 0);reply.readException();data.recycle();reply.recycle();}



b.添加调用接口
在方法
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
…………
}
体中,添加一分支:
case UPDATE_LANGUAGE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Configuration config = Configuration.CREATOR.createFromParcel(data);
updateLanguage(config);
reply.writeNoException();
return true;
}

c.声明 UPDATE_LANGUAGE_TRANSACTION 常量,updateLanguage(Configuration values) 方法:
修改:/frameworks/base/core/java/android/app/IActivityManager.java
添加:
public void updateLanguage(Configuration values) throws RemoteException;
int UPDATE_LANGUAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;(161视情况而定,不能重复)

=============================================================================================================================
以上是底层代码实现,一般语言设置调用代码:
public static void updateLocale(Locale locale) {try {IActivityManager am = ActivityManagerNative.getDefault();Configuration config = am.getConfiguration();// Will set userSetLocale to indicate this isn't some passing default - the user// wants this rememberedconfig.setLocale(locale);am.updateConfiguration(config);// Trigger the dirty bit for the Settings Provider.BackupManager.dataChanged("com.android.providers.settings");} catch (RemoteException e) {// Intentionally left blank}}


这是会刷新界面的,经过上面修改后,可以这样调用 ;
 public static void updateLanguage(Locale locale) {try {IActivityManager am = ActivityManagerNative.getDefault();Configuration config = am.getConfiguration();// Will set userSetLocale to indicate this isn't some passing default - the user// wants this rememberedconfig.setLocale(locale);am.updateLanguage(config);// Trigger the dirty bit for the Settings Provider.BackupManager.dataChanged("com.android.providers.settings");} catch (RemoteException e) {// Intentionally left blank}}



当然,要先编译services.jar,然后编译framework.jar,否则后面的那个方法:updateLanguage会找不到的 



3 0
原创粉丝点击