项目中需要加载网页 ,在布局文件中写入系统控件  WebView , 运行项目直接就崩溃了,这让我匪夷所思

一  、 先抛出来我的异常信息


03-09 10:55:57.746: E/AndroidRuntime(27323): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cloudmind.vernier/com.cloudmind.vernier.LZMainActivity}:  android.view.InflateException: Binary XML file line #7: Error inflating class android.webkit.WebView
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2345)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2407)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread.access$800(ActivityThread.java:151)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.os.Handler.dispatchMessage(Handler.java:102)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.os.Looper.loop(Looper.java:135)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread.main(ActivityThread.java:5280)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at java.lang.reflect.Method.invoke(Native Method)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at java.lang.reflect.Method.invoke(Method.java:372)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:963)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:758)
03-09 10:55:57.746: E/AndroidRuntime(27323): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class android.webkit.WebView
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.createView(LayoutInflater.java:633)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:459)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.Activity.setContentView(Activity.java:2174)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at com.cloudmind.vernier.LZMainActivity.onCreate(LZMainActivity.java:127)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.Activity.performCreate(Activity.java:6222)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2295)
03-09 10:55:57.746: E/AndroidRuntime(27323):     ... 10 more
03-09 10:55:57.746: E/AndroidRuntime(27323): Caused by: java.lang.reflect.InvocationTargetException
03-09 10:55:57.746: E/AndroidRuntime(27323):     at java.lang.reflect.Constructor.newInstance(Native Method)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.LayoutInflater.createView(LayoutInflater.java:607)
03-09 10:55:57.746: E/AndroidRuntime(27323):     ... 23 more
03-09 10:55:57.746: E/AndroidRuntime(27323): Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:100)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.getFactory(WebView.java:2194)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.ensureProviderCreated(WebView.java:2189)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.setOverScrollMode(WebView.java:2248)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.View.<init>(View.java:3617)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.View.<init>(View.java:3711)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.view.ViewGroup.<init>(ViewGroup.java:497)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.<init>(WebView.java:544)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.<init>(WebView.java:489)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.<init>(WebView.java:472)
03-09 10:55:57.746: E/AndroidRuntime(27323):     at android.webkit.WebView.<init>(WebView.java:459)
03-09 10:55:57.746: E/AndroidRuntime(27323):     ... 26 more

二、 看一下我的布局文件 

代码中并没有发现任何问题,然后我新建了一个项目,复用了这个xml,,,结果运行成功了,没有崩溃,这下我确定是我项目的问题,接着找问题。

三、 经了解我的项目是系统级别的

系统应用引用webView 的时候确实会有问题,这下问题就明确了,在Application 的oncreate 方法中调用一下方法 hookWebView(), 就可以了, 运行就成功了。

    public static void hookWebView(){
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            field.setAccessible(true);
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                Log.i("11","sProviderInstance isn't null");
                return;
            }

            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                Log.i("","Don't need to Hook WebView");
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
            delegateConstructor.setAccessible(true);
            if(sdkInt < 26){//低于Android O版本
                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
                if (providerConstructor != null) {
                    providerConstructor.setAccessible(true);
                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
                }
            } else {
                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
                chromiumMethodName.setAccessible(true);
                String chromiumMethodNameStr = (String)chromiumMethodName.get(null);
                if (chromiumMethodNameStr == null) {
                    chromiumMethodNameStr = "create";
                }
                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
                if (staticFactory!=null){
                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
                }
            }

            if (sProviderInstance != null){
                field.set("sProviderInstance", sProviderInstance);
                Log.i("11","Hook success!");
            } else {
                Log.i("11","Hook failed!");
            }
        } catch (Throwable e) {
            Log.w("11",e);
        }
    }

四 ,问题就这样被解决了,但是 为什么系统级别的项目引用 webView 会有问题呢?

因难以避免WebView存在安全漏洞,系统遭受攻击,Android不允许特权进程应用使用WebView。如果使用了,便会抛出以上异常。

五、参考

当WebView运行在特权进程时抛出安全异常,Hook方式解决方案(包含对Android 8.0的处理) - 庚拓天下 - 博客园

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