Intereting Posts
NotSerializableException при нажатии кнопки «домой» Как нарисовать растровое изображение с использованием другого растрового изображения в качестве маски? Удалить строку между настраиваемыми пунктами меню TransactionTooLargeException при запуске нового действия Эмуляция Samsung Galaxy S2 Получите первый понедельник после определенной даты? Фоновая частичная параллельная развертка метки GC Как импортировать файлы в sdcard на эмуляторе в Android? Диалог пользовательских предупреждений не центрирован по вертикали на Android Запустить приложение Android без основной активности и запустить службу при запуске приложения Получить время разных часовых поясов при выборе времени из таймера ImageView adjustViewBounds не работает с Relative Layout Как собственный код Android может работать с несколькими типами процессоров? Как обнаружить утечку памяти Appcompat / добавить библиотеку с Android-студией

Android – Язык WebView внезапно меняется на Android N

У меня есть многоязычное приложение с основным языковым английским и арабским языками.

Как описано в документации ,

  • Я добавил android:supportsRtl="true" в манифесте.
  • Я изменил все свойства xml с left и right атрибутами для start и end соответственно.
  • Я добавил строки арабского языка в strings-ar (и аналогично для других ресурсов).

Вышеуказанная настройка работает правильно. После изменения Locale в ar-AE арабский текст и ресурсы отображаются правильно в моих действиях.

Тем не менее, каждый раз, когда я WebView к Activity с помощью WebView и / или WebViewClient , язык, текст и расположение макета резко возвращаются к устройству по умолчанию.

Дальнейшие подсказки:

  • Это происходит только на Nexus 6P с Android 7.0 . Все работает правильно на Android 6.0.1 и ниже.
  • Резкий сдвиг в локали происходит только тогда, когда я WebView к Activity , у которого есть WebView и / или WebViewClient (и у меня их несколько). Это не происходит ни в одной из других Деяний.

Android 7.0 поддерживает многоязычность, позволяя пользователю устанавливать более одного стандарта по умолчанию. Поэтому, если я установил основной язык в Locale.UK :

Введите описание изображения здесь

Затем при переходе к WebView локаль изменяется с ar-AE на en-GB .

Изменения API Android 7.0:

Как указано в списке изменений API , в API 24 были добавлены новые методы, относящиеся к языку:

Locale :

  • Locale.getDefault(...)
  • Locale.setDefault(...)

Configuration :

  • getLocales()
  • setLocales(...)

Тем не менее, я создаю свое приложение с API 23 и не использую ни один из этих новых методов.

Более того …

  • Проблема возникает и на эмуляторе Nexus 6P.

  • Чтобы получить стандартную локаль, я использую Locale.getDefault() .

  • Чтобы установить языковой стандарт по умолчанию, я использую следующий код:

     public static void setLocale(Locale locale){ Locale.setDefault(locale); Configuration config = new Configuration(); config.setLocale(locale); Context context = MyApplication.getInstance(); context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); } 

Кто-нибудь сталкивался с этой проблемой раньше? В чем причина этого и как я могу это решить?

Рекомендации:

1. Поддержка родной RTL в Android 4.2 .

2. Многоязычная поддержка – язык и локаль .

