1. ホーム
  2. android

[解決済み] Android context.getResources.updateConfiguration() deprecated

2022-11-28 08:43:53

質問

つい最近、context.getResources(). updateConfiguration() は Android API 25 で非推奨となり、context.getResources() を使うことが推奨されています。 createConfigurationContext() を使うことをお勧めします。

どなたか、どのように createConfigurationContext はアンドロイドのシステムロケールを上書きするために使うことができるのか?

によって行われるであろう前に。

Configuration config = getBaseContext().getResources().getConfiguration();
config.setLocale(locale);
context.getResources().updateConfiguration(config,
                                 context.getResources().getDisplayMetrics());

どのように解決するのですか?

インスピレーション カリグラフィー に触発され、コンテキストラッパーを作成することにしました。 私の場合、アプリの言語を変更するオプションをユーザーに提供するために、システム言語を上書きする必要がありますが、これはあなたが実装する必要がある任意のロジックでカスタマイズすることが可能です。

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.ContextWrapper;
    import android.content.res.Configuration;
    import android.os.Build;
    
    import java.util.Locale;
    
    public class MyContextWrapper extends ContextWrapper {

    public MyContextWrapper(Context base) {
        super(base);
    }

    @SuppressWarnings("deprecation")
    public static ContextWrapper wrap(Context context, String language) {
        Configuration config = context.getResources().getConfiguration();
        Locale sysLocale = null;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            sysLocale = getSystemLocale(config);
        } else {
            sysLocale = getSystemLocaleLegacy(config);
        }
        if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                setSystemLocale(config, locale);
            } else {
                setSystemLocaleLegacy(config, locale);
            }
            
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             context = context.createConfigurationContext(config);
        } else {
             context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
            }
        return new MyContextWrapper(context);
    }

    @SuppressWarnings("deprecation")
    public static Locale getSystemLocaleLegacy(Configuration config){
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static Locale getSystemLocale(Configuration config){
        return config.getLocales().get(0);
    }

    @SuppressWarnings("deprecation")
    public static void setSystemLocaleLegacy(Configuration config, Locale locale){
        config.locale = locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static void setSystemLocale(Configuration config, Locale locale){
        config.setLocale(locale);
    }
}

で、ラッパーを注入するために、各アクティビティに以下のコードを追加してください。

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(MyContextWrapper.wrap(newBase,"fr"));
}

更新日:2020年12月22日 androidのMaterialライブラリのContextThemeWrapperの実装でダークモードをサポートした後、言語設定が壊れて言語設定が失われることがありました。数ヶ月間頭を悩ませましたが、ActivityとFragmentのonCreateメソッドに以下のコードを追加することで問題は解決しました。

Context context = MyContextWrapper.wrap(this/*in fragment use getContext() instead of this*/, "fr");
   getResources().updateConfiguration(context.getResources().getConfiguration(), context.getResources().getDisplayMetrics());

2018/10/19更新 向きを変更したり、アクティビティを一時停止/再開すると、Configuration オブジェクトがデフォルトのシステム構成にリセットされ、その結果、フランス語 "fr" ロケールでコンテキストをラップしたにもかかわらず、アプリで英語 "en" テキストが表示されることがあります。したがって、グッドプラクティスとして、アクティビティやフラグメントのグローバル変数に Context/Activity オブジェクトを保持しないようにしてください。

さらに、MyBaseFragmentやMyBaseActivityの中で以下を作成し、使用してください。

public Context getMyContext(){
    return MyContextWrapper.wrap(getContext(),"fr");
}

この練習は100%バグのない解決策を提供します。