Android 当apk是系统应用时,无法使用webView的解决方案

发布于:2025-06-23 ⋅ 阅读:(19) ⋅ 点赞:(0)

最近在做项目时,遇到了一个无法使用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";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "==onReceive==");
            if (!Myapplication.isHookSuccess) {
                Myapplication.hookWebView();
            }
        }

    }
}

以上就是解决的思路和方法,留着以后备用。


网站公告

今日签到

点亮在社区的每一天
去签到