web-dev-qa-db-ja.com

Android context.getResources.updateConfiguration()は非推奨

ちょうど最近context.getResources(). pdateConfiguration() はAndroid AP​​I 25で非推奨になりました。コンテキストを使用することをお勧めします。 createConfigurationContext()

createConfigurationContext を使用してAndroidシステムロケールをオーバーライドする方法を知っている人はいますか?

これが行われる前に:

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

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

    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.JELLY_BEAN_MR1) {
             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"));
}

UPDATE 10/19/2018時々、向きの変更、またはアクティビティの一時停止/再開後に、構成オブジェクトがデフォルトのシステム構成にリセットされ、結果としてアプリが表示されますコンテキストをフランス語の「fr」ロケールでラップしていても、英語の「en」テキストを表示します。したがって、ベストプラクティスとして、アクティビティまたはフラグメントのグローバル変数にContext/Activityオブジェクトを保持しないでください。

さらに、MyBaseFragmentまたはMyBaseActivityで次を作成して使用します。

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

このプラクティスは、100%バグのないソリューションを提供します。

89
Bassel Mourjan

おそらくこのように:

Configuration overrideConfiguration = getBaseContext().getResources().getConfiguration();
overrideConfiguration.setLocales(LocaleList);
Context context  = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();

ボーナス: createConfigurationContext()を使用するブログ記事

21
compte14031879

書道とムルジャンと私に触発され、私はこれを作成しました。

最初に、アプリケーションのサブクラスを作成する必要があります。

public class MyApplication extends Application {
    private Locale locale = null;

    @Override
    public void onCreate() {
        super.onCreate();

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);

        Configuration config = getBaseContext().getResources().getConfiguration();

        String lang = preferences.getString(getString(R.string.pref_locale), "en");
        String systemLocale = getSystemLocale(config).getLanguage();
        if (!"".equals(lang) && !systemLocale.equals(lang)) {
            locale = new Locale(lang);
            Locale.setDefault(locale);
            setSystemLocale(config, locale);
            updateConfiguration(config);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (locale != null) {
            setSystemLocale(newConfig, locale);
            Locale.setDefault(locale);
            updateConfiguration(newConfig);
        }
    }

    @SuppressWarnings("deprecation")
    private static Locale getSystemLocale(Configuration config) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return config.getLocales().get(0);
        } else {
            return config.locale;
        }
    }

    @SuppressWarnings("deprecation")
    private static void setSystemLocale(Configuration config, Locale locale) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            config.setLocale(locale);
        } else {
            config.locale = locale;
        }
    }

    @SuppressWarnings("deprecation")
    private void updateConfiguration(Configuration config) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            getBaseContext().createConfigurationContext(config);
        } else {
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
        }
    }
}

次に、これをAndroidManifest.xmlアプリケーションタグに設定する必要があります。

<application
    ...
    Android:name="path.to.your.package.MyApplication"
    >

これをAndroidManifest.xmlアクティビティタグに追加します。

<activity
    ...
    Android:configChanges="locale"
    >

pref_localeは次のような文字列リソースであることに注意してください。

<string name="pref_locale">fa</string>

pref_localeが設定されていない場合、ハードコード「en」はデフォルトのlangです

3
Mahpooya

コトリンの長所を備えた@ bassel-mourjanのソリューションは次のとおりです。

import Android.annotation.TargetApi
import Android.content.ContextWrapper
import Android.os.Build
import Java.util.*

@Suppress("DEPRECATION")
fun ContextWrapper.wrap(language: String): ContextWrapper {
    val config = baseContext.resources.configuration
    val sysLocale: Locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        this.getSystemLocale()
    } else {
        this.getSystemLocaleLegacy()
    }

    if (!language.isEmpty() && sysLocale.language != language) {
        val locale = Locale(language)
        Locale.setDefault(locale)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            this.setSystemLocale(locale)
        } else {
            this.setSystemLocaleLegacy(locale)
        }
    }

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        val context = baseContext.createConfigurationContext(config)
        ContextWrapper(context)
    } else {
        baseContext.resources.updateConfiguration(config, baseContext.resources.displayMetrics)
        ContextWrapper(baseContext)
    }

}

@Suppress("DEPRECATION")
fun ContextWrapper.getSystemLocaleLegacy(): Locale {
    val config = baseContext.resources.configuration
    return config.locale
}

@TargetApi(Build.VERSION_CODES.N)
fun ContextWrapper.getSystemLocale(): Locale {
    val config = baseContext.resources.configuration
    return config.locales[0]
}


@Suppress("DEPRECATION")
fun ContextWrapper.setSystemLocaleLegacy(locale: Locale) {
    val config = baseContext.resources.configuration
    config.locale = locale
}

@TargetApi(Build.VERSION_CODES.N)
fun ContextWrapper.setSystemLocale(locale: Locale) {
    val config = baseContext.resources.configuration
    config.setLocale(locale)
}

そして、これがあなたの使い方です:

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(ContextWrapper(newBase).wrap(defaultLocale.language))
}
1
Michael

これを試して:

Configuration config = getBaseContext().getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
0
Eric B.

contextWrapperを使用した簡単なソリューションがここにあります。 Android Nはプログラムで言語を変更します recreate()メソッドに注意

0