Force locale для аромата Android с помощью resConfig

Я пытаюсь использовать resConfig и resConfigs из системы Android Build.

  • Android Studio версия 1.2.2
  • Gradle build version 1.2.3
  • OSX 10.10.3

У меня были проблемы с этими двумя вариантами в моем проекте, поэтому я запустил новый пустой проект с Android Studio. Я прикрепил свой build.gradle, где я только добавил resConfigs "en", "fr" под

android { 
   defaultConfig {
        ...
        resConfigs "en", "fr" 
        ...
   }
}

И определены 2 основных вкуса

productFlavors {
        fr {
            resConfig "fr"
        }

        en {
            resConfig "en"
        }
}

Затем я создал 2 файла strings.xml и перевел метку hello_world по умолчанию

/src/main/res/values/strings.xml (по умолчанию)
/src/main/res/values-en/strings.xml
/src/main/res/values-fr/strings.xml

При этом я ожидаю увидеть только 3 папки значений в MyApplication/app/builds/ промежуточные / res / en / debug, так как я определил в resConfigs использовать только "en" и "fr" и фильтровать все остальное

/ценности/
/ значение-о /
/ Значения-FR /

Хотя папка значений всех языков все еще там, так что resConfigs ничего не фильтрует, очевидно.

Я также ожидал бы увидеть метку hello_world из values-en при запуске варианта оформления enDebug, поскольку я указал, что аромат en будет использовать resConfig "en", хотя при запуске тестового приложения я вижу метку из / values-fr / strings. xml вместо /values-en/strings.xml, поскольку язык на планшете настроен как французский Канада

Я неправильно понимаю цель, стоящую за resConfig? Если это так, как я должен заставить исполнение работать только на одном языке и не зависеть от настроек локали ОС? Это решение должно быть совместимо и с flavourDimensions, поскольку я использую их в реальном приложении, которое пытаюсь настроить.

ПРИМЕЧАНИЕ. Я также подал сообщение об ошибке, поскольку считаю, что с этим поведением resConfig действительно существует проблема https://code.google.com/p/android/issues/detail?id=180694

Спасибо

2 ответа

Решение

Что ж, спустя много часов, вот решение моей проблемы для тех, кто столкнулся с той же проблемой.

Оказывается, что ResConfig не для того, что я, хотя. Правильный и единственный способ заставить локаль для конкретного аромата выглядит так:

Во-первых, убедитесь, что все ваши действия распространяются на общую деятельность, которая будет отвечать за форсирование локали. (Мне пришлось создать 2, так как у меня есть некоторые действия, расширяющие FragmentActivity и некоторые расширяющие Activity. Мне также не очень нравится делать это в конструкторе Activity, но, поскольку мне приходится вызывать applyOverrideConfiguration перед выполнением любого вызова getResources, мне нужно вызвать это до начала действия).

public class LocaleMainActivity extends Activity {

    public LocaleMainActivity() {
        ActivityUtils.forceLocale(this);
    }
}

public class LocaleMainFragmentActivity extends FragmentActivity {

    public LocaleMainFragmentActivity() {
        ActivityUtils.forceLocale(this);
    }
}

//Method from ActivityUtils
public static void forceLocale(ContextThemeWrapper contextThemeWrapper) {
    Configuration configuration = new Configuration();
    Locale defaultLocale = new Locale(BuildConfig.LOCALE);
    configuration.locale = defaultLocale;
    contextThemeWrapper.applyOverrideConfiguration(configuration);      
}

Далее вам нужно определить локаль в ваших вариантах build.gradle

productFlavors {

    myFrenchFlavor {
     buildConfigField "String", "LOCALE", "\"fr\""
    }
    myEnglishFlavor {
      buildConfigField "String", "LOCALE", "\"en\""
    }
}

Я тестировал решение на API 19+. Работает, когда вы меняете язык в приложении.



Альтернативное решение (не работает на Android M+, см. Отчет об ошибках Android) Это решение широко распространено на stackOverflow, но я столкнулся со стеной при реализации этого на Android M, так что имейте это в виду.

В onCreate() вашего AndroidApplication вы можете вызвать updateConfiguration с установленным языковым стандартом.

Locale myLocale = new Locale(BuildConfig.LOCALE);
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());

Вам также нужно будет сбросить его, если вы определили onConfigurationChanged()

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);            
        Configuration config = new Configuration(newConfig);
        config.locale = new Locale(BuildConfig.LOCALE);
        getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
    }

РЕДАКТИРОВАТЬ: Имейте в виду, что этот applyOverrideConfiguration в настоящее время имеет побочный эффект, который объясняется здесь. Веб-представление Chromium, похоже, не работает с Android applyOverrideConfiguration. Команда Chromium в настоящее время работает над этим!

Благодарю.

resConfig не переопределяет указанное resConfigs из defaultConfig, но просто объединяет их вместо. Таким образом, вы получите все ароматы, содержащие en а также fr Ресурсы.

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

Кроме того, приложение всегда будет включать в себя по умолчанию values, что означает, что если у вас есть английские строки там, fr flavor будет по-прежнему отображаться с английским контентом на устройстве, настроенном на любую не французскую локаль

Другие вопросы по тегам