错误膨胀类 android.webkit

在 Lollipop (API 22)中,每次我在应用程序中显示 webview 时,应用程序都会崩溃。 与此事件相关的 android 开发者控制台中出现了多次崩溃。

不需要说它可以在 Android 4、6和7上运行。

阅读堆栈跟踪(张贴在这篇文章的结尾) ,有些东西困扰着我

Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040003

我在生成的 R.java 中搜索没有任何运气,显然因为 ID 不存在,但值得一试。

用 Google 搜索这个问题似乎与棒棒糖处理 webview 的方式有关。我用棒棒糖启动了一个新的 AVD 基于我在环球数据中心的坠机记者那里找到的一个设备我可以重现这个问题。


完整堆栈跟踪:

android.view.InflateException: Binary XML file line #7: Error inflating class android.webkit.WebView
at android.view.LayoutInflater.createView(LayoutInflater.java:633)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55) 
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67) 
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295) 
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) 
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682) 
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541) 
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5254) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040003
at android.content.res.Resources.getText(Resources.java:299)
at android.content.res.Resources.getString(Resources.java:385)
at com.android.org.chromium.content.browser.ContentViewCore.setContainerView(ContentViewCore.java:684)
at com.android.org.chromium.content.browser.ContentViewCore.initialize(ContentViewCore.java:608)
at com.android.org.chromium.android_webview.AwContents.createAndInitializeContentViewCore(AwContents.java:631)
at com.android.org.chromium.android_webview.AwContents.setNewAwContents(AwContents.java:780)
at com.android.org.chromium.android_webview.AwContents.<init>(AwContents.java:619)
at com.android.org.chromium.android_webview.AwContents.<init>(AwContents.java:556)
at com.android.webview.chromium.WebViewChromium.initForReal(WebViewChromium.java:311)
at com.android.webview.chromium.WebViewChromium.access$100(WebViewChromium.java:96)
at com.android.webview.chromium.WebViewChromium$1.run(WebViewChromium.java:263)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.drainQueue(WebViewChromium.java:123)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue$1.run(WebViewChromium.java:110)
at com.android.org.chromium.base.ThreadUtils.runOnUiThread(ThreadUtils.java:144)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.addTask(WebViewChromium.java:107)
at com.android.webview.chromium.WebViewChromium.init(WebViewChromium.java:260)
at android.webkit.WebView.<init>(WebView.java:554)
at android.webkit.WebView.<init>(WebView.java:489)
at android.webkit.WebView.<init>(WebView.java:472)
at android.webkit.WebView.<init>(WebView.java:459)
at java.lang.reflect.Constructor.newInstance(Native Method) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:288) 
at android.view.LayoutInflater.createView(LayoutInflater.java:607) 
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55) 
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67) 
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295) 
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) 
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682) 
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541) 
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5254) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 
48856 次浏览

尝试创建 webview:

mWebView = new WebView(getActivity().createConfigurationContext(new Configuration()));

警告: 此解决方案也可能破坏某些东西; 请参阅注释了解详细信息

如果您想从 XML 布局中扩展 WebView,您可以将其封装在一个漂亮的小子类中(基于 伊科斯特的回答) :

public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}


public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}


public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}


@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}


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


public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}

编辑: 现在更好与科特林

class LollipopFixedWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : WebView(context.createConfigurationContext(Configuration()), attrs, defStyleAttr, defStyleRes)

我的建议是使用自定义/新的 Configuration只有当“原来的一个”是造成问题,所以只有在棒棒糖。@ SpaceBizon 代码在 Android 8.x 之前运行良好,在9和 Q (目前测试版) ,每个选择/下拉按钮都不会显示 AlertDialog选择器,而不是发生内存泄漏... 下面是固定的 getFixedContext方法和“ iff”正确的版本代码

public class LollipopFixedWebView extends WebView {


public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}


public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}


public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}


@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}


private static Context getFixedContext(Context context) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) // Android Lollipop 5.0 & 5.1
return context.createConfigurationContext(new Configuration());
return context;
}
}

