Android 根据SIM卡自动切换语言
1. 实现只在Google setup wizard情况下才切换SIM卡语言,其余时候(比如已经开机进入Home)不切换语言
在/frameworks/opt/telephony/src/java/com/android/internal/telephony/MccTable.java中添加:
public static void updateMccMncConfiguration(Context context, String mccmnc) { ... Slog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc); Locale mccLocale = null; if (mcc != 0) { setTimezoneFromMccIfNeeded(context, mcc); mccLocale = getLocaleFromMcc(context, mcc,null);//添加这句读取SIM语言 } try { Configuration config = new Configuration(); boolean updateConfig = false; if (mcc != 0) { config.mcc = mcc; config.mnc = mnc == 0 ? Configuration.MNC_ZERO : mnc; updateConfig = true; } //Add code BEGIN if(UPDATE_SIM_LANGUAGE) { boolean isDeviceProvisioned = Settings.Global.getInt( context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,0) != 0; boolean setupCompleted = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE,0) != 0; if (mccLocale != null && !isDeviceProvisioned && !setupCompleted) { Configuration sysConfig = new Configuration(); sysConfig = ActivityManager.getService().getConfiguration();; LocaleList currentLocales = sysConfig.getLocales(); LocaleList newUserLocales = new LocaleList(mccLocale, currentLocales); config.setLocales(newUserLocales); updateConfig = true; Settings.System.putConfiguration(context.getContentResolver(), config); } } //Add code END if (updateConfig) { Slog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config); ActivityManager.getService().updateConfiguration(config); } else { Slog.d(LOG_TAG, "updateMccMncConfiguration nothing to update"); } } catch (RemoteException e) { Slog.e(LOG_TAG, "Can't update configuration", e); } } }
此处有下面几个关键点。
Settings.Global.DEVICE_PROVISIONED 和 Settings.Secure.USER_SETUP_COMPLETE用来判断当前Google SetupWizard有没有结束。
如果还在SetupWizard画面,这两个值都是0;当SetupWizard结束,这两个会被设定为1.
ActivityManager.getService().updateConfiguration(config) 会呼叫到ActivityTaskManagerService里面,但真正走到update config之前,会有下面的code
if (values != null) { Settings.System.clearConfiguration(values); }
也就是会把通过Configuration设定进来的Locale设定清除(不清楚为什么这么设定)
/** * @hide Erase the fields in the Configuration that should be applied * by the settings. */ public static void clearConfiguration(Configuration inoutConfig) { inoutConfig.fontScale = 0; if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) { inoutConfig.clearLocales(); } }
因此,还需要再在frameworks/base/services/core/java/com/android/server/am/ActivityTaskManagerService.java中添加:
@Override public boolean updateConfiguration(Configuration values) { mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()"); ... final long origId = Binder.clearCallingIdentity(); try { //Add code BEGIN if(UPDATE_SIM_LANGUAGE){ boolean isDeviceProvisioned = Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; boolean setupCompleted = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE,0) != 0; if(isDeviceProvisioned || setupCompleted){ if (values != null) { Settings.System.clearConfiguration(values); } } }else { //保留原有 if (values != null) { Settings.System.clearConfiguration(values); } } //Add code END updateConfigurationLocked(values, null, false, false /* persistent */, UserHandle.USER_NULL, false /* deferResume */, mTmpUpdateConfigurationResult); return mTmpUpdateConfigurationResult.changes != 0; } finally { Binder.restoreCallingIdentity(origId); } } }
2. 如果想每次插入SIM卡都要切换成SIM卡语言,只需要把第一步里面关于isDeviceProvisioned和setupCompleted的判断拿掉就行,也就是每次插入SIM卡都会默认切换成SIM卡语言。
3. 如果只想SIM卡插入第一次才去切换,先把第一步的isDeviceProvisioned和setupCompleted的判断拿掉,再去判断Settings.System.SYSTEM_LOCALES是否已经包含当前SIM卡语言。
判断时候不要用mccLocale.toString(),会有zh-CN和zh_CN的差异,用mccLocale.getLanguage(),只去判断zh就好
WARNING:报BUG啦!
按照方法1修改代码后,功能可以实现,但是在Settings中设置startup security(开机启动需要解锁)的话,在开机到secure startup画面时,所有user setting不能被访问。
因此此时 Settings.Global.DEVICE_PROVISIONED 和Settings.Secure.USER_SETUP_COMPLETE读出来都是默认值!
因此需要再在Settings中CryptKeeper.java中去添加一个flag,activity start时候flag设为true,onDestroy时候清除flag。
这时在方法1添加判断的地方添加一个读Settings字段flag的功能,发现此时是secure startup时,切换语言的功能不要去执行!