You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android SDK注入JS至WebView时,Cordova8 SystemWebView的setWebViewClient异常

解决Cordova 8下WebView注入JavaScript的问题

我太懂你遇到的这个坑了——在普通Android WebView上顺顺当当的JS注入逻辑,到了Cordova 8的org.apache.cordova.engine.SystemWebView直接失效。核心问题就出在这个WebView子类重写了setWebViewClient()方法,它强制要求使用自家的SystemWebViewClient子类,你直接塞自定义的WebViewClient要么被拒绝,要么会冲掉Cordova的原有逻辑,两边都乱套。

下面给你两个靠谱的解决方案:

方案一:顺着Cordova的规则来——继承SystemWebViewClient

既然Cordova卡着必须用它的WebViewClient子类,那我们就按它的规矩办,继承SystemWebViewClient包装原有逻辑,再插进去自己的注入代码:

// 假设你已经通过枚举UI拿到了目标SystemWebView实例
SystemWebView cordovaWebView = (SystemWebView) targetWebView;

// 自定义WebViewClient,继承Cordova的SystemWebViewClient
class CustomCordovaWebClient extends SystemWebViewClient {
    private final SystemWebViewClient originalClient;
    private final String injectScript;

    public CustomCordovaWebClient(SystemWebEngine engine, SystemWebViewClient originalClient, String injectScript) {
        super(engine);
        this.originalClient = originalClient;
        this.injectScript = injectScript;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        // 先执行Cordova原有Client的onPageFinished,保证应用原有功能正常
        if (originalClient != null) {
            originalClient.onPageFinished(view, url);
        }
        // 执行你的JS注入
        view.evaluateJavascript(injectScript, null);
        // 别忘了调用父类方法
        super.onPageFinished(view, url);
    }
}

// 获取Cordova原来的WebViewClient
SystemWebViewClient originalClient = cordovaWebView.getSystemWebViewClient();
// 创建自定义Client并设置
CustomCordovaWebClient customClient = new CustomCordovaWebClient(
        cordovaWebView.getEngine(),
        originalClient,
        "console.log('注入的JS代码执行啦');"
);
cordovaWebView.setWebViewClient(customClient);

这个方案的好处是完全兼容Cordova的原有逻辑,不会破坏Cordova应用的正常运行,属于最稳妥的做法。

方案二:用动态代理Hook原有WebViewClient

如果不想替换整个WebViewClient,也可以用反射+动态代理的方式,在原有Client的onPageFinished方法执行前后插入你的注入逻辑:

WebView targetWebView = ...; // 你的目标WebView实例
WebViewClient originalClient = targetWebView.getWebViewClient();
final String injectScript = "console.log('注入的JS代码执行啦');";

// 创建动态代理对象
WebViewClient proxyClient = (WebViewClient) Proxy.newProxyInstance(
        WebViewClient.class.getClassLoader(),
        new Class[]{WebViewClient.class},
        (proxy, method, args) -> {
            // 先执行原Client的方法
            Object result = method.invoke(originalClient, args);
            // 判断是否是onPageFinished方法
            if ("onPageFinished".equals(method.getName()) && args.length == 2) {
                WebView view = (WebView) args[0];
                // 执行JS注入
                view.evaluateJavascript(injectScript, null);
            }
            return result;
        }
);

// 设置代理后的Client
targetWebView.setWebViewClient(proxyClient);

⚠️ 注意:如果Cordova的setWebViewClient方法做了严格的类型校验(比如只允许SystemWebViewClient实例),这个方案会抛出IllegalArgumentException,此时优先选方案一。

额外小提醒

  • 尽量用evaluateJavascript()代替loadUrl("javascript:..."),前者是Android 4.4+的推荐方式,更安全还支持回调。
  • 如果要注入的JS代码很长,建议把代码放在assets目录,读取后再注入,避免字符串拼接的麻烦。

内容的提问来源于stack exchange,提问作者leon karabchesvky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:01:20