You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用shouldInterceptRequest拦截URL?求Android广告拦截App开发帮助

如何用shouldInterceptRequest拦截WebView中的广告JS请求

嘿,刚好我之前做过类似的WebView广告拦截功能,给你梳理下具体的实现步骤和代码细节,应该能帮你解决问题!

核心原理

shouldInterceptRequestWebViewClient提供的回调方法,当WebView准备加载任何资源(JS、图片、CSS等)时都会触发这个回调。我们可以在这里对请求的URL进行校验,判断是否属于需要拦截的广告资源,然后返回空响应来阻止加载。

具体实现代码

1. 定义禁止的广告域名列表

首先我们需要维护一个预定义的广告域名集合,用HashSet来存储可以保证高效的查询速度:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

// 预定义需要拦截的广告域名,你可以根据自己的需求添加或修改
private static final Set<String> BLOCKED_AD_DOMAINS = new HashSet<>(Arrays.asList(
    "ad.example.com",
    "ads.tracker.net",
    "cdn.adnetwork.com",
    "analytics.adcompany.org"
));

2. 自定义WebViewClient并重写拦截方法

我们需要同时兼容低版本(API < 21)和高版本(API 21+)的shouldInterceptRequest方法,确保在不同系统版本上都能正常工作:

import android.annotation.TargetApi;
import android.os.Build;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.net.URI;
import java.net.URISyntaxException;

webView.setWebViewClient(new WebViewClient() {
    // 兼容Android 5.0以下的版本
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if (isBlockableRequest(url)) {
            // 返回空响应,阻止WebView加载该资源
            return new WebResourceResponse(null, null, null);
        }
        return super.shouldInterceptRequest(view, url);
    }

    // Android 5.0及以上推荐使用这个方法,能获取更详细的请求信息
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        String url = request.getUrl().toString();
        if (isBlockableRequest(url)) {
            return new WebResourceResponse(null, null, null);
        }
        return super.shouldInterceptRequest(view, request);
    }

    // 核心判断逻辑:判断当前请求是否需要被拦截
    private boolean isBlockableRequest(String url) {
        // 第一步:先判断是不是JS请求(只拦截.js资源)
        boolean isJsResource = url.toLowerCase().endsWith(".js");
        if (!isJsResource) {
            return false;
        }

        // 第二步:解析URL中的域名,判断是否在禁止列表中
        try {
            URI uri = new URI(url);
            String domain = uri.getHost();
            if (domain == null) {
                return false;
            }
            // 这里可以根据需求调整匹配逻辑,比如拦截子域名的话可以用domain.endsWith(".ad.example.com")
            return BLOCKED_AD_DOMAINS.contains(domain);
        } catch (URISyntaxException e) {
            // URL解析失败,不拦截
            e.printStackTrace();
            return false;
        }
    }
});

关键注意事项

  • 域名匹配的灵活性:如果需要拦截某个域名的所有子域名(比如sub.ad.example.comabc.ad.example.com),可以把判断逻辑改成domain.endsWith(".ad.example.com"),而不是直接匹配完整域名。
  • 避免网站异常:有些网站依赖某些JS资源,盲目拦截可能导致页面加载异常。你可以先测试拦截效果,或者返回一个空白的JS文件(比如创建一个空的InputStream传入WebResourceResponse)来替代直接返回null。
  • 性能优化:使用HashSet存储禁止域名,因为它的查询时间复杂度是O(1),比ArrayList的线性查找效率高很多,尤其是当禁止域名数量较多时。
  • 动态更新域名:如果需要支持用户自定义拦截域名,建议使用线程安全的集合(比如ConcurrentHashMap或者CopyOnWriteArraySet),避免在更新域名时出现并发问题。
  • 其他资源拦截:如果之后需要拦截图片、CSS等其他广告资源,只需要修改isBlockableRequest中的判断条件,比如添加url.toLowerCase().endsWith(".png")来拦截图片。

内容的提问来源于stack exchange,提问作者Leonar Aung

火山引擎 最新活动