Android 6/7系统不加载自定义英文strings.xml问题咨询
你的问题很典型——同样的语言切换代码在Android 8+正常生效,却在6/7系统完全失效,核心原因是不同Android版本对资源配置更新的处理逻辑存在差异,具体拆解如下:
问题根源
低版本资源配置更新的范围局限性
在Android 7.0(API 24)及以下,你调用getBaseContext().getResources().updateConfiguration()只会更新BaseContext的资源配置,但当前Activity自身的Resources对象可能还缓存着旧的Locale配置。当你调用recreate()重建Activity时,系统可能还是用旧配置初始化新实例,导致文本无法更新。默认Locale的同步问题
虽然你设置了Locale.setDefault(locale),但在低版本系统中,部分资源加载逻辑不会实时读取这个新的默认值,尤其是Activity重建时,系统可能优先使用系统全局Locale而非你设置的自定义默认值。
修复方案
1. 全面更新资源配置
不要只更新BaseContext的资源,同时覆盖当前Activity和Application的资源配置,确保所有Context都使用新的Locale:
private void saveLang(String lng) { Locale locale = new Locale(lng); Locale.setDefault(locale); // 更新当前Activity的Resources Resources activityRes = getResources(); Configuration activityConfig = activityRes.getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { activityConfig.setLocale(locale); } else { activityConfig.locale = locale; } activityRes.updateConfiguration(activityConfig, activityRes.getDisplayMetrics()); // 更新Application的Resources(确保全局生效) Resources appRes = getApplicationContext().getResources(); Configuration appConfig = appRes.getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { appConfig.setLocale(locale); } else { appConfig.locale = locale; } appRes.updateConfiguration(appConfig, appRes.getDisplayMetrics()); recreate(); }
2. 持久化语言设置并在启动时恢复
系统重启或应用被杀后,语言设置会被重置,所以需要把用户选择的语言存在SharedPreferences里,然后在Application的onCreate()中提前应用:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); restoreSavedLanguage(); } private void restoreSavedLanguage() { SharedPreferences prefs = getSharedPreferences("app_settings", MODE_PRIVATE); String selectedLang = prefs.getString("selected_language", "en"); // 默认英文 Locale locale = new Locale(selectedLang); Locale.setDefault(locale); Resources res = getResources(); Configuration config = res.getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { config.setLocale(locale); } else { config.locale = locale; } res.updateConfiguration(config, res.getDisplayMetrics()); } }
记得在saveLang()方法里同步把选择的语言保存到SharedPreferences中。
3. 替换recreate()为显式重启(低版本可选)
如果recreate()在低版本仍然不生效,可以用Intent重启当前Activity,彻底刷新资源:
// 替换原有的super.recreate(); Intent intent = getIntent(); finish(); startActivity(intent); overridePendingTransition(0, 0); // 去掉过渡动画,避免视觉闪烁
补充说明
Android 8.0(API 26)之后,系统对资源配置更新的逻辑做了优化,updateConfiguration的行为更统一,同时Configuration.setLocale()的兼容性更好,所以你的原始代码在高版本能正常工作。另外,尽量避免直接使用已弃用的config.locale,通过版本分支处理来适配全版本。
内容的提问来源于stack exchange,提问作者Darksymphony

