前言

之前介绍Android系统应用使用WebView时,出现异常。如果有Android源码且可以编译,那就改源码(注释掉而已,这种比较方便),方便系统应用;如果没有那就使用hook方式。这里简单记录一下,方便自己查阅。

正文

异常打印

主要的AndroidRuntime日志打印

AndroidRuntime: Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
AndroidRuntime:        at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:235)
AndroidRuntime:        at android.webkit.WebView.getFactory(WebView.java:2681)
AndroidRuntime:        at android.webkit.WebView.ensureProviderCreated(WebView.java:2676)
AndroidRuntime:        at android.webkit.WebView.setOverScrollMode(WebView.java:2741)
AndroidRuntime:        at android.view.View.<init>(View.java:4807)
AndroidRuntime:        at android.view.View.<init>(View.java:4948)
AndroidRuntime:        at android.view.ViewGroup.<init>(ViewGroup.java:661)
AndroidRuntime:        at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
AndroidRuntime:        at android.webkit.WebView.<init>(WebView.java:659)
AndroidRuntime:        at android.webkit.WebView.<init>(WebView.java:604)
AndroidRuntime:        at android.webkit.WebView.<init>(WebView.java:587)
AndroidRuntime:        at android.webkit.WebView.<init>(WebView.java:574)

hook

@SuppressLint({"PrivateApi", "SoonBlockedPrivateApi", "DiscouragedPrivateApi"})
public 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 (null != factoryProviderClass) {
            if (sdkInt < 26) {//低于Android O版本
                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
                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);
                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);
    }
}

onCreate()中setContentView()之前调用即可

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //
    hookWebView();
    setContentView(R.layout.activity_main);
    Log.d(TAG, "onCreate: ");
}

亲测有效。

改源码

frameworks/base/core/java/android/webkit/WebViewFactory.java

然后找到

For security reasons, WebView is not allowed in privileged processes

相关地方。

如下,比较粗暴哈。

sTimestamps.mWebViewLoadStart = SystemClock.uptimeMillis();
final int uid = android.os.Process.myUid();
//这里根据获取的uid进行判断,显示粗暴的解决方式。
//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");
//}

参考文章

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

相关文章

暂无评论

none
暂无评论...