欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

解决 Android 系统应用无法使用WebView的问题

程序员文章站 2022-04-16 16:14:49
在 android 8.0 系统上,普通应用使用 WebView 时,正常使用没问题。如果是系统级应用,就会报错java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes解决办法有:1.使用 hookWebView() 方法欺骗系统;2.修改源代码;一.使用 hookWebView() 方法欺骗系统;使用 hookWebView()...

在 android 8.0 系统上,普通应用使用 WebView 时,正常使用没问题。
如果是系统级应用,就会报错

java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes

解决办法有:
1.使用 hookWebView() 方法欺骗系统;
2.修改源代码;

一.使用 hookWebView() 方法欺骗系统;

  1. 使用 hookWebView() 方法欺骗系统,然后在应用的 ApplicationonCreate() 里调用此方法。
	/**
     * 给WebViewFactory sProviderInstance赋值,避免进行进程判断而抛出异常(系统应用不能使用WebView)
     */
    @SuppressWarnings("unchecked")
    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);
        }
    }

2.我已经这样改了,又有新问题出现了。
在 Setting 应用中添加,提示 xxxx (具体的报错忘了);
删除 AndroidManifest.xml 文件里的 android:defaultToDeviceProtectedStorage="true"
测试之后发现,不用在 Application 里调用 hookWebView() 方法,
在使用 WebViewActivity 里调用也会生效。

二.修改源代码

搜索异常提示 "For security reasons, WebView is not allowed in privileged processes" 得知,
是在 frameworks/base/core/java/android/webkit/WebViewFactory.java
static WebViewFactoryProvider 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 = android.os.Process.myUid();
            if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID
                    || uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID
                    || uid == android.os.Process.BLUETOOTH_UID) {
                throw new UnsupportedOperationException(
                        "For security reasons, WebView is not allowed in privileged processes");
            }
            //省略其余代码
        }
   }

将该异常注释即可,当然,这样做不太好,谨慎。

本文地址:https://blog.csdn.net/weixin_44021334/article/details/107496721

相关标签: Android webview