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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:06:41