Android WebView中动态创建a标签触发onCreateWindow时URL为null的问题
解决Android WebView捕获未插入DOM的动态a标签跳转URL问题
方案1:注入JavaScript拦截所有a标签点击行为
针对动态创建、未插入DOM就触发click的a标签,可通过注入JS覆盖原生点击方法,提前拦截target="_blank"的跳转URL并传递给原生层。
示例代码:
// 开启JS支持 webView.getSettings().setJavaScriptEnabled(true); // 注册JS与原生交互的接口 webView.addJavascriptInterface(new Object() { @JavascriptInterface public void handleBlankTargetUrl(String url) { // 在这里处理捕获到的跳转URL,比如打开新窗口或自定义逻辑 Log.d("WebView", "捕获到跳转URL: " + url); } }, "AndroidWebViewBridge"); // 注入拦截用的JS代码 String injectScript = "(" + "function() {" + "const originalClick = HTMLElement.prototype.click;" + "HTMLElement.prototype.click = function() {" + "if(this.tagName === 'A' && this.target === '_blank' && this.href) {" + "AndroidWebViewBridge.handleBlankTargetUrl(this.href);" + "return; // 阻止默认跳转,避免重复触发onCreateWindow" + "}" + "originalClick.call(this);" + "};" + "})();"; webView.loadUrl("javascript:" + injectScript);
注意:需确保JS注入时机(如页面加载完成后),若页面有CSP限制,需调整WebView设置允许脚本注入。
方案2:重写onCreateWindow,通过新WebView拦截跳转URL
放弃依赖requestFocusNodeHref(),直接在onCreateWindow中创建新WebView,通过其shouldOverrideUrlLoading方法捕获跳转URL,无论原a标签是否插入DOM都能生效。
示例代码:
@Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { WebView newWebView = new WebView(view.getContext()); newWebView.getSettings().setJavaScriptEnabled(true); newWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String targetUrl = request.getUrl().toString(); // 处理捕获到的URL Log.d("WebView", "新窗口跳转URL: " + targetUrl); view.loadUrl(targetUrl); return true; } }); // 将新WebView绑定到结果消息 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(newWebView); resultMsg.sendToTarget(); return true; }
该方式无需依赖DOM节点状态,兼容性更强,适合大多数场景。
注意事项
- 使用
addJavascriptInterface时,需遵循Android安全规范:Android 4.2+必须添加@JavascriptInterface注解,避免暴露敏感方法。 - 若页面启用CSP,需在WebView设置中添加允许的脚本源,否则注入JS会被拦截。
内容的提问来源于stack exchange,提问作者Hư Vũ
相关产品推荐
相关产品推荐

