Android block ads in webview

[亡魂溺海] 提交于 2019-11-30 22:51:36

In your custom WebViewClient, you can override the function shouldInterceptRequest(WebView, WebResourceRequest).

From Android docs:

Notify the host application of a resource request and allow the application to return the data.

So the general idea is to check if the request is coming from an ad URL (plenty of black list filters out there), then return a "fake" resource that isn't the ad.

For a more in depth explanation plus an example, I recommend checking out this blog post.

To implement this, you have two options:

  1. Use Javascript injected code to do this (which you explicitely said, don't want)
  2. In WebView, instead of "http://example.com" load "http://myproxy.com?t=http://example.com" (properly escaped, of course) and setup "myproxy.com" to be a proxy which will fetch the upstream page (given in "t" query parameter, or in any other way) and replace ads with the trusted ones before sending response to the client. This will be pretty complex, though, because ads can be in many forms, they're usually Javascript injected themselves and you'd probably need to rewrite a lot of URL's in the fetched HTML, CSS and JS files etc.
Devangi

I made a custom WebViewClient like:

public class MyWebViewClient extends WebViewClient {

    @Override
    public void onPageFinished(WebView view, String url) { }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.endsWith(".mp4")) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse(url), "video/*");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            view.getContext().startActivity(intent);
            return true;
        } else if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:")
                || url.startsWith("mms:") || url.startsWith("mmsto:")) {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            view.getContext().startActivity(intent);
            return true;
        } else {
            return super.shouldOverrideUrlLoading(view, url);
        }
    }

    private Map<String, Boolean> loadedUrls = new HashMap<>();

    @SuppressWarnings("deprecation")
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        boolean ad;
        if (!loadedUrls.containsKey(url)) {
            ad = AdBlocker.isAd(url);
            loadedUrls.put(url, ad);
        } else {
            ad = loadedUrls.get(url);
        }
        return ad ? AdBlocker.createEmptyResource() :
                super.shouldInterceptRequest(view, url);
    }
}

And created an AdBlocker class like:

public class AdBlocker {
private static final Set<String> AD_HOSTS = new HashSet<>();

public static boolean isAd(String url) {
    try {
        return isAdHost(getHost(url));
    } catch (MalformedURLException e) {
        Log.e("Devangi..", e.toString());
        return false;
    }
}

private static boolean isAdHost(String host) {
    if (TextUtils.isEmpty(host)) {
        return false;
    }
    int index = host.indexOf(".");
    return index >= 0 && (AD_HOSTS.contains(host) ||
            index + 1 < host.length() && isAdHost(host.substring(index + 1)));
}

public static WebResourceResponse createEmptyResource() {
    return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes()));
}

public static String getHost(String url) throws MalformedURLException {
    return new URL(url).getHost();
}

}

And use this WebViewClient in your oncreate like:

 webview.setWebViewClient(new MyWebViewClient());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!