原因
在具有系統(tǒng)級(jí)權(quán)限的應(yīng)用中使用 WebView 時(shí)匀泊,可能會(huì)遇到 java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 錯(cuò)誤。這是因?yàn)槌鲇诎踩紤]朵你,Android 不允許在擁有系統(tǒng)權(quán)限的應(yīng)用中使用 WebView。
解決方案
在setContentView之前調(diào)用以下hookWebView方法即可
const val TAG = "hookWebView"
private fun hookWebView() {
val sdkInt = Build.VERSION.SDK_INT
try {
val factoryClass = Class.forName("android.webkit.WebViewFactory")
val field = factoryClass.getDeclaredField("sProviderInstance")
field.isAccessible = true
var sProviderInstance = field[null]
if (sProviderInstance != null) {
Log.i(TAG, "sProviderInstance isn't null")
return
}
val getProviderClassMethod = if (sdkInt > 22) {
factoryClass.getDeclaredMethod("getProviderClass")
} else if (sdkInt == 22) {
factoryClass.getDeclaredMethod("getFactoryClass")
} else {
Log.i(TAG, "Don't need to Hook WebView")
return
}
getProviderClassMethod.isAccessible = true
val factoryProviderClass = getProviderClassMethod.invoke(factoryClass) as Class<*>
val delegateClass = Class.forName("android.webkit.WebViewDelegate")
val delegateConstructor = delegateClass.getDeclaredConstructor()
delegateConstructor.isAccessible = true
if (sdkInt < 26) { //低于Android O版本
val providerConstructor = factoryProviderClass.getConstructor(delegateClass)
if (providerConstructor != null) {
providerConstructor.isAccessible = true
sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance())
}
} else {
val chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD")
chromiumMethodName.isAccessible = true
var chromiumMethodNameStr = chromiumMethodName[null] as String
if (chromiumMethodNameStr == null) {
chromiumMethodNameStr = "create"
}
val staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass)
if (staticFactory != null) {
sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance())
}
}
if (sProviderInstance != null) {
field["sProviderInstance"] = sProviderInstance
Log.i(TAG, "Hook success!")
} else {
Log.i(TAG, "Hook failed!")
}
} catch (e: Throwable) {
Log.w(TAG, e)
}
}