Android Webview的shouldOverrideUrlLoading方法在Android10及以上版本失效问题
问题根因
Android 10(API 级别 29)及以上版本中,WebView对**同页面内的锚点跳转(href属性为#开头的同文档定位链接)**默认归类为内部导航动作,不再触发shouldOverrideUrlLoading的任意重载方法,因此原有的重写逻辑无法捕获这类请求。
可行解决方案
- 方案1:通过
WebViewClient的doUpdateVisitedHistory方法监听所有URL变化(包括锚点跳转)
该方法在WebView访问历史更新时都会回调,锚点变化也会触发回调,可适配全版本系统,代码示例:
@Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { super.doUpdateVisitedHistory(view, url, isReload); // 此处可拿到变化后的完整url(包含锚点后缀),执行自定义逻辑 if (url.contains("#")) { // 锚点跳转场景的业务处理逻辑 } }
- 方案2:注入JS接口精准监听锚点点击
如果需要单独捕获锚点的点击事件而非所有URL变化,可以给WebView开启JS支持,注入原生交互接口,页面加载完成后遍历所有锚点链接绑定点击回调,代码示例:
第一步配置WebView参数:
webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new AnchorClickInterface(), "AndroidBridge"); webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 页面加载完成后注入锚点监听的JS代码 view.loadUrl("javascript:" + "document.querySelectorAll('a[href^=\"#\"]').forEach(anchor => {" + " anchor.addEventListener('click', function() {" + " AndroidBridge.onAnchorClick(this.getAttribute('href'));" + " });" + "});"); } });
第二步定义原生交互接口:
public class AnchorClickInterface { @JavascriptInterface public void onAnchorClick(String anchorHref) { // 此处可拿到点击的锚点链接,执行自定义逻辑 } }
原有代码优化提示
你原有重写shouldOverrideUrlLoading的逻辑存在冗余:调用view.loadUrl(url)后返回false,返回false代表WebView会自行处理该URL加载,重复调用loadUrl会造成不必要的二次加载。如果不需要拦截跳转仅需要采集URL做埋点等操作,直接返回false即可不需要手动调用loadUrl;如果需要拦截跳转自行处理,调用loadUrl后返回true即可。
内容的提问来源于stack exchange,提问作者Sun
相关产品推荐
相关产品推荐

