Android: установка языкового стандарта программным способом изменяет контекст - PullRequest
0 голосов
/ 01 февраля 2019

Я знаю, что есть много дискуссий на эту тему, и я сделал свою домашнюю работу и ранее прочитал много сообщений stackoverflow, но ни один из них, кажется, не решил мою проблему.

У меня есть функция setLocale, которая запускается накаждое действие onCreate (не уверен, что это лучший способ сделать это, но это то, как я это делаю прямо сейчас) и setLocale создает и возвращает новый контекст с примененной настройкой пользовательской локали, и это работает (когда вы вызываете getString текст вправильный язык возвращается), но дело в том, что этот новый контекст (context = context.createConfigurationContext (config) в setLocale) имеет тип ContextImpl? , и я ожидаю, что это будет Activity, которая называетсяsetLocale, потому что я затем запускаю методы, которым нужно действие в контексте (контекст типа деятельности), но так как оно ContextImpl, я получаю «Невозможно привести android.app.ContextImpl к Activity».Это понятно?Любая помощь?

Спасибо.

public static Context setLocale(Context context, String language) {

        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }

        return context;
    }

Редактировать 1: Один хороший подход.

Если я вставлю следующий фрагмент кода в свою деятельность SplashScreen:

Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = getBaseContext().getResources().getConfiguration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
        getBaseContext().getResources().getDisplayMetrics());

Тогда языковой стандарт работает вместе со всем приложением, но я знаю, UpdateConfiguration устарела , и я пытаюсь использовать новый формат, который может быть:

public static Context updateResources(Context context, String language) {

        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT <= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }

        return context;
    }

Но сэтот второй обновленный подход не работает, какие-либо предложения?

1 Ответ

0 голосов
/ 02 февраля 2019

После долгих исследований я отвечу себе тем, что пришел к выводу, что это оптимальное (и современное) решение для глобальной языковой настройки текущим способом.

Я создал класс ContextWrapper следующим образом:

import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Build;

import com.testmepracticetool.toeflsatactexamprep.helpers.TMLocale;

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 = TMLocale.getLocale(context);

        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));
}

Это должно быть вставлено вкаждое действие, кроме того, что я в итоге сделал, чтобы сделать его еще проще и лучше, - это создание класса BaseActivity, и каждое действие расширяет его.

Таким образом, мы устанавливаем язык в актуальном и предпочтительном порядке иэто работает, когда вы делаете getString, правильный язык выбран.

Надеюсь, что мое расследование поможет кому-то еще с такой же проблемой.

...