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時,切換語言的功能不要去執行!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM