由于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. Difference between java.lang.RuntimeException and java.lang.Exception

    In Java, there are two types of exceptions: checked exceptions and un-checked exceptions. A checked ...

  2. Openresty 健康检查

    ## 指定共享内存 lua_shared_dict healthcheck 1m; ## 在worker初始化过程中,启动定时器,进行后端结点的检查 init_worker_by_lua_block ...

  3. time 库

    time 库的三类函数 时间获取: >>> import time >>> time.time() 1570150181.4052463#单位为秒 >> ...

  4. netcore 版本 切换 sdk

    https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-json

  5. Map 集合按字母排序方法

    @Testpublic void testMapSort() { Map<String, String> map = new HashMap<>(); map.put(&quo ...

  6. 全栈项目|小书架|服务器端-NodeJS+Koa2 实现点赞功能

    效果图 接口分析 通过上面的效果图可以看出,点赞入口主要是在书籍的详情页面. 而书籍详情页面,有以下几个功能是和点赞有关的: 获取点赞状态 点赞 取消点赞 所以项目中理论上与点赞相关的接口就以上三个. ...

  7. java之抽象类介绍

    什么抽象方法和抽象类 抽象方法 在类里面定义的没有方法体且用关键字“abstract”来修饰的方法就是抽象方法,所谓的没有方法体指的是在方法声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名 ...

  8. php中的htmlspecialchars_decode()函数

    htmlspecialchars_decode() 函数把一些预定义的 HTML 实体转换为字符. <?php $str = "This is some <b>bold&l ...

  9. Windows下使用MongoDb的经验

    随着NoSql广泛应用MongoDb这个Json数据库现在也被广泛使用,接下来简单介绍一下Windows下如使安装使用MongoDb. 一.安装MongoDb 1.首先去官方网址:(https://w ...

  10. 解读HTTP/3

    技术的发展总是让人目不暇接,2018年10月,HTTP/3又发布了.虽然已经有一些中文技术媒体做了报道,但大多数是翻译的,而且内容大同小异.最近我专门学习了点关于HTTP/3的知识,在这里随便写写,和 ...