Browse Source

解决app共用system uid时使用webview报java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 错误

weizhengliang 1 year ago
parent
commit
348e8168d4

+ 72 - 3
android_bed/src/main/java/com/wdkl/app/ncs/callingbed/activity/WebviewActivity.kt

@@ -22,12 +22,22 @@ import kotlinx.android.synthetic.main.webciew_lay.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.greenrobot.eventbus.ThreadMode
+import java.lang.reflect.Constructor
+import java.lang.reflect.Field
+import java.lang.reflect.Method
 
 
 
 
 @Router(path = "/callingbed/webview")
 @Router(path = "/callingbed/webview")
 class WebviewActivity :BaseActivity<BedWebviewActivityPresenter, WebciewLayBinding>(), BedWebViewActivityContract.View{
 class WebviewActivity :BaseActivity<BedWebviewActivityPresenter, WebciewLayBinding>(), BedWebViewActivityContract.View{
     private val TAG = "WebviewActivity"
     private val TAG = "WebviewActivity"
     override fun getLayId(): Int {
     override fun getLayId(): Int {
+        // 解决共用system uid时报
+        // Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 错误
+        val uid = android.os.Process.myUid()
+        if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID) {
+            hookWebView()
+        }
+
         return R.layout.webciew_lay
         return R.layout.webciew_lay
     }
     }
 
 
@@ -50,13 +60,72 @@ class WebviewActivity :BaseActivity<BedWebviewActivityPresenter, WebciewLayBindi
         if (url!=null && key!=null){
         if (url!=null && key!=null){
             val result = key.replace("&amp;", "&")
             val result = key.replace("&amp;", "&")
             Log.d(TAG, "更新后的 url_params_temp 值为:"+url+"?"+result)
             Log.d(TAG, "更新后的 url_params_temp 值为:"+url+"?"+result)
-            webview.loadUrl(url+"?"+result);
+            webview.loadUrl(url+"?"+result)
         }
         }
 //        webview.loadUrl("https://www.baidu.com/");
 //        webview.loadUrl("https://www.baidu.com/");
         //带参数
         //带参数
 //        webview.loadDataWithBaseURL(HttpConstant.PATH, content, "text/html", "UTF-8", null);
 //        webview.loadDataWithBaseURL(HttpConstant.PATH, content, "text/html", "UTF-8", null);
     }
     }
 
 
+    fun hookWebView() {
+        val sdkInt = Build.VERSION.SDK_INT
+        try {
+            val factoryClass = Class.forName("android.webkit.WebViewFactory")
+            val field: Field = factoryClass.getDeclaredField("sProviderInstance")
+            field.setAccessible(true)
+            var sProviderInstance: Any? = field.get(null)
+            if (sProviderInstance != null) {
+                Log.i(TAG, "sProviderInstance isn't null")
+                return
+            }
+            val getProviderClassMethod: Method
+            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)
+            val factoryProviderClass = getProviderClassMethod.invoke(factoryClass) as Class<*>
+            val delegateClass = Class.forName("android.webkit.WebViewDelegate")
+            val delegateConstructor: Constructor<*> = delegateClass.getDeclaredConstructor()
+            delegateConstructor.setAccessible(true)
+            if (sdkInt < 26) { //低于Android O版本
+                val providerConstructor: Constructor<*>? =
+                    factoryProviderClass.getConstructor(delegateClass)
+                if (providerConstructor != null) {
+                    providerConstructor.setAccessible(true)
+                    sProviderInstance =
+                        providerConstructor.newInstance(delegateConstructor.newInstance())
+                }
+            } else {
+                val chromiumMethodName: Field =
+                    factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD")
+                chromiumMethodName.setAccessible(true)
+                var chromiumMethodNameStr = chromiumMethodName.get(null)
+                if (chromiumMethodNameStr == null) {
+                    chromiumMethodNameStr = "create"
+                }
+                val staticFactory: Method? =
+                    factoryProviderClass.getMethod(chromiumMethodNameStr as String, 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 (e: Throwable) {
+            Log.w(TAG, e)
+        }
+    }
+
     override fun bindEvent() {
     override fun bindEvent() {
         back_btn.setOnClickListener {
         back_btn.setOnClickListener {
             finish()
             finish()
@@ -101,9 +170,9 @@ class WebviewActivity :BaseActivity<BedWebviewActivityPresenter, WebciewLayBindi
 
 
     override fun onBackPressed() {
     override fun onBackPressed() {
         if (webview.canGoBack()) {
         if (webview.canGoBack()) {
-            webview.goBack();
+            webview.goBack()
         } else {
         } else {
-            this.finish();
+            this.finish()
         }
         }
     }
     }
     private fun webviewSetting(webSettings: WebSettings) {
     private fun webviewSetting(webSettings: WebSettings) {

+ 2 - 0
android_bed/src/main/java/com/wdkl/app/ncs/callingbed/fragment/NursingWorkFragment.kt

@@ -211,6 +211,8 @@ NursingWorkFragment : BaseFragment<BedNursingWorkFragmentPresenter, NursingWorkL
                     showMessage("暂未开通")
                     showMessage("暂未开通")
                 }
                 }
 
 
+            } else {
+                showMessage("类型错误")
             }
             }
         } catch (e: Exception) {
         } catch (e: Exception) {
             showMessage("结果异常,请在后台设置")
             showMessage("结果异常,请在后台设置")