Android开发系统应用(android.uid.system)使用webview报错For security reasons, WebView is not allowed in privileged processes

原文

现象:

在开发系统级应用的时候,需要将自己的app在manifest中添加上android:sharedUserId="android.uid.system",此时如果在app中使用webview应用就会报错

Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:155)
at android.webkit.CookieManager.getInstance(CookieManager.java:42)

原因:

由于Android的webview在各个版本改动较大,谷歌已经将其独立出来,作为一个Android system webviewapp。为了防止影响系统app,谷歌从5.1开始全面禁止系统应用使用webview。查看源码获悉在WebviewFactory代码中某个静态实例初始化之前判断api版本并抛出错误。
问题分析:既然是谷歌禁止,那么要么是欺骗api版本;要么修改源码。根据大牛的分析,欺骗API不大可行,反倒是修改源码,人工给该变量赋值比较靠谱。

问题处理:

在使用webview之前,使用hook(钩子)方法,给该变量赋值。具体代码如下

private void hookWebView() {
        Class factoryClass = null;
        try {
            factoryClass = Class.forName("android.webkit.WebViewFactory");
            Method getProviderClassMethod = null;
            Object sProviderInstance = null;

            if (Build.VERSION.SDK_INT == 23) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
                getProviderClassMethod.setAccessible(true);
                Class providerClass = (Class) getProviderClassMethod.invoke(factoryClass);
                Class delegateClass = Class.forName("android.webkit.WebViewDelegate");
                Constructor constructor = providerClass.getConstructor(delegateClass);
                if (constructor != null) {
                    constructor.setAccessible(true);
                    Constructor constructor2 = delegateClass.getDeclaredConstructor();
                    constructor2.setAccessible(true);
                    sProviderInstance = constructor.newInstance(constructor2.newInstance());
                }
            } else if (Build.VERSION.SDK_INT == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
                getProviderClassMethod.setAccessible(true);
                Class providerClass = (Class) getProviderClassMethod.invoke(factoryClass);
                Class delegateClass = Class.forName("android.webkit.WebViewDelegate");
                Constructor constructor = providerClass.getConstructor(delegateClass);
                if (constructor != null) {
                    constructor.setAccessible(true);
                    Constructor constructor2 = delegateClass.getDeclaredConstructor();
                    constructor2.setAccessible(true);
                    sProviderInstance = constructor.newInstance(constructor2.newInstance());
                }
            } else if (Build.VERSION.SDK_INT == 21) {// Android 21无WebView安全限制
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
                getProviderClassMethod.setAccessible(true);
                Class providerClass = (Class) getProviderClassMethod.invoke(factoryClass);
                sProviderInstance = providerClass.newInstance();
            }
            if (sProviderInstance != null) {
                Field field = factoryClass.getDeclaredField("sProviderInstance");
                field.setAccessible(true);
                field.set("sProviderInstance", sProviderInstance);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

你可能感兴趣的:(Android开发系统应用(android.uid.system)使用webview报错For security reasons, WebView is not allowed in privileged processes)