如果使用 androidx.appcompat:appcompat:1.1.0,请尝试使用 androidx.appcompat:appcompat:1.0.2。 看起来 1.1.0并没有修复 Android 5.1.1WebView的 bug。

2020年2月更新: 恢复到 1.0.2对许多人(包括我的应用程序)不起作用,但使用当前版本的 androidx.appcompat:appcompat:1.2.0-alpha02确实修复了崩溃。(在谷歌自动“发布前报告”测试期间,我在一台运行安卓5.0的华为 P8 Lite 上看到了它)。

2020年6月更新: 有比2020年2月更新中提到的更新版本,你可以在这里看到目前可用的版本:

戴文锦也适合我。 但是仅仅将 androidx.appcompat: appcompat: 1.1.0降级到1.0.2并没有成功。

我把之前升级的 androidx 版本都从

implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta04'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.core:core:1.2.0-alpha04'

回到

implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta03'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta03'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0-rc01'
implementation 'androidx.preference:preference:1.1.0-rc01'
implementation 'androidx.core:core:1.2.0-alpha03'

提醒一下,Google 的代码到目前为止还没有完全没有 bug,也没有经过良好的测试,任何人都不应该草率地升级版本。

如果您正在使用 androidx.appcompat: appcompat: 1.1.0,要么更改为 androidx.appcompat: appcompat: 1.0.2,要么如果您想使用 DayNight 主题,在您的活动中覆盖 applicyOverrideConfiguration,如下所示。(注意: 这需要在从黑暗主题切换到光明主题时重启应用程序,反之亦然)。

override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
if (Build.VERSION.SDK_INT in 21..25 && (resources.configuration.uiMode ==  applicationContext.resources.configuration.uiMode)) {
return
}
super.applyOverrideConfiguration(overrideConfiguration)
}
/**
* Customized WebView to avoid crashing on Android 5 and 6 (API level 21 to 23)
* If the Android System WebView is old and is not updated, the WebView view inflation fails.
* To reproduce the issue, try on OS 5 or 6 with Android System WebView 72.0.3626.76 (this version is just a reference point from being which we saw no crashes)
*/
class BrilliantWebView : WebView {


companion object {
private fun getBrilliantContext(context: Context?) =
if (!OSUtils.hasNougat()) // OS < 24 or OS < 7.0
context?.createConfigurationContext(Configuration())
else
context
}


constructor(context: Context?) : super(getBrilliantContext(context))
constructor(context: Context?, attrs: AttributeSet?) : super(getBrilliantContext(context), attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(getBrilliantContext(context), attrs, defStyleAttr)
}

我在模拟器里重现了 API 21的崩溃。

因此,我尝试将它添加到实现中,如 医生中所述:

dependencies {
def appcompat_version = "1.1.0"


implementation "androidx.appcompat:appcompat:$appcompat_version"
// For loading and tinting drawables on older versions of the platform
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
}

增加 appcompat-resources确实解决了 没有的问题。

也许未来的版本会有,但我想提到的是,似乎有一个补充资源库,应该解决这个问题。因此,当尝试用新版本的 appcompat修复这个问题时,添加具有相同版本的 appcompat-resources库。

恢复到 androidx.appcompat:appcompat:1.0.2确实解决了这个问题。

如果不依赖 DayNight 主题切换(或其他 UiMode 事件) ,则可以将 ConfigChanges = “ uiMode”添加到 webview 活动清单中,以防止 AppCompatgenerate 更新 Resources 配置,从而扰乱 webview 膨胀。

这个问题通过降级到实现‘ androidx.appcompat: appcompat: 1.0.2’得到了解决

另一个尝试修复这个问题。应该在你的活动中覆盖这个方法:

    @Override
public void applyOverrideConfiguration(final Configuration overrideConfiguration) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 25) {
overrideConfiguration.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
}
super.applyOverrideConfiguration(overrideConfiguration);
}

顺便说一句,我挣扎了一段时间,尽管我降级到了1.0.2,只是因为我似乎有一个传递依赖到 appcompat: 1.1.0 via androidx。一旦我降级为约束布局: 1.1.3,一切工作正常

