18

我们在 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

请知道这种行为是错误还是更改语言环境的错误植入。

这是在 Android 组上发出票证的链接:问题 218310:[开发人员预览] 创建 WebView 将区域设置重置为用户默认值

4

2 回答 2

16

这是我的解决方法。

我们通过在初始化 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());
    }
}

我希望这可能会有所帮助,'。

我仍在寻找更好的解决方案。

于 2016-11-08T12:33:06.003 回答
0

这个问题也让我有些头疼,特别是因为谷歌认为这不是他们这边的错误。但是,这绝对不是应用程序中所期望的行为,即仅在打开 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使用以下代码定义 a ,所有活动都应从其扩展:

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该类无法正确识别语言标签(例如,需要在 resConfigs 中定义 de-rDE,但Locale会成为de_DE)

于 2021-12-16T13:30:14.440 回答