android13(T) 客制化预置语言列表
效果图
需求分析
这个列表界面一般都是后来手动添加后才现实的,通过分析源码发现通过如下值可控
adb shell settings get system system_locales
zh-CN,ja-JP,en-AT
所以只需查询出这个值,然后加在 SettingProvider 中即可
隐藏 bug
如果客户要求默认语言为 en-AT,且客制列表顺序如上显示,通过之前惯用设置语言反射接口设置后,
有bug版本接口 使用 updateConfiguration
public void changeSystemLanguage(Locale locale) {//Locale.ENGLISH
try {
Object objIActMag, objActMagNative;
Class clzIActMag = Class.forName("android.app.IActivityManager");
Class clzActMagNative = Class.forName("android.app.ActivityManagerNative");
Method mtdActMagNative$getDefault = clzActMagNative.getDeclaredMethod("getDefault");
objIActMag = mtdActMagNative$getDefault.invoke(clzActMagNative);
Method getConfiguration = clzIActMag.getDeclaredMethod("getConfiguration");
Configuration config = (Configuration) getConfiguration.invoke(objIActMag);
config.locale = locale;
Class clzConfig = Class.forName("android.content.res.Configuration");
java.lang.reflect.Field userSetLocale = clzConfig.getField("userSetLocale");
userSetLocale.set(config, true);
Class[] clzParams = {Configuration.class};
Method mtdIActMag$updateConfiguration = clzIActMag.getDeclaredMethod("updateConfiguration", clzParams);
mtdIActMag$updateConfiguration.invoke(objIActMag, config);
BackupManager.dataChanged("com.android.providers.settings");
} catch (Exception e) {
e.printStackTrace();
}
}
首次开机预置语言列表将不显示,重启一次后才会正确显示。经过分析是设置语言接口的锅,
替换新方法即可解决
正常版本接口 使用 updatePersistentConfiguration
private LocaleList makeLocalListData(Context mContext, String locale) {
// String defaultConfig = "zh-CN,ja-JP,en-AT";
String defaultConfig = Settings.System.getString(mContext.getContentResolver(),"system_locales");
String[] split = defaultConfig.split(",");
int index=0;
String newConfig = "";
for (int i = 0; i < split.length; i++) {
if (split[i].contains(locale)) {
index = i;
newConfig = split[i];
break;
}
}
for (int i = 0; i < split.length; i++) {
if (i == index) {
continue;
}
newConfig = newConfig.concat(","+split[i]);
}
return LocaleList.forLanguageTags(newConfig);
}
public void changeSystemLocales(Context mContext, String locale) {
try {
LocaleList localeList = makeLocalListData(mContext, locale);
Class iActivityManager = Class.forName("android.app.IActivityManager");
Class activityManagerNative = Class.forName("android.app.ActivityManagerNative");
Method getDefault = activityManagerNative.getDeclaredMethod("getDefault");
Object objIActMag = getDefault.invoke(activityManagerNative);
Method getConfiguration = iActivityManager.getDeclaredMethod("getConfiguration");
Configuration config = (Configuration) getConfiguration.invoke(objIActMag);
config.setLocales(localeList);
Class clzConfig = Class.forName("android.content.res.Configuration");
java.lang.reflect.Field userSetLocale = clzConfig.getField("userSetLocale");
userSetLocale.set(config, true);
Class[] clzParams = {Configuration.class};
Method updateConfiguration = iActivityManager.getDeclaredMethod("updatePersistentConfiguration", clzParams);
updateConfiguration.invoke(objIActMag, config);
BackupManager.dataChanged("com.android.providers.settings");
} catch (Exception e) {
e.printStackTrace();
}
}