Android WebView在WebViewDelegate.getPackageId处导致RuntimeException

时间:2019-06-07 14:55:45

标签: android

我的MainActivity的布局xml中有一个WebView,我setWebViewClient(new WebViewClient()),然后在onCreate中loadUrl(...)到它。

大多数情况下,应用程序运行良好且Web内容正确显示。

但是在某些情况下,打开应用程序会导致崩溃。我注意到,当应用程序通过AlarmManager安排了PendingIntent广播时,会发生这种情况,这会触发一个通知,该通知的contentIntent为PendingIntent.getActivity设置为启动MainActivity。 但这仅在用户同时从活动应用程序堆栈中删除该应用程序的情况下才会发生(通知可见,尚未单击,并且如果清除了应用程序则堆栈。因此,应用程序进程可能停止了吗?)。

两者之间似乎没有其他系统修改(特别是没有应用/系统更新,没有玩过用户个人资料或Chrome应用)。

堆栈跟踪:

java.lang.RuntimeException: 
  at android.webkit.WebViewDelegate.getPackageId (WebViewDelegate.java:164)
  at yj.a (PG:16)
  at xH.run (PG:14)
  at java.lang.Thread.run (Thread.java:764)

Android 7.0到9一起出现。另外,当我将目标SDK升级到28时,似乎开始出现。

我没有明确使用WebViewDelegate。它必须是内部系统代码(因此难以理解)。

通过阅读AOSP的源代码,似乎WebView无法检索其所属的程序包-但是为什么有时只有它!?

任何帮助表示赞赏!谢谢。

2 个答案:

答案 0 :(得分:1)

经过了数周的反复调查,但我终于找到了为什么看到此问题的原因。对我来说,这仅仅是因为我在应用程序范围内重写了getResources()方法以使用当前活动。像这样:

public class MyApplication extends MultiDexApplication {
    private static MyApplication sInstance = null;
    private WeakReference<Activity> mCurrentActivity;

    public static MyApplication getInstance() {
        return sInstance;
    }

    public void setCurrentActivity(Activity activity) {
        mCurrentActivity = new WeakReference<>(activity);
    }

    public Activity getCurrentActivity() {
        return mCurrentActivity == null ? null : mCurrentActivity.get();
    }

    @Override
    public Resources getResources() {
        // This is a very BAD thing to do
        Activity activity = getCurrentActivity();
        if (activity != null) {
            return activity.getResources();
        }
        return super.getResources();
    }
}

这是作为快捷方式完成的,因为我经常想获取特定于活动的字符串,因此我在调用MyApplication.getInstance()。getResources()。getString()。我现在知道这是一件坏事-删除我对此方法的覆盖会立即修复它。

因此,对我而言,主要的收获是,在初始化WebView时,它必须能够掌握应用程序上下文,以便传递给WebViewDelegate.getPackageId()的资源位于应用程序级别-活动上下文是不够的,并且会导致此错误。

作为旁注-我什至没有尝试将WebView添加到我的应用程序中。我实际上只是在使用以下内容:

String userAgent = WebSettings.getDefaultUserAgent(this);

然后,我将此值传递到我正在使用的自定义媒体播放器中。由于我的覆盖,传递“ this”作为应用程序或活动范围始终失败。

答案 1 :(得分:0)

查看文档,您会发现找不到包时抛出错误。检查语法,包名称,然后重试。

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/webkit/WebViewDelegate.java(第164行)

 /**
     * Returns the package id of the given {@code packageName}.
     */
    public int getPackageId(Resources resources, String packageName) {
        SparseArray<String> packageIdentifiers =
                resources.getAssets().getAssignedPackageIdentifiers();
        for (int i = 0; i < packageIdentifiers.size(); i++) {
            final String name = packageIdentifiers.valueAt(i);
            if (packageName.equals(name)) {
                return packageIdentifiers.keyAt(i);
            }
        }
        throw new RuntimeException("Package not found: " + packageName);
    }