3. Будьте осторожны с языковым стандартом по умолчанию .

    Ответ Тедда Хоппа удалось решить проблему, но он не затронул вопрос о том, почему это происходит.

    Причина заключается в изменениях, внесенных в класс Webview и его пакет поддержки в Android 7.0.

    Задний план:

    WebView приложение Android построено с использованием webkit . Хотя он изначально был частью AOSP, начиная с KitKat, было принято решение WebView в отдельный компонент под названием Android System WebView . Это, по сути, системное приложение Android, которое поставляется с предустановленными устройствами Android. Он периодически обновляется, как и другие системные приложения, такие как Google Play Services и приложение Play Store. Вы можете увидеть его в списке установленных системных приложений:

    Android-система WebView

    Изменения Android 7.0 :

    Начиная с Android N, приложение Chrome будет использоваться для рендеринга любых / всех WebView в сторонних приложениях Android. В телефонах, у которых есть Android N из коробки, приложение Android WebView System отсутствует вообще. В устройствах, получивших обновление OTA для Android N, система Android WebView отключена:

    Отключен WebView

    а также

    Отключен WebView

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

    Введите описание изображения здесь

    Это имеет важное значение для приложений с несколькими языками. Если ваше приложение имеет WebView , то они отображаются с помощью приложения Chrome. Поскольку Chrome – это приложение Android, которое работает в своем изолированном процессе, оно не будет привязано к языку, установленному вашим приложением. Вместо этого Chrome вернется к основному языку устройства. Например, скажем, что в вашем локали приложения установлено значение ar-AE , а основной язык устройства – en-US . В этом случае локаль Activity содержащего WebView , изменится с ar-AE на en-US , а строки и ресурсы из соответствующих папок локали будут отображаться. Вы можете увидеть mish-mash строк и ресурсов LTR и RTL для этих Activity s, которые имеют WebView .

    Решение:

    Полное решение этой проблемы состоит из двух шагов:

    ШАГ 1:

    Во-первых, сбросьте локаль по умолчанию вручную в каждой Activity или, по крайней мере, для каждого Activity , у которого есть WebView .

     public static void setLocale(Locale locale){ Locale.setDefault(locale); Context context = MusafirApplication.getInstance(); final Resources resources = context.getResources(); final Configuration config = resources.getConfiguration(); config.setLocale(locale); context.getResources().updateConfiguration(config, resources.getDisplayMetrics()); } 

    Вызовите вышеуказанный метод перед вызовом setContentView(...) в onCreate() всех ваших действий. Параметр locale должен быть установленным по умолчанию Locale . Например, если вы хотите установить арабский язык / ОАЭ в качестве языкового стандарта по умолчанию, вы должны передать new Locale("ar", "AE") . Или, если вы хотите установить локаль по умолчанию (то есть Locale которая автоматически устанавливается операционной системой), вы должны передать Locale.US .

    ШАГ 2:

    Кроме того, вам необходимо добавить следующую строку кода:

     new WebView(this).destroy(); 

    В onCreate() вашего класса Application (если он у вас есть), и где бы еще пользователь не мог менять язык. Это позаботится обо всех случаях, которые могут возникнуть при перезагрузке приложения после изменения языка (вы могли заметить строки на других языках или с противоположным выравниванием после изменения языка в Activities , имеющих WebView на Android 7.0 ++) ,

    В качестве добавления пользовательские вкладки Chrome теперь являются предпочтительным способом рендеринга веб-страниц в приложении.

    Рекомендации:

    1. Android 7.0 – изменения для WebView .

    2. Понимание патчей безопасности WebView и Android .

    3. WebView для Android .

    4. WebView: от «Работает на Chrome», чтобы настроить Chrome .

    5. Nougat WebView .

    6. Android 7.0 Нуга .

    7. Android N Mysteries, часть 1: Android-система WebView теперь просто «Chrome»? ,

    Кажется, что ваш код устанавливает локаль в конфигурации самого приложения ( MyApplication.getInstance() ). Однако вам необходимо обновить конфигурацию контекста активности до раздувания содержимого контента активности. Я обнаружил, что изменить контекст приложения недостаточно (и, как оказалось, даже не нужно). Если я не обновляю каждый контекст действия, то поведение несовместимо с действиями.

    Я AppCompatActivity к этому подклассу AppCompatActivity (или Activity , если не использовать библиотеку совместимости), а затем выводит все мои классы активности из этого подкласса. Вот упрощенная версия моего кода:

     public class LocaleSensitiveActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { Locale locale = ... // the locale to use for this activity fixupLocale(this, locale); super.onCreate(savedInstanceState); ... } static void fixupLocale(Context ctx, Locale newLocale) { final Resources res = ctx.getResources(); final Configuration config = res.getConfiguration(); final Locale curLocale = getLocale(config); if (!curLocale.equals(newLocale)) { Locale.setDefault(newLocale); final Configuration conf = new Configuration(config); conf.setLocale(newLocale); res.updateConfiguration(conf, res.getDisplayMetrics()); } } private static Locale getLocale(Configuration config) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return config.getLocales().get(0); } else { //noinspection deprecation return config.locale; } } } 

    Затем я вызываю вызов super.onCreate(savedInstanceState) в каждом onCreate() подкласса перед вызовом любых методов (например, setContentView() ), которые используют контекст.

    Ни один из ответов выше не помог мне, мне удалось снова восстановить локализацию приложения внутри метода onStop () активности, содержащей Webview

    Я хочу добавить еще один прецедент :

    При возврате из активности веб-просмотра (т. Е. Отображение экрана платежа и нажатия кнопки пользователя), onCreate () предыдущей активности не выполняется, чтобы язык снова был сброшен. Чтобы это не было ошибкой, мы должны сбросить локализацию приложения в onResume() базовой активности.

     private static void updateResources(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration config = new Configuration(); config.setLocale(locale); config.setLayoutDirection(locale); context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); } 

    Вызовите метод выше в onResume () базовой активности или по крайней мере в активности веб-просмотра.

    В Android N, когда вы new WebView() , он добавит /system/app/WebViewGoogle/WebViewGoogle.apk к пути к ресурсам, и если он не добавлен к пути, это приведет к восстановлению ресурса.

    Поэтому, если вы хотите решить вопрос, просто сделайте new WebView(application) в приложении, прежде чем менять локальный.

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