Android开发:系统进程中使用Webview引发异常的处理

栏目: IOS · Android · 发布时间: 5年前

内容简介:,最近在布局开发中使用了 Webview,然而程序在运行时直接 carsh 了,查看 log,报错信息如下:原来是 Android 官方为了安全考虑,不允许特权进程(即系统进程)中使用 Webview。可是我们确实需要使用 Webview 该怎么办呢?跟踪源码发现在
Android开发:系统进程中使用Webview引发异常的处理
我司开发的产品一般都是系统应用,即在 AndroidManifest.xml 中配置了 android:sharedUserId="android.uid.system"

,最近在布局开发中使用了 Webview,然而程序在运行时直接 carsh 了,查看 log,报错信息如下:

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。可是我们确实需要使用 Webview 该怎么办呢?

跟踪源码发现在 WebViewFactory 类中的 getProvider() 方法中有如下代码(API版本:26):

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");
}
复制代码

可以看到第一次使用时,系统会检查 sProviderInstance 是否为空,不为空的话直接返回创建过的实例,否则就判断当前 uid,如果是 Root/System/Phone/NFC/Bluetooth 的话就会抛出异常。 sProviderInstanceWebViewFactoryProvider 的对象,那么,我们可以考虑提前创建 sProviderInstance 实例,这样就可以绕过系统检查,从而避免异常的抛出。

这时候就需要用到我们的 Hook 思想了,首先我们需要找到一个合适的 Hook 点。 sProviderInstance 是 static 变量,恰恰是一个非常合适的 Hook 点。这里需要用到反射的方法,代码如下:

/**
     * 避免系统检查抛出异常
     */
    public static void checkWebView() {
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            //拿到 WebViewFactory 类
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            //拿到类对应的 field
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            //field为private,设置为可访问的
            field.setAccessible(true);
            //拿到 WebViewFactory 的 sProviderInstance 实例
            //sProviderInstance 是 static 类型,不需要传入具体对象
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                return;
            }
            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> providerClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> providerConstructor = providerClass.getConstructor(delegateClass);
            if (providerConstructor != null) {
                providerConstructor.setAccessible(true);
                Constructor<?> declaredConstructor = delegateClass.getDeclaredConstructor();
                declaredConstructor.setAccessible(true);
                //利用反射创建了 sProviderInstance
                sProviderInstance = providerConstructor.newInstance(declaredConstructor.newInstance());
                //完成 sProviderInstance 赋值
                field.set("sProviderInstance", sProviderInstance);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
复制代码

这样我们就完成了 checkWebView() 方法,在使用WebView前只需要调用一次 checkWebView() 方法就可以成功绕过系统的检查,顺利在系统进程里使用WebView。

总结:在解决这次问题的过程中最大的收获是了解并使用了 HookHook 功能十分强大,远非三言两语可以讲清楚,大家有兴趣可以进一步学习了解。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

写给大忙人看的C++

写给大忙人看的C++

【美】Brian Overland(布莱恩.奥弗兰德) / 卢涛、李颖 / 电子工业出版社 / 2015-8 / 109.00

《写给大忙人看的C++》全面介绍了C++语言知识,既提供了学习C++语言最新功能的捷径,也为快速找到特定问题的答案提供了便利。《写给大忙人看的C++》简明地描述了C++核心语言和标准库中几乎所有的函数、对象和运算符,一目了然地显示了语法、结构和重要函数的信息,内容组织形式便于快速查找信息。《写给大忙人看的C++》精选了实用的例子来深入地讲解概念,还提供了富有挑战性的练习及参考答案,便于读者举一反三......一起来看看 《写给大忙人看的C++》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具