Android API23-27 WebView点击自定义URL未触发回调的解决方法
解决WebView自定义URL(tvloc://)未触发回调的问题
这种自定义Scheme的URL没触发shouldOverrideUrlLoading等回调是WebView开发里的常见坑,我帮你梳理下核心原因和解决步骤:
1. 确保覆盖全版本的shouldOverrideUrlLoading回调
从API 24开始,WebView新增了带WebResourceRequest参数的shouldOverrideUrlLoading重载方法,而你需要兼容API23-27,所以必须同时重写两个版本的方法,否则API24+设备上可能不会触发旧版回调:
webView.setWebViewClient(new WebViewClient() { // 适配API < 24 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return handleCustomScheme(url); } // 适配API >= 24 @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); return handleCustomScheme(url); } // 统一处理自定义Scheme的逻辑 private boolean handleCustomScheme(String url) { // 检测是否是你的自定义tvloc Scheme if (url.startsWith("tvloc://")) { // 解析URL中的参数,比如lat和lng Uri uri = Uri.parse(url); String lat = uri.getQueryParameter("lat"); String lng = uri.getQueryParameter("lng"); // 这里写你需要的业务逻辑,比如解析位置、跳转原生页面等 Log.d("CustomURLHandler", "获取到位置:lat=" + lat + ", lng=" + lng); // 返回true表示自己处理该URL,阻止WebView继续加载 return true; } // 非自定义Scheme的URL,交给WebView默认处理 return false; } // 确保你的页面加载回调正常工作 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // 你的原有逻辑 } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 你的原有逻辑 } });
2. 检查WebSettings的关键配置
如果页面中的自定义链接是通过JavaScript触发的(比如window.location.href = 'tvloc://...'),或者存在target="_blank"的链接,需要开启对应的WebSettings:
WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // 启用JS,处理JS触发的跳转 webSettings.setSupportMultipleWindows(true); // 支持多窗口,处理target="_blank"的链接
3. 处理target="_blank"的自定义链接
如果页面中的自定义链接是在新窗口打开的(带target="_blank"),WebView会创建新的WebView实例,这时候需要重写WebChromeClient的onCreateWindow方法,给新窗口也绑定相同的WebViewClient,确保自定义Scheme被拦截:
webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { WebView newWebView = new WebView(view.getContext()); // 给新WebView绑定同样的WebViewClient,复用自定义Scheme处理逻辑 newWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView newView, String url) { return handleCustomScheme(url); } @Override public boolean shouldOverrideUrlLoading(WebView newView, WebResourceRequest request) { String url = request.getUrl().toString(); return handleCustomScheme(url); } }); // 传递新WebView的引用给系统 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(newWebView); resultMsg.sendToTarget(); return true; } });
4. 排除系统级拦截的可能
如果你的AndroidManifest中给当前Activity配置了tvloc Scheme的Intent Filter,系统可能会直接唤起你的应用而不是让WebView处理。如果不需要外部应用唤起你的应用处理该Scheme,可以暂时移除这个Intent Filter,或者在回调里优先处理。
按照上面的步骤调整后,你的自定义tvloc://链接应该就能正常触发回调并被拦截处理了。
内容的提问来源于stack exchange,提问作者Satyam
相关产品推荐
相关产品推荐

