由于webView存在安全漏洞,谷歌从5.1开始全面禁止系统应用使用webview,使用会导致应用崩溃错误提示:Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 异常信息可以看出 是在 WebViewFactory.java 的getProvider 方法 抛出的。源码路径为 frameworks/base/core/java/android/webkit/WebViewFactory.java

static WebViewFactoryProvider getProvider() {
        synchronized (sProviderLock) {
            // For now the main purpose of this function (and the factory abstraction) is to keep
            // us honest and minimize usage of WebView internals when binding the proxy.
            if (sProviderInstance != null) return sProviderInstance; //如果sProviderInstance不为空直接返回
             
          //1,判断,如果是系统id ,则抛出异常。
            final int uid = android.os.Process.myUid();
            if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID) {
                throw new UnsupportedOperationException(
                        "For security reasons, WebView is not allowed in privileged processes");
            }
 
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
            try {
                //2
                Class<WebViewFactoryProvider> providerClass = getProviderClass();
 
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
                try {
                    //3 给 sProviderInstance 赋值
                    sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
                            .newInstance(new WebViewDelegate());
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }
    }

  如果是系统id,就抛出异常! 可以通过反射在调用webview 之前,给sProviderInstance 赋值,这样就可以了 在Application调用方法,兼容8.0

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(TAG,"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(TAG,"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(TAG,"Hook success!");
      } else {
        Log.i(TAG,"Hook failed!");
      }
    } catch (Throwable e) {
      Log.w(TAG,e);
    }
  }

  

解决Android8.0系统应用打开webView报错的更多相关文章

  1. 解决windows64位系统上安装mysql-python报错

    解决windows64位系统上安装mysql-python报错 2018年03月12日 13:08:24 一个CD包 阅读数:1231    版权声明:本文为博主原创文章,未经博主允许不得转载. ht ...

  2. 一招解决OpenERP8.0安装旧版模块报错

    有喜欢尝鲜的网友开始玩8.0了,可是版本还没发布,社区的很多特别好的模块还没有升级到8,所以经常碰到模块无法安装的问题. No module name osv 网友提出将模块的 from osv im ...

  3. dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法

    dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法 在混淆的时候报错了,错误描述大致如下: Could not find a compatible vers ...

  4. 使用自编译的Emacs26.0.50build10版本,helm报错(已解决)

    使用自编译的Emacs26.0.50build10版本,helm报错(已解决) */--> code {color: #FF0000} pre.src {background-color: #0 ...

  5. 如何解决vue2.0 打包之后 打开index.html出现空白页

    如何解决vue2.0 打包之后 打开index.html出现空白页 1.打包之前修改三个文件       1.1.第一步,找到build文件,在webpack.prod.conf.js 第25行左右 ...

  6. Linux系统下启动MySQL报错:Neither host &#39;localhost.localdomain&#39; nor &#39;localhost&#39; could be looked up with

    Linux系统下启动MySQL报错:Neither host 'localhost.localdomain' nor 'localhost' could be looked up with 摘要 Li ...

  7. 打开eclipse报错:发现了以元素 'd:skin' 开头的无效内容。此处不应含有子元素。

    [错误] 打开eclipse报错:发现了以元素 ‘d:skin’ 开头的无效内容.此处不应含有子元素. [具体报错信息] Error parsing D:\Android-sdks\system-im ...

  8. 【WPF】弹窗定位、弹窗关闭后再打开的报错

    需求:点击按钮,打开一个弹窗. // 获得窗体实例 Window window = openDesignViewModel.View as Window; // 这是使用了WAF框架 //Window ...

  9. 开着idea,死机了,关机重启。重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification

    开着idea,死机了,关机重启.重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification. goo ...

随机推荐

  1. springboot 控制台程序读取配置文件(原创)

    首先新建一个springboot项目,此处省略. 1.新建一个application.properties person.name=kevin person.age=6 person.sex=male ...

  2. 「杂录」CSP-S 2019 爆炸记&题解

    考试状况 \(Day1\) \(8:30\) 解压,先打个含头文件和\(freopen\)的模板程序,准备做题. \(8:35\) 开题,心想着按顺序做吧,毕竟难度一般是按顺序排的. 第一题,一眼看过 ...

  3. 图片懒加载--lazyload.js的用法

    这几天公司的项目已经完成的差不多了,只剩下各种优化问题.今天着重于图片加载的优化.当一个页面需要下拉很长而且又有过多的图片要加载时,就会发生很多http请求,就会拉慢网页加载速度,用户体验不友好.怎么 ...

  4. docker关系图解析

    docker关系图解析 一.docker有5种状态 Dockerfile 文本文件,制作images的配置文件 images image,静态文件 containers container image ...

  5. 转!!通俗理解数字加密,数字签名,数字证书和https

    原博文地址:https://www.jianshu.com/p/4932cb1499bf 前言 最近在开发关于PDF合同文档电子签章的功能,大概意思就是在一份PDF合同上签名,盖章,使其具有法律效应. ...

  6. 在 Target 中获取项目引用的所有依赖(dll/NuGet/Project)的路径

    原文:在 Target 中获取项目引用的所有依赖(dll/NuGet/Project)的路径 在项目编译成 dll 之前,如何分析项目的所有依赖呢?可以在在项目的 Target 中去收集项目的依赖. ...

  7. ExtractFileDir 与 ExtractFilePath 的区别

    ExtractFileDir 从文件名中获取目录名(文件不在根目录下时取得的值后没有“/”,在根目录时一样,都是盘符,例如“C:/”) ExtractFilePath 从文件名中获取路径名(文件不在根 ...

  8. .Net Core WebApi(3)—NLog

    在.Net Core中,微软提供的内置的日志组件没有实现将日志记录到文件.数据库上.这里使用NLog替代内置的日志组件 1.在项目中引入NuGet包   NLog         NLog.Web.A ...

  9. MyBatis和spring整合简单实现

    spring和MyBatis整合: 导入spring和MyBatis的整合jar包,以及其依赖jar包: 导入MyBatis和spring的整合jar包. spring的核心jar包. 定义Mybat ...

  10. Fluxay流光使用

    扫描IPC主机 填写扫描地址.扫描类型为NT/98 显示如下,扫描成功 扫描用户列表 显示如下,扫描成功 下面想怎么做就怎么做 IPC连接失败原因 对方未打开IPC共享 对方未开启139或445端口 ...