【问题标题】:WebView Crash on Android 5-5.1 (API 21-22) Resources$NotFoundException: String resource ID #0x2040002Android 5-5.1 (API 21-22) 上的 WebView 崩溃 Resources$NotFoundException: 字符串资源 ID #0x2040002
【发布时间】:2019-09-20 12:55:39
【问题描述】:

我正在将 Android 应用从 API 27 更新到 API 29,我注意到在基于 5.0 和/或 5.1 的模拟器上尝试渲染 WebView 时出现崩溃。在运行 6.0 或更高版本 (API 23-29) 的模拟器上不会发生此问题。

我似乎找不到任何有关会影响 5.0 或 5.1 的 WebView 行为的文档,但我可以确认当我使用 API 27 运行应用程序时问题不会发生。我不知所措,因为我不知道是否这是一个模拟器问题或实际的 API/设备问题(我认为是后者)。

问题是 Activity 和 Fragment 根本不会膨胀,因为缺少 String 资源。这是一些堆栈跟踪(它似乎找不到字符串资源):

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.MyActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.MyWebView
Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.MyWebView...
Caused by: java.lang.reflect.InvocationTargetException...
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040002

在崩溃发生之前,与资源相关的日志中有一些相关警告:

W/chromium: [WARNING:resource_bundle.cc(315)] locale_file_path.empty()
E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
W/chromium: [WARNING:proxy_service.cc(901)] PAC support disabled because there is no system implementation
W/chromium: [WARNING:data_reduction_proxy_settings.cc(403)] SPDY proxy OFF at startup
W/ResourceType: No known package when getting value for resource number 0x02040002

网络视图:

public class MyWebView extends WebView {

    public MyWebView (Context context) {
        super(context);
        initialize();
    }

