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 будет по-прежнему отображаться с английским контентом на устройстве, настроенном на любую не французскую локаль