zoukankan      html  css  js  c++  java
  • 解决Android8.0系统应用打开webView报错

       由于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);
        }
      }
    

      

  • 相关阅读:
    为什么要对url进行encode
    活在当下
    Linux Shell 文本处理工具
    Servlet、Servlet容器等内容讲解
    Java编程中的一些常见问题汇总
    创建文件目录
    ubuntu
    iptables
    mysqldump导入导出
    pt-table-sync
  • 原文地址:https://www.cnblogs.com/68xi/p/11206543.html
Copyright © 2011-2022 走看看