Android系統程序無法載入WebView
當系統程序載入WebView時會報錯:UnsupportedOperationException:
如下
java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:96) at android.webkit.WebView.getFactory(WebView.java:2194) at android.webkit.WebView.ensureProviderCreated(WebView.java:2189) at android.webkit.WebView.setOverScrollMode(WebView.java:2248) at android.view.View.<init>(View.java:3588) at android.view.View.<init>(View.java:3682) at android.view.ViewGroup.<init>(ViewGroup.java:497) at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55) at android.webkit.WebView.<init>(WebView.java:544) at android.webkit.WebView.<init>(WebView.java:489) at android.webkit.WebView.<init>(WebView.java:472) at android.webkit.WebView.<init>(WebView.java:459) at android.webkit.WebView.<init>(WebView.java:449)
通過log分析原因是:
因為安全問題,WebView禁止在系統程序中載入。這肯定是因為WebView眾所周知的安全漏洞,可以通過JSBridge調Android內部函式,從而引起安全問題
有興趣詳細瞭解這個問題可以移步這裡。 ofollow,noindex">WebView詳解及安全問題
原始碼分析:
在原始碼中看下異常丟擲的位置

WebViewFactory.jpg
程式碼具體位置 AndroidXref 注:android 8.0
通過程式碼發現當WebView啟動時調到這個getProvide函式,然後會判斷程序的uid,如果是上面那幾種就掛了。
解決辦法 -- HOOK
HOOK思路:在使用 WebView 之前,我們先 Hook WebViewFactory,建立 sProviderInstance 物件,從而繞過系統檢查。
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.debug("sProviderInstance isn't null"); return; } Method getProviderClassMethod; if (sdkInt > 22) { getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass"); } else if (sdkInt == 22) { getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass"); } else { log.info("Don't need to Hook WebView"); 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 = providerConstructor.newInstance(declaredConstructor.newInstance()); log.debug("sProviderInstance:{}", sProviderInstance); field.set("sProviderInstance", sProviderInstance); } log.debug("Hook done!"); } catch (Throwable e) { log.error(e); } }