webViwe 报错 For security reasons, WebView is not allowed in privileged processes

时间:2025-04-23 07:06:34

问题起源:

当我们申请我们的app为系统应用,也就是当我们在AndroidManifest文件中添加

android:sharedUserId=""

这一行的时候,如果我们使用webView就会报错:For security reasons, WebView is not allowed in privileged processes。

 这个是8.0代码中的一种安全机制。

网上查找资料,解决方案都是通过Hook技术根本思想是在异常发生前就给sProviderInstance赋值,因为在getProvider方法中当判断这个值不为空就直接返回了就不会抛异常了

 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;

            final int uid = ();
            if (uid == .ROOT_UID || uid == .SYSTEM_UID
                    || uid == .PHONE_UID || uid == .NFC_UID
                    || uid == .BLUETOOTH_UID) {
                throw new UnsupportedOperationException(
                        "For security reasons, WebView is not allowed in privileged processes");
            }

             oldPolicy = ();
            (Trace.TRACE_TAG_WEBVIEW, "()");
            try {
                Class<WebViewFactoryProvider> providerClass = getProviderClass();
                Method staticFactory = null;
                try {
                    staticFactory = (
                        CHROMIUM_WEBVIEW_FACTORY_METHOD, );
                } catch (Exception e) {
                    if (DEBUG) {
                        (LOGTAG, "error instantiating provider with static factory method", e);
                    }
                }

                (Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
                try {
                    sProviderInstance = (WebViewFactoryProvider)
                            (null, new WebViewDelegate());
                    if (DEBUG) (LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    (LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    (Trace.TRACE_TAG_WEBVIEW);
                }
            } finally {
                (Trace.TRACE_TAG_WEBVIEW);
                (oldPolicy);
            }
        }
    }

通过源码可以看到这一行代码if (sProviderInstance != null) return sProviderInstance; 紧接着就有抛异常的代码。

所以我们要让sProviderInstance不为空。

网上查找反射方法,发现了良好总方案:
方案一:


public static void hookWebView() {
        int sdkInt = .SDK_INT;
        try {
            Class<?> factoryClass = ("");
            Field field = ("sProviderInstance");
            (true);
            Object sProviderInstance = (null);
            if (sProviderInstance != null) {
                ("sProviderInstance isn't null");
                return;
            }
            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = ("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = ("getFactoryClass");
            } else {
                ("Don't need to Hook WebView");
                return;
            }
            (true);
            Class<?> providerClass = (Class<?>) (factoryClass);
            Class<?> delegateClass = ("");
            Constructor<?> providerConstructor = (delegateClass);
            if (providerConstructor != null) {
                (true);
                Constructor<?> declaredConstructor = ();
                (true);
                sProviderInstance = (());
                ("sProviderInstance:{}", sProviderInstance);
                ("sProviderInstance", sProviderInstance);
            }
            ("Hook done!");
        } catch (Throwable e) {
            (e);
        }

搜索了好多博客都是这个答案,于是兴致勃勃的cv打法一顿操作,但是发现当执行到

Constructor<?> providerConstructor = (delegateClass);

这一行代码的时候必然会报NoSuchMethod的错误,仔细看了一下frameWork代码,发现WebViewFactoryProvider这个类是个借口类,里面没有构造方法,自然会报这个错误。

又是一通百度,终于找打了另一种hook方案:

方案2:

    private static String TAG = "hookWebView";
    public static void hookWebView(){
        int sdkInt = .SDK_INT;
        try {
            Class<?> factoryClass = ("");
            Field field = ("sProviderInstance");
            (true);
            Object sProviderInstance = (null);
            if (sProviderInstance != null) {
                (TAG,"sProviderInstance isn't null");
                return;
            }

            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = ("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = ("getFactoryClass");
            } else {
                (TAG,"Don't need to Hook WebView");
                return;
            }
            (true);
            Class<?> factoryProviderClass = (Class<?>) (factoryClass);
            Class<?> delegateClass = ("");
            Constructor<?> delegateConstructor = ();
            (true);
            if(sdkInt < 26){//低于Android O版本
                Constructor<?> providerConstructor = (delegateClass);
                if (providerConstructor != null) {
                    (true);
                    sProviderInstance = (());
                }
            } else {
                Field chromiumMethodName = ("CHROMIUM_WEBVIEW_FACTORY_METHOD");
                (true);
                String chromiumMethodNameStr = (String)(null);
                if (chromiumMethodNameStr == null) {
                    chromiumMethodNameStr = "create";
                }
                Method staticFactory = (chromiumMethodNameStr, delegateClass);
                if (staticFactory!=null){
                    sProviderInstance = (null, ());
                }
            }

            if (sProviderInstance != null){
                ("sProviderInstance", sProviderInstance);
                (TAG,"Hook success!");
            } else {
                (TAG,"Hook failed!");
            }
        } catch (Throwable e) {
            (TAG,e);
        }
    }

这个方案完美的解决了这个问题。因为中间做了一次判断,判断是低于o版本还是高于o版本。

然后我只要在Activity的oncreate方法中调用就行了,切记一定要在setContentView之前调用,或者在webVIew创建之前调用,不然还是会报错的。

方案2转自:/68xi/p/