博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android开发:系统进程中使用Webview引发异常的处理
阅读量:6048 次
发布时间:2019-06-20

本文共 3394 字,大约阅读时间需要 11 分钟。

我司开发的产品一般都是系统应用,即在
AndroidManifest.xml中配置了
android:sharedUserId="android.uid.system",最近在布局开发中使用了 Webview,然而程序在运行时直接 carsh 了,查看 log,报错信息如下:

Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processesat 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 点。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 功能十分强大,远非三言两语可以讲清楚,大家有兴趣可以进一步学习了解。

转载地址:http://qqxex.baihongyu.com/

你可能感兴趣的文章
git简单命令
查看>>
LAMP编译部署
查看>>
XenDesktop7.6安装部署入门教程
查看>>
HashMap的工作原理及HashMap和Hashtable的区别
查看>>
GregorianCalendar日历程序
查看>>
Sublime 中运行 Shell 、Python、Lua、Groovy...等各种脚本
查看>>
【Java集合源码剖析】ArrayList源码剖析
查看>>
linux的目录结构
查看>>
这次逻辑通了,
查看>>
HTMLHelper
查看>>
快速构建Windows 8风格应用29-捕获图片与视频
查看>>
OC语言Block和协议
查看>>
使用xpath时出现noDefClass的错误(找不到某个类)
查看>>
.Net规则引擎介绍 - REngine
查看>>
CSS3 transforms 3D翻开
查看>>
利用传入的Type类型来调用范型方法的解决方案
查看>>
Top命令内存占用剖析
查看>>
转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
查看>>
求带分数(蓝桥杯)
查看>>
Retrofit 入门学习
查看>>