在 android 8.0 系统上,普通应用使用 WebView 时,正常使用没问题。
如果是系统级应用,就会报错
java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
解决办法有:
1.使用 hookWebView()
方法欺骗系统;
2.修改源代码;
hookWebView()
方法欺骗系统;hookWebView()
方法欺骗系统,然后在应用的 Application
的 onCreate()
里调用此方法。 /**
* 给WebViewFactory sProviderInstance赋值,避免进行进程判断而抛出异常(系统应用不能使用WebView)
*/
@SuppressWarnings("unchecked")
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);
}
}
2.我已经这样改了,又有新问题出现了。
在 Setting 应用中添加,提示 xxxx (具体的报错忘了);
删除 AndroidManifest.xml
文件里的 android:defaultToDeviceProtectedStorage="true"
。
测试之后发现,不用在 Application
里调用 hookWebView()
方法,
在使用 WebView
的 Activity
里调用也会生效。
搜索异常提示 "For security reasons, WebView is not allowed in privileged processes"
得知,
是在 frameworks/base/core/java/android/webkit/WebViewFactory.java
的
static WebViewFactoryProvider getProvider() {}
方法中抛出的,
static WebViewFactoryProvider getProvider() {
synchronized (sProviderLock) {
// For now the main purpose of this function (and the factory abstraction) is to keep
// us honest and minimize usage of WebView internals when binding the proxy.
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");
}
//省略其余代码
}
}
将该异常注释即可,当然,这样做不太好,谨慎。
本文地址:https://blog.csdn.net/weixin_44021334/article/details/107496721
如对本文有疑问, 点击进行留言回复!!
网友评论