    public MyWebView (Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public MyWebView (Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialize();
    }

    public MyWebView (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initialize();
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
        super(context, attrs, defStyleAttr, privateBrowsing);
        initialize();
    }

    private void initialize() {
        this.clearCache(true);
        this.clearHistory();
        this.getSettings().setJavaScriptEnabled(true);
        this.getSettings().setLoadsImagesAutomatically(true);
        this.getSettings().setUseWideViewPort(true);
        this.getSettings().setAllowContentAccess(false);
        this.getSettings().setAllowFileAccess(false);
        this.getSettings().setAllowFileAccessFromFileURLs(false);
        this.getSettings().setAllowUniversalAccessFromFileURLs(false);
        this.getSettings().setDomStorageEnabled(false);
        this.getSettings().setAppCacheEnabled(false);
        this.getSettings().setDatabaseEnabled(false);
        this.getSettings().setGeolocationEnabled(false);
        this.getSettings().setSaveFormData(false);
        this.getSettings().setSupportMultipleWindows(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            this.getSettings().setSafeBrowsingEnabled(false);
        }
    }
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <com.example.MyWebView
        android:id="@+id/my_web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

有什么想法我做错了什么,或者 API 28 或 29 中可能发生的变化可能会破坏这一点吗?

【问题讨论】:

  • 我也遇到了同样的问题,但这是一个重复的问题。
  • 哇,我在运行 Android 5.0.2 的模拟器时遇到了完全相同的崩溃,但运行 Android 5.1 的物理设备运行时没有任何问题。正如上面发布的@DmitryBrant 的答案,问题不在于 API 28 或 29,而在于androidx.appcompat:appcompat:1.1.0,如果您降级到1.0.21.1.0-beta01,那么崩溃应该会消失。
  • @Seven 你确定它在物理设备上工作正常吗?因为我没有 API 级别 21 的物理设备可以测试!
  • @SumitShukla 是的,我确定。它在我运行 Android 5.1(Moto G 1st Gen)的物理设备上运行良好。

标签: android android-webview


【解决方案1】:

我遇到了同样的麻烦,实际上解决它的方法是将构造函数中的上下文更改为context.getApplicationContext()

之后,它可以在 Android 5 上毫无问题地构建和渲染。

【讨论】:

  • 美丽。这为我修复了 LayoutInflater.from(activity.applicationContext).inflate(layoutResId, null) 而不是使用 activity
  • 它对我有用,但 context 和 getapplicationContext 有什么区别?为什么它不适用于棒棒糖?
【解决方案2】:

这似乎是 appcompat 1.1.0 的错误 - https://issuetracker.google.com/issues/141132133

虽然您可以尝试降级 appcompat 或等待修复,但您也可以尝试

使用自定义 WebView:

private fun Context.getLollipopFixWebView(): Context {
    return if (Build.VERSION.SDK_INT in 21..22) {
        createConfigurationContext(Configuration())
    } else this
}

/**
 * Workaround appcompat-1.1.0 bug https://issuetracker.google.com/issues/141132133
 */
class LollipopFixWebView(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
    WebView(context.getLollipopFixWebView(), attrs, defStyle)

或者将此解决方法添加到您的 WebView 的父 Activity:

    // Workaround appcompat-1.1.0 bug https://issuetracker.google.com/issues/141132133
    override fun applyOverrideConfiguration(overrideConfiguration: Configuration) {
        if (Build.VERSION.SDK_INT in 21..22) {
            return
        }
        super.applyOverrideConfiguration(overrideConfiguration)
    }

感谢https://github.com/ankidroid/Anki-Android/issues/5507 那里的人认为它也发生在 Android 7 上,但我无法复制

更新

自定义 WebView 解决方案可能会引入一个新问题:所有 Android 版本都没有显示键盘。

所以我们需要将 isFocusableisFocusableInTouchMode 设置为自定义 WebView 类来防止此类问题

class LollipopFixWebView : WebView {
    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context.getLollipopFixWebView(), attrs, defStyleAttr) {
        isFocusable = true
        isFocusableInTouchMode = true
    }
}

免责声明

我的minSdk 版本是 21 (Lollipop),所以不能保证我的解决方案适用于 minSdk 版本较低的应用

【讨论】:

  • 覆盖 applyOverrideConfiguration 对我有用!
  • 谢谢。解决方案运行良好。只是想知道重写 applyOverrideConfiguration 函数是否有任何潜在风险。
  • 从主题中检索任何属性时注意不要使用 WebView 上下文,因为新创建的上下文不会有它们。
  • @ericn 升级到 implementation 'androidx.appcompat:appcompat:1.2.0-beta01 解决了这个问题,会是它对上述版本(6.0 及更高版本)的任何副作用
  • 感谢您不使用带有defStyleRes: Int 的棒棒糖版本的构造函数。在这种情况下,即使在 API 19 中也会调用它并崩溃。所以,你只是没有添加它,它不会崩溃。
【解决方案3】:

固定在androidx.appcompat:appcompat:1.2.0-alpha02 只需使用以下行更新您的应用程序build.gradle 文件:

implementation "androidx.appcompat:appcompat:1.2.0-alpha02"

【讨论】:

  • 更新到 1.2.0-alpha02 解决了这个问题,但引入了不同的问题。最终做了一个解决方法@ericn 下面提到
  • @user3783123,您能说一下,出现了什么错误吗? Gunnar Bernstein 的建议有帮助吗?
  • @user3783123 升级到 implementation 'androidx.appcompat:appcompat:1.2.0-beta01 解决了这个问题,它对上述版本(6.0 及更高版本)是否有任何副作用
  • @Girish 它以某种方式破坏了应用程序在 android 6.0 及更低版本上的更改语言(区域设置)功能。虽然没有时间研究它是如何以及为什么会发生的
  • @user3783123 是唯一损坏的东西还是其他东西?
【解决方案4】:

这似乎是 appcompat 1.1.0 的错误 - https://issuetracker.google.com/issues/141132133

看看那个讨论中的#30,这解决了我的问题:

// add to gradle module:app
configurations.all {
    resolutionStrategy {
        force 'androidx.appcompat:appcompat:1.1.0-rc01'
    }
}

【讨论】:

    猜你喜欢
    • 2020-01-22
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 2021-05-09
    • 2012-06-26
    • 2019-08-16
    相关资源
    最近更新 更多