(根据 https://issuetracker.google.com/issues/141351441发行将很快固定与应用程序: 1.2.0-alpha02)

如果您正在使用 androidx.appcompat:appcompat:1.1.0,并且不想降级到 androidx.appcompat:appcompat:1.0.2或升级到 androidx.appcompat:appcompat:1.2.0-alpha03,那么在谷歌问题跟踪程序的 此评论中描述了另一种解决方案。

我注意到在调用 applicyOverrideConfiguration 之后,Context.getAssets()Context.getResources().getAssets()没有返回相同的 AssetManager 对象。从 Context.getAssets()返回的 AssetManager 无法访问其他包(包括系统 WebView 包)中的资源,从而导致 WebView 崩溃。如果我重写 Context.getAssets()返回 getResources().getAssets(),问题就解决了。

基于该注释,您可以覆盖 WebView 活动中的 getAssets(),以便它返回 getResources().getAssets()来解决问题。

爪哇咖啡

@Override
public AssetManager getAssets() {
return getResources().getAssets();
}

科特林

override fun getAssets(): AssetManager {
return resources.assets
}

AppCompat 1.2.0-alpha02今天发布,因此您可以使用

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

修复棒棒糖上的 WebView 问题。

我能够在 Nexus7API 22上重现这个问题。通过将平板电脑版本的 Android System WebView 从 版本39(2237560-手臂)升级到 版本79.0.3945.136,这个问题得到了解决

对于用户来说,这不在我的控制范围之内,但是如果你需要帮助别人立即使用你的应用程序,这是一个解决方案。

检查版本。安卓应用程序和谷歌材料版本始终保持相同。

implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation "androidx.cardview:cardview:1.0.0"

在此输入图像描述

在我的情况下,一个问题是在方法上

fun getUserId(): Int = userId

主要活动。我不知道为什么会影响 WebViewgetUserId()既不会被重写,也不会重写 Activity类的公共方法。如果我重命名或删除此方法,WebView将开始打开。也在努力改变

private var userId: Int = 0

var userId: Int = 0
private set

导致同样的例外。我明白了,当看到一个例外: Caused by: java.lang.SecurityException: Permission Denial: null asks to run as user 123456 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS。在这种情况下,user = 123456实际上是我的授权用户,它在某些请求中使用,而不是在 WebView中。我怀疑 Android 使用 userId作为其进程的本地 user _ id。

正如许多其他人注意到,我们可以使用 appcompat:1.1.01.0.2和扩展 WebView类。在没有 Google Play Services 的模拟器21中,这个 WebView会在长时间触摸文本标签时崩溃,但是在典型的设备上一切正常。

下面的代码将解决这个问题。请将它添加到您的 Activity:

@Override
public AssetManager getAssets() {
return getResources().getAssets();
}

我使用的是最新版本的 这个来源。请检查和使用您自己的基础上,你认为是最好的。

如果你想跳过,下面的实现可以解决这个问题:

implementation 'androidx.appcompat:appcompat:1.2.0'

我没有更改任何依赖项的版本,而是以编程方式实现了 webView 的生成作为解决方案。

这个问题看起来像是从 xml 文件读取布局开始的。所以如果编程方式适用于您的解决方案,请检查下面的样品。

private WebView generateWebView(){
WebView wv = new WebView(YourContext);
wv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
wv.setFitsSystemWindows(false); // your preferences
wv.setVerticalScrollBarEnabled(false); // your preferences
wv.setPadding(15,15,15,15); // your preferences
return wv;
}

而不仅仅是加入父母的观点:

LinearLayout scrollContainer = findViewById(R.id.scrollContainer);
scrollContainer.addView(generateWebView());

2022年11月的解决方案

这个问题是解决与做改变

implementation 'androidx.appcompact:appcompact:1.2.0-alpha02'

特别提示

确保在整个项目中没有使用 getUserId()。更改或替换此函数。

请做卸载应用程序,然后检查它。这是为我工作。