1.问题起源
报错语句是:java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
因难以避免WebView存在安全漏洞,系统遭受攻击,Android不允许特权进程应用使用WebView。如果使用了,便会抛出以上异常。
特权进程包括sharedUserId为ROOT_UID和SYSTEM_UID的进程,从Android O(8.0)开始共享PHONE_UID、NFC_UID、BLUETOOTH_UID的进程也属于特权进程。
如果不幸,你的应用共享了以上的UserId,又有使用WebView,将会Crash掉,并抛出异常。下面提供一种Hook代码的方法,可以不用修改sharedUserId且避免Crash。
不过为了安全起见,还是不建议在Google规定的特权进程里继续使用WebView。下面提供的方案仅供不方便很快去掉WebView,临时避免Crash使用。
2.解决方法
请自行搜索了解为什么会想起这样解决,我是分析了Android8.0 frameworks源码,对网上的方法进行了改进,以使其在Android 8.0(SDK版本号为26)上使用.
在你的Application OnCreate方法里调用下面的方法即可。
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);}}
