Android Nougat 7.1 在启动 WebView 后重置语言环境
Android Nougat 7.1 resets Locale after launching WebView
我们在 Android N 7.1 ( API-25 ) 中遇到了一个奇怪的行为,即在启动 WebView 后,系统会强制将区域设置重置为设备区域设置。这会覆盖应用程序中使用的语言环境(用于本地化)。重现的简单方法是在应用程序上进行本地化。并启动 WebView。然后您将不会再看到本地化内容,直到您再次重新启动应用程序。这只发生在 Android-7.1 (API-25)
以下是我切换语言环境的方法,它在所有 API 中都有效:
public void switchToCzLocale() {
Locale mLocale = new Locale("cs","CZ");// it can be any other Locale
Configuration config = getBaseContext().getResources()
.getConfiguration();
Locale.setDefault(mLocale);
config.setLocale(mLocale);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
我已经上传了一个示例来重现该问题,其中包含更多详细信息:
https://github.com/mabuthraa/WebView-android7-issue
如果此行为是一个错误或可能是更改区域设置的错误植入,请知道。
这里是 link 在 Android 组发票:Issue 218310: [developer preview] Creating a WebView resets Locale to user defaults
这是我的解决方案。
我们通过在初始化 webView 之后和加载内容之前再次强制设置语言环境来解决该问题:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
MyApp.getApplication().switchToCzLocale();
}
例如在 WebActivity 中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
mWebView = (WebView) findViewById(R.id.webview);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
MyApp.getApplication().switchToCzLocale();
}
mWebView.loadData(getString(R.string.web_content), "text/html", "charset=UTF-8");
}
我的应用程序:
import android.app.Application;
import android.content.res.Configuration;
import java.util.Locale;
public class MyApp extends Application {
private static MyApp sApplication;
@Override
public void onCreate() {
super.onCreate();
switchToCzLocale();
sApplication = this;
}
public static MyApp getApplication() {
return sApplication;
}
public void switchToCzLocale() {
Locale mLocale = new Locale("cs","CZ");
Configuration config = getBaseContext().getResources()
.getConfiguration();
Locale.setDefault(mLocale);
config.setLocale(mLocale);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
希望对您有所帮助,'。
我还在寻找更好的解决方案。
这个问题也让我头疼,特别是因为Google认为这不是他们这边的错误。但是,这绝对不是应用程序中希望的行为,即在打开 WebView 时语言就会发生变化。
我们的解决方案不依赖于硬编码语言,适用于 Android 7+。首先,将此代码添加到您的应用 build.gradle 文件中:
android {
defaultConfig {
...
resConfigs rootProject.ext.available_languages
buildConfigField "String[]", "AVAILABLE_LANGUAGES", "{\"${rootProject.ext.available_languages.join("\",\"")}\"}"
}
}
并将以下代码添加到您的根 build.gradle:
ext {
available_languages = ["en", "de"]
}
这两个代码块定义了可用 strings.xml
文件的列表,并将该列表放在 BuildConfig.AVAILABLE_LANGUAGES
字段中。
现在,我们可以定义一个 BaseActivity
,所有活动都应从中扩展,代码如下:
abstract class BaseActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
val locale = getFirstAvailableLocale(newBase)
val context = createContextWithLocale(locale, newBase)
super.attachBaseContext(context)
}
private fun getFirstAvailableLocale(context: Context): Locale {
val availableLanguages = BuildConfig.AVAILABLE_LANGUAGES // Gets list of available languages defined in the build.gradle file
val locales = context.resources.configuration.locales
for (i in 0..locales.size()) {
if (locales[i].language in availableLanguages) {
return locales[i]
}
}
return locales[0]
}
@Suppress("DEPRECATION")
private fun createContextWithLocale(locale: Locale, baseContext: Context): Context {
val resources = baseContext.resources
val configuration = resources.configuration
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
baseContext.createConfigurationContext(configuration)
} else {
resources.updateConfiguration(configuration, resources.displayMetrics)
baseContext
}
}
}
您甚至可以扩展此解决方案以支持不同的区域,但是您必须将 resConfigs 中的字符串拆分为语言和区域,因为 Locale
class 无法识别语言标签正确(例如 de-rDE 需要在 resConfigs 中定义,但 Locale
将是 de_DE)
我们在 Android N 7.1 ( API-25 ) 中遇到了一个奇怪的行为,即在启动 WebView 后,系统会强制将区域设置重置为设备区域设置。这会覆盖应用程序中使用的语言环境(用于本地化)。重现的简单方法是在应用程序上进行本地化。并启动 WebView。然后您将不会再看到本地化内容,直到您再次重新启动应用程序。这只发生在 Android-7.1 (API-25)
以下是我切换语言环境的方法,它在所有 API 中都有效:
public void switchToCzLocale() {
Locale mLocale = new Locale("cs","CZ");// it can be any other Locale
Configuration config = getBaseContext().getResources()
.getConfiguration();
Locale.setDefault(mLocale);
config.setLocale(mLocale);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
我已经上传了一个示例来重现该问题,其中包含更多详细信息:
https://github.com/mabuthraa/WebView-android7-issue
如果此行为是一个错误或可能是更改区域设置的错误植入,请知道。
这里是 link 在 Android 组发票:Issue 218310: [developer preview] Creating a WebView resets Locale to user defaults
这是我的解决方案。
我们通过在初始化 webView 之后和加载内容之前再次强制设置语言环境来解决该问题:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
MyApp.getApplication().switchToCzLocale();
}
例如在 WebActivity 中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
mWebView = (WebView) findViewById(R.id.webview);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
MyApp.getApplication().switchToCzLocale();
}
mWebView.loadData(getString(R.string.web_content), "text/html", "charset=UTF-8");
}
我的应用程序:
import android.app.Application;
import android.content.res.Configuration;
import java.util.Locale;
public class MyApp extends Application {
private static MyApp sApplication;
@Override
public void onCreate() {
super.onCreate();
switchToCzLocale();
sApplication = this;
}
public static MyApp getApplication() {
return sApplication;
}
public void switchToCzLocale() {
Locale mLocale = new Locale("cs","CZ");
Configuration config = getBaseContext().getResources()
.getConfiguration();
Locale.setDefault(mLocale);
config.setLocale(mLocale);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
希望对您有所帮助,'。
我还在寻找更好的解决方案。
这个问题也让我头疼,特别是因为Google认为这不是他们这边的错误。但是,这绝对不是应用程序中希望的行为,即在打开 WebView 时语言就会发生变化。
我们的解决方案不依赖于硬编码语言,适用于 Android 7+。首先,将此代码添加到您的应用 build.gradle 文件中:
android {
defaultConfig {
...
resConfigs rootProject.ext.available_languages
buildConfigField "String[]", "AVAILABLE_LANGUAGES", "{\"${rootProject.ext.available_languages.join("\",\"")}\"}"
}
}
并将以下代码添加到您的根 build.gradle:
ext {
available_languages = ["en", "de"]
}
这两个代码块定义了可用 strings.xml
文件的列表,并将该列表放在 BuildConfig.AVAILABLE_LANGUAGES
字段中。
现在,我们可以定义一个 BaseActivity
,所有活动都应从中扩展,代码如下:
abstract class BaseActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
val locale = getFirstAvailableLocale(newBase)
val context = createContextWithLocale(locale, newBase)
super.attachBaseContext(context)
}
private fun getFirstAvailableLocale(context: Context): Locale {
val availableLanguages = BuildConfig.AVAILABLE_LANGUAGES // Gets list of available languages defined in the build.gradle file
val locales = context.resources.configuration.locales
for (i in 0..locales.size()) {
if (locales[i].language in availableLanguages) {
return locales[i]
}
}
return locales[0]
}
@Suppress("DEPRECATION")
private fun createContextWithLocale(locale: Locale, baseContext: Context): Context {
val resources = baseContext.resources
val configuration = resources.configuration
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
baseContext.createConfigurationContext(configuration)
} else {
resources.updateConfiguration(configuration, resources.displayMetrics)
baseContext
}
}
}
您甚至可以扩展此解决方案以支持不同的区域,但是您必须将 resConfigs 中的字符串拆分为语言和区域,因为 Locale
class 无法识别语言标签正确(例如 de-rDE 需要在 resConfigs 中定义,但 Locale
将是 de_DE)