前言
之前介绍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"); //}
参考文章
《
© 版权声明