android语言切换

转载请注明: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 remembered
						config.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 remembered
						config.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 remembered
					config.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会找不到的 



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ytmfdw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值