您的位置:首页 > 移动开发 > Android开发

aidl实现Android系统语言切换

2016-11-09 13:03 597 查看
参考和引用:ytmfdw博文

简要分析

One step点击系统Settings直接看logcat

I/ActivityManager( 458): Config changes=2004 {1.0 ?mcc?mnc ja_JP ldltr sw800dp w800dp h1207dp 160dpi xlrg port finger -keyb/v/h -nav/h s.9}

I/ContactsProvider( 680): Locale has changed from zh_TW to ja_JP

I/ContactsDatabaseHelper( 680): Switching to locale ja_JP (ICU v51.1.0.1)

I/ContactsDatabaseHelper( 680): Locale change completed in 490ms

I/ContactsDatabaseHelper( 680): Switching to locale ja_JP (ICU v51.1.0.1)


Two_stepSettings_apk

packages/apps/Settings/com/android/settings/LocalePicker.Java


发现其中onLocaleSelected(final Locale locale)方法,去调用了fromwork层下的
/frameworks/base/core/Java/com/android/internal/app/LocalePicker
下的updateLocale()方法

public static void updateLocale(Locale locale) {
try {
IActivityManager am = ActivityManagerNative.getDefault();
Configuration config = am.getConfiguration();
config.setLocale(locale);
am.updateConfiguration(config);
BackupManager.dataChanged("com.android.providers.settings");
} catch (RemoteException e) {
}
}


实现步骤

One_step添加一个公共方法

/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(TAG, "update language::" + values.toString());
}
}
}
}


Two_step:修改代理

/frameworks/base/core/java/android/app/ActivityManagerNative.java


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();
}


添加调用接口在方法体中,添加一分支:

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;
}


Three_step声明常量

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视情况而定,不能重复)


Four_stepservice中添加方法

import com.android.internal.app.LocalePicker;
import android.os.RemoteException;
import java.util.Locale;
import android.content.res.Configuration;
import android.app.IActivityManager;
import android.app.backup.BackupManager;
import android.app.ActivityManagerNative;
......
Locale locale;
public void updateLanguage(String arg,String arg1) {
// switch(arg)
// { case 1:
// locale = new Locale("zh","CN");
// break;
// default:
// break;
// }
locale = new Locale(arg,arg1);
Slog.e(TAG,"ldd_locale locale:"+locale);
String language = locale.getDisplayName();
Slog.e(TAG,"ldd_locale language:"+language);
try {
IActivityManager am = ActivityManagerNative.getDefault();
Configuration config = am.getConfiguration();
Slog.e(TAG,"ldd_locale old_language:"+config);
config.setLocale(locale);
Slog.e(TAG,"ldd_locale new_language:"+config);
am.updateLanguage(config);
Slog.e(TAG,"ldd_locale updateLanguage success");
BackupManager.dataChanged("com.android.providers.settings");
} catch (RemoteException e) {
}
}


Five_stepaidl接口

aidl接口

void updateLanguage(String arg,String arg1);


将3个文件push 到 /system/framework/ 后重启

应用层调用例:

中文简体 reemanService.updateLanguage(zh,CN);

中文香港 reemanService.updateLanguage(zh,HK);

中文繁体(台湾)zh_TW

英文(英国)en_GB

英文(美国)en_US

日文 ja_JP

韩文 ko_KR

调用接口需要系统重启,系统才会更新语言

Six_step直接调用系统updateLocale方法

直接调用updateLocale()方法来传递参数locale来实现语言切换,而不需要系统重启

service中添加方法

public  void wakeLocale(String arg,String arg1){
Locale wake = new Locale(arg,arg1);
LocalePicker.updateLocale(wake);
Slog.e(TAG,"ldd_locale success");
}


系统签名&添加权限

在AndroidManifest.xml 中添加

android:sharedUserId="android.uid.system"


<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />


在Android.mk中添加

LOCAL_CERTIFICATE:=platform


在实际项目开发过程中,可能你需要用到第一种方法,后者的方法的应用程序需要内嵌入系统中来编译下执行?系统签名?……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: