当前位置: 首页 > 知识库问答 >
问题:

Android-WebView语言在Android 7.0及以上版本上突然发生变化

窦哲彦
2023-03-14

我有一个多语言应用程序,主要语言为英语,次要语言为阿拉伯语。

如文件所述,

  • 我在清单中添加了android: support sRtl="true"
  • 我已经将带有属性的所有xml属性分别更改为startend
  • 我已经在string-ar添加了阿拉伯语字符串(其他资源也是如此)。

上述设置工作正常。将Locale更改为ar AE后,将显示阿拉伯语文本

但是,每次我导航到WebView和/或WebViewClient活动时,区域设置、文本和布局方向都会突然恢复到设备默认值。

进一步提示:

  • 这只发生在Android7.0的Nexus 6P上。Android6.0.1及以下版本的一切都正常工作。
  • 只有当我导航到具有WebView和/或WebViewClient活动(我有几个)时,区域设置的突然转换才会发生。它不会发生在任何其他活动上。

Android 7.0支持多语言环境,允许用户设置多个默认语言环境。因此,如果我将主区域设置为locale。英国

然后在导航到WebView时,语言环境从ar-AE更改为en-GB

Android 7.0 API的变化:

如API变更列表所示,与locale相关的新方法已添加到API 24中的以下类中:

Locale

  • Locale。getDefault(…)

配置

  • 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.Android 4.2中的本地RTL支持。

    2.多语言支持-语言和区域设置。

    3.注意默认的区域设置。


  • 共有3个答案

    阎劲
    2023-03-14

    在阅读了所有答案后,我发现每一个答案都缺少一些东西,所以这里是迄今为止对我有效的解决方案。由于WebView会覆盖活动上下文和html" target="_blank">应用程序上下文的语言配置,因此每次发生这种情况时,必须确保调用一个方法来重置这些更改。在我的例子中,我写了下面的课程,我提出了这个问题的活动扩展(那些显示网络视图的活动):

    public class WebViewFixAppCompatActivity extends AppCompatActivity {
    
    private Locale mBackedUpLocale = null;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mBackedUpLocale = getApplicationContext().getResources().getConfiguration().getLocales().get(0);
        }
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        fixLocale();
    }
    
    @Override
    public void onBackPressed() {
        fixLocale();
        super.onBackPressed();
    }
    
    /**
     * The locale configuration of the activity context and the global application context gets overridden with the first language the app supports.
     */
    public void fixLocale() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Resources resources = getResources();
            final Configuration config = resources.getConfiguration();
    
            if (null != mBackedUpLocale && !config.getLocales().get(0).equals(mBackedUpLocale)) {
                Locale.setDefault(mBackedUpLocale);
                final Configuration newConfig = new Configuration(config);
                newConfig.setLocale(new Locale(mBackedUpLocale.getLanguage(), mBackedUpLocale.getCountry()));
                resources.updateConfiguration(newConfig, null);
            }
    
            // Also this must be overridden, otherwise for example when opening a dialog the title could have one language and the content other, because
            // different contexts are used to get the resources.
            Resources appResources = getApplicationContext().getResources();
            final Configuration appConfig = appResources.getConfiguration();
            if (null != mBackedUpLocale && !appConfig.getLocales().get(0).equals(mBackedUpLocale)) {
                Locale.setDefault(mBackedUpLocale);
                final Configuration newConfig = new Configuration(appConfig);
                newConfig.setLocale(new Locale(mBackedUpLocale.getLanguage(), mBackedUpLocale.getCountry()));
                appResources.updateConfiguration(newConfig, null);
            }
    
        }
    }
    }
    

    @Tobliug发布的在WebView覆盖之前保存初始配置的想法对我有效,在我的特殊情况下,我发现这比发布的其他解决方案更容易实现。重要的是,fix方法在退出WebView后被调用,例如在按下back和On Stop时。如果webView显示在对话框中,则必须注意在取消对话框后调用修复方法,主要是在onResume和/或onCreate中。如果webView直接加载到活动的onCreate中,而不是之后加载到新片段中,则在设置活动标题之前,还必须在setContentView之后直接调用修复程序,等等。如果webView加载到活动的片段中,在onViewCreated中调用该片段的活动,该活动应该调用fix方法。并不是所有的活动都需要像aswer中提到的那样扩展上述课程,这是一种过激的做法,没有必要。用Google Chrome标签替换WebView或打开外部浏览器也无法解决这个问题。

    如果您真的需要在Resources配置中设置完整的语言列表,而不仅仅是一种语言,那么您需要将此解决方案与当前的解决方案合并https://gist.github.com/amake/0ac7724681ac1c178c6f95a5b09f03ce就我而言,这是没有必要的。

    我也没有发现有必要调用新的WebView(这个)。破坏();正如在这里的回答中所指出的。

    谷梁博易
    2023-03-14

    您的代码似乎正在为应用程序本身的配置设置区域设置(MyApplication.getInstance())。但是,在扩展活动的内容视图之前,需要更新活动上下文的配置。我发现修改应用程序的上下文是不够的(事实证明,甚至没有必要)。如果我不更新每个活动上下文,那么活动之间的行为是不一致的。

    我的方法是将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;
            }
        }
    }
    

    然后我确保在调用任何使用上下文的方法(如setContentView())之前,在每个子类的onCreate()方法中调用super.onCreate(SavedInstanceState)

    锺离声
    2023-03-14

    特德·霍普的回答设法解决了这个问题,但他没有回答为什么会发生这种情况的问题。

    原因是在Android 7.0中对WebView类及其支持包所做的更改。

    背景:

    Android的WebView是使用WebKit构建的。虽然它最初是AOSP的一部分,但从KitKat开始,决定将WebView拆分为一个名为Android系统WebView的独立组件。它本质上是一款Android系统应用,预装了Android设备。它会定期更新,就像谷歌Play Services和Play Store应用程序等其他系统应用程序一样。您可以在已安装的系统应用程序列表中看到:

    Android7.0的变化:

    从AndroidN开始,Chrome应用程序将用于在第三方Android应用程序中呈现任何/所有WebViews。在安装了Android N开箱即用的手机中,根本不存在Android WebView系统应用程序。在接收到Android N的OTA更新的设备中,Android系统WebView被禁用:

    此外,还引入了多语言环境支持,设备具有多种默认语言:

    对于使用多种语言的应用程序来说,这是一个重要的结果。如果你的应用程序有WebViews,那么这些将使用Chrome应用程序呈现。因为Chrome本身就是一款Android应用程序,运行在自己的沙盒进程中,所以它不会绑定到应用程序设置的区域设置。相反,Chrome将恢复为主设备区域设置。例如,假设您的应用程序区域设置为ar AE,而设备的主要区域设置为en US。在这种情况下,包含WebView活动的区域设置将从ar AE更改为en US,并显示相应区域设置文件夹中的字符串和资源。您可能会在那些具有WebViews的Activitys上看到大量的LTR和RTL字符串/资源。

    解决方案是:

    此问题的完整解决方案包括两个步骤:

    第一步:

    首先,在每个活动中手动重置默认区域设置,或者至少在每个活动具有网络视图的活动中手动重置默认区域设置。

    public static void setLocale(Locale locale){
        Context context = MyApplication.getInstance();
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        Locale.setDefault(locale);
        configuration.setLocale(locale);
    
        if (Build.VERSION.SDK_INT >= 25) {
            context = context.getApplicationContext().createConfigurationContext(configuration);
            context = context.createConfigurationContext(configuration);
        }
    
        context.getResources().updateConfiguration(configuration,
                resources.getDisplayMetrics());
    }
    

    在调用setContentView(…)之前调用上述方法 onCreate()方法中。locale参数应该是您希望设置的默认locale。例如,如果希望将阿拉伯语/UAE设置为默认语言环境,则应传递新语言环境(“ar”、“AE”)。或者,如果您希望设置默认区域设置(即操作系统自动设置的locale),则应传递locale。美国

    第二步:

    此外,还需要添加以下代码行:

    new WebView(this).destroy();
    

    应用程序类的onCreate()中(如果有),以及用户可能正在更改语言的其他地方。这将解决在更改语言后重新启动应用程序时可能出现的各种边缘情况(您可能注意到其他语言中的字符串,或者在Android 7.0上具有WebViews的Activities上更改语言后出现的相反对齐方式)。

    作为补充,Chrome定制标签现在是呈现应用程序内网页的首选方式。

    参考资料:

    1. Android 7.0-WebView的更改。

    2.了解WebView和Android安全补丁。

    3.Android的网络视图。

    4.网络视图:从“由Chrome提供动力”到直接使用Chrome。

    5.牛轧糖WebView。

    6.Android7.0牛轧糖。

    7.AndroidN之谜,第1部分:Android系统WebView现在只是“Chrome”?。

     类似资料:
    • 我想阅读Android4.2及以上版本的APN设置。我在参考链接上找到的最佳答案是什么时候 它适用于大多数拥有OS4.2及以上操作系统的android手机。但大多数三星设备都不起作用。有没有其他方法来确定默认APN设置?

    • 我正在尝试在我的应用程序中实现通话录音,但由于受限权限CAPTURE_AUDIO_OUTPUT(只能授予系统应用程序),我无法录制其他人的音频。我在Play store Cube ACR上找到了一个应用程序,可以清楚地录制双方的音频。如果谷歌禁用了通话录音,那么它如何录制通话。有什么解决方法可以记录我缺失的通话吗?

    • 我对谷歌的游戏商店感到失望。我的应用程序根本不会出现在搜索中。没有一个“本周新内容”部分,用户可以从我这样的独立开发者那里找到新内容。最重要的结果通常包括带有腥味的Hillary评论 我联系了谷歌,他们说我可以付钱让他们出现在顶级搜索中(通过广告),这样可以改善我的“市场策略”。我只是想分享我的免费应用程序,以便其他人可以使用它,我没有市场策略 因此,我将重点关注我的Apple Store版本(它

    • 本文向大家介绍Android 7.0以上版本实现应用内语言切换的方法,包括了Android 7.0以上版本实现应用内语言切换的方法的使用技巧和注意事项,需要的朋友参考一下 前言 项目里有个功能,在应用内切换语言,之前上线了大半年,一直都是正常运行,但是最近这次发版以后,在国外的同事反馈(这里面还包括CEO... 尴尬),他们的华为手机上出现了中英文混乱的问题。本文记录了解决问题的过程和方法。 正文

    • 我是android应用程序开发的新手,试图开发一个web视图应用程序,但似乎无法让文件上传工作。。。请帮忙 这是我的网页视图代码 公共类WebActive扩展了活动{ } 所以我在wv下添加了这个代码。setWebChromeClient//未记录的魔术方法覆盖//br>//如果您尝试在此处放置@override,Eclipse将对您发誓//Android 3.0 public void open

    • iOS版本的应用程序运行良好,所有的图像都能出现。 下面是我安装调试版本时的消息: /users/someguy/projects/third/something-app/android/gaialibrary/src/main/androidmanifest.xml:9:5-15:19警告:application@android:allowbackup在androidmanifest.xml:9