Изменение языка не работает после перехода на Androidx
У меня есть старый проект, который поддерживает несколько языков. Я хочу обновить библиотеку поддержки и целевую платформу. До перехода на Androidx все работало нормально, но теперь смена языка не работает!
Я использую этот код для изменения локали приложения по умолчанию
private static Context updateResources(Context context, String language)
{
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
И вызывайте этот метод для каждого действия путем переопределения attachBaseContext
следующим образом:
@Override
protected void attachBaseContext(Context newBase)
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String language = preferences.getString(SELECTED_LANGUAGE, "fa");
super.attachBaseContext(updateResources(newBase, language));
}
Я стараюсь другой метод, чтобы получить строку, и я заметил, что getActivity().getBaseContext().getString
работы и getActivity().getString
не работает. Даже следующий код не работает и всегда показывает app_name
vlaue в ресурсе по умолчанию string.xml.
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
Я поделился примером кода в https://github.com/Freydoonk/LanguageTest
Также getActivity()..getResources().getIdentifier
не работает и всегда возвращает 0!
Ответы
Ответ 1
Наконец я нахожу проблему в своем приложении. При переносе проекта на Androidx зависимости моего проекта менялись так:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-alpha04'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
}
Как видно, версия androidx.appcompat:appcompat
1.1.0-alpha03
когда я изменил ее на последнюю стабильную версию 1.0.2
, моя проблема решена и язык изменения работает должным образом.
Я нахожу последнюю стабильную версию библиотеки appcompat в репозитории Maven. Я также изменяю другие библиотеки на последнюю стабильную версию.
Теперь мой раздел зависимостей приложения выглядит так:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
Ответ 2
В основном, что происходит в фоновом режиме, это то, что, если вы правильно установили конфигурацию в attachBaseContext
, AppCompatDelegateImpl
затем переходит и переопределяет конфигурацию в совершенно новую конфигурацию без локали:
final Configuration conf = new Configuration();
conf.uiMode = newNightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
try {
...
((android.view.ContextThemeWrapper) mHost).applyOverrideConfiguration(conf);
handled = true;
} catch (IllegalStateException e) {
...
}
В последнем (пока не выпущенном) коде это на самом деле исправлено: новая конфигурация является глубокой копией конфигурации базового контекста.
final Configuration conf = new Configuration(baseConfiguration);
conf.uiMode = newNightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
try {
...
((android.view.ContextThemeWrapper) mHost).applyOverrideConfiguration(conf);
handled = true;
} catch (IllegalStateException e) {
...
}
Пока это не будет выпущено, то же самое можно сделать вручную. Чтобы продолжить использовать версию 1.1.0, добавьте это ниже вашего attachBaseContext
:
Раствор Котлина
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
if (overrideConfiguration != null) {
val uiMode = overrideConfiguration.uiMode
overrideConfiguration.setTo(baseContext.resources.configuration)
overrideConfiguration.uiMode = uiMode
}
super.applyOverrideConfiguration(overrideConfiguration)
}
Java-решение
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (overrideConfiguration != null) {
int uiMode = overrideConfiguration.uiMode;
overrideConfiguration.setTo(getBaseContext().getResources().getConfiguration());
overrideConfiguration.uiMode = uiMode;
}
super.applyOverrideConfiguration(overrideConfiguration);
}
Этот код делает то же самое, что Configuration(baseConfiguration)
делает под капотом, но поскольку мы делаем это после того, как AppCompatDelegate
уже установил правильный uiMode
, мы должны убедиться, что переопределяем uiMode
после того, как мы это исправим, чтобы не потерять настройку темного/светлого режима.
Ответ 3
В новых библиотеках приложений, связанных с ночным режимом, существует проблема, которая приводит к переопределению конфигурации на Android с 21 по 25.
Это можно исправить, применив вашу конфигурацию при вызове этой общедоступной функции:
public void applyOverrideConfiguration (Конфигурация overrideConfiguration
Для меня этот маленький трюк сработал, скопировав настройки из переопределенной конфигурации в мою конфигурацию, но вы можете делать все, что захотите. Лучше повторно применить вашу языковую логику к новой конфигурации, чтобы минимизировать ошибки
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (Build.VERSION.SDK_INT >= 21&& Build.VERSION.SDK_INT <= 25) {
getResources().getConfiguration().setTo(overrideConfiguration);
}
super.applyOverrideConfiguration(getResources().getConfiguration());
}
Ответ 4
Теперь есть более новая версия, которая также работает:
implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
Как @Fred упомянул appcompat:1.1.0-alpha03
имеет сбой, хотя он не упоминается в журнале их appcompat:1.1.0-alpha03
версий
Ответ 5
Наконец, я получил решение для поиска, в моем случае проблема была с bundle apk
, потому что он разделил файлы поиска. В bundle apk
по умолчанию будут созданы все сплиты. но в блоке android вашего файла build.gradle
вы можете указать, какие разделы будут сгенерированы.
bundle {
language {
// Specifies that the app bundle should not support
// configuration APKs for language resources. These
// resources are instead packaged with each base and
// dynamic feature APK.
enableSplit = false
}
}
После добавления этого кода в блок android файла build.gradle
моя проблема была решена.
Ответ 6
Была такая же ошибка на androidx.appcompat:appcompat:1.1.0
. Переключился на androidx.appcompat:appcompat:1.1.0-rc01
и теперь меняются langs на Android 5-6.
Ответ 7
1. Метод, который вы можете использовать в attachBaseContext()
private void setLanguage(Context mContext, String localeName) {
Locale myLocale = new Locale(localeName);
Resources res = mContext.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
}
2. Переопределить в деятельности
@Override
protected void attachBaseContext(Context newBase) {
setLanguage(newBase, "your language");
super.attachBaseContext(newBase);
}
NB: Это нормально работает после того, как я воссоздаю упражнение