Android 当apk是系统应用时,无法使用webView的解决方案
最近在做项目时,遇到了一个无法使用webView的问题,apk是系统应用,点击加载webView时应用就是崩溃,原因是系统应用时,Android会觉得webView不安全,不避让加载。
解决的思路就是使用映射,把原生的拦截设置为ture,不让系统拦截。
设置hook代码如下
public static void hookWebView() {Log.i(TAG, "==hookWebView start==");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;getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");getProviderClassMethod.setAccessible(true);Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();delegateConstructor.setAccessible(true);@SuppressLint("SoonBlockedPrivateApi") 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!");isHookSuccess = true;} else {Log.i(TAG, "Hook failed!");isHookSuccess = false;}} catch (Throwable e) {Log.w(TAG, e);}}
此方法还需要时机,如果加载太晚或者太早也会不生效,要在Android原生设置属性前,并且isUserUnlocked后调用。
我本项目是在三个地方多次调用了
1、第一个地方是Myapplication的onCreate方法里面并判断了isUserUnlocked
boolean isUserUnlock = getSystemService(UserManager.class).isUserUnlocked();if (isUserUnlock) {Myapplication.hookWebView();}
2、在MainActivity的onCreate方法里面
if (!Myapplication.isHookSuccess) {Myapplication.hookWebView();}
3、在开机广播里面
public class ReceiverLocalSetting extends BroadcastReceiver {private static final String TAG = "ReceiverLocalSetting";private static final String USER_UNLOCKED_ACTION = "android.intent.action.USER_UNLOCKED";@Overridepublic void onReceive(Context context, Intent intent) {Log.i(TAG, "==onReceive==");if (!Myapplication.isHookSuccess) {Myapplication.hookWebView();}}}
}
以上就是解决的思路和方法,留着以后备用。