Android N以编程方式更改语言

我发现很奇怪的错误,只在Android N设备上复制。

在浏览我的应用程序时,可能会改变语言。 这是改变它的代码。

public void update(Locale locale) { Locale.setDefault(locale); Configuration configuration = res.getConfiguration(); if (BuildUtils.isAtLeast24Api()) { LocaleList localeList = new LocaleList(locale); LocaleList.setDefault(localeList); configuration.setLocales(localeList); configuration.setLocale(locale); } else if (BuildUtils.isAtLeast17Api()){ configuration.setLocale(locale); } else { configuration.locale = locale; } res.updateConfiguration(configuration, res.getDisplayMetrics()); } 

这段代码在我的游览活动( recreate()调用)中起作用,但是在所有的下一个活动中,所有的String资源都是错误的。 屏幕旋转修复它。 我可以怎样解决这个问题? 我应该改变区域为Android N不同或它只是系统错误?

PS这是我发现的。 在MainActivity的第一次启动(这是我的巡视之后) Locale.getDefault()是正确的,但资源是错误的。 但在其他活动中,它给了我错误的语言环境和本地区的错误资源。 旋转屏幕后(或者其他一些configuration更改) Locale.getDefault()是正确的。

  • 在Android N多窗口模式下按下主页button时,未调用Activity onStop()
  • Android PackageStats提供负值
  • Android N Display Size设置为“Small”时,“Canvas:试图绘制太大的位图”
  • Android N无法在应用程序结算AIDL中编译
  • Html标签处理程序没有在Android N中调用“ul”,“li”
  • Android N中无法使用SecureRandom提供程序“Crypto”来确定生成密钥
  • 检测Android N版本代码
  • Eclipse - 使用Android 7清空Logcat
  • 好。 最后我设法find了一个解决scheme。

    首先,您应该知道在25个API中,不build议使用.updateConfiguration Resources.updateConfiguration(...) 。 所以,你可以做这样的事情:

    1)您需要创build自己的ContextWrapper,它将覆盖baseContext中的所有configuration参数。 例如,这是我的ContextWrapper正确更改区域设置。 注意context.createConfigurationContext(configuration)方法。

     public class ContextWrapper extends android.content.ContextWrapper { public ContextWrapper(Context base) { super(base); } public static ContextWrapper wrap(Context context, Locale newLocale) { Resources res = context.getResources(); Configuration configuration = res.getConfiguration(); if (BuildUtils.isAtLeast24Api()) { configuration.setLocale(newLocale); LocaleList localeList = new LocaleList(newLocale); LocaleList.setDefault(localeList); configuration.setLocales(localeList); context = context.createConfigurationContext(configuration); } else if (BuildUtils.isAtLeast17Api()) { configuration.setLocale(newLocale); context = context.createConfigurationContext(configuration); } else { configuration.locale = newLocale; res.updateConfiguration(configuration, res.getDisplayMetrics()); } return new ContextWrapper(context); }} 

    2)以下是您应该在BaseActivity中执行的操作:

      @Override protected void attachBaseContext(Context newBase) { Locale newLocale; // .. create or get your new Locale object here. Context context = ContextWrapper.wrap(newBase, newLocale); super.attachBaseContext(context); } 

    记住要重新创build你的活动,如果你想改变你的应用程序的地方的地方。 您可以覆盖使用此解决scheme的任何configuration。

    受各种代码的启发(即:我们的Stackoverflow兄弟(喊出男孩)),我已经制作了一个更简单的版本。 ContextWrapper扩展是不必要的。

    首先让我们假设你有2个button,用于2种语言,EN和KH。 在onClickbutton中将语言代码保存到SharedPreferences ,然后调用activity的recreate()方法。

    例:

     @Override public void onClick(View v) { switch(v.getId()) { case R.id.btn_lang_en: //save "en" to SharedPref here break; case R.id.btn_lang_kh: //save "kh" to SharedPref here break; default: break; } getActivity().recreate(); } 

    然后创build一个返回ContextWrapper的静态方法,也许在一个Utils类中(这就是我所做的,lul)。

     public static ContextWrapper changeLang(Context context, String lang_code){ Locale sysLocale; Resources rs = context.getResources(); Configuration config = rs.getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { sysLocale = config.getLocales().get(0); } else { sysLocale = config.locale; } if (!lang_code.equals("") && !sysLocale.getLanguage().equals(lang_code)) { Locale locale = new Locale(lang_code); Locale.setDefault(locale); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { config.setLocale(locale); } else { config.locale = locale; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { context = context.createConfigurationContext(config); } else { context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); } } return new ContextWrapper(context); } 

    最后,在ALL ACTIVITY的 attachBaseContext(Context newBase)方法中从SharedPreferences中加载语言代码。

     @Override protected void attachBaseContext(Context newBase) { String lang_code = "en"; //load it from SharedPref Context context = Utils.changeLang(newBase, lang_code); super.attachBaseContext(context); } 

    奖金:为了节省键盘上的手掌汗水,我创build了一个LangSupportBaseActivity类来扩展Activity并使用最后一块代码。 而且我还有其他所有活动扩展了LangSupportBaseActivity

    例:

     public class LangSupportBaseActivity extends Activity{ ...blab blab blab so on and so forth lines of neccessary code @Override protected void attachBaseContext(Context newBase) { String lang_code = "en"; //load it from SharedPref Context context = Utils.changeLang(newBase, lang_code); super.attachBaseContext(context); } } public class HomeActivity extends LangSupportBaseActivity{ ...blab blab blab }