Skip to content Skip to sidebar Skip to footer

Android Block Ads In Webview

I want to implement a mechanism in a custom webview client (without JavaScript injection) that can block ads. Is a way I can catch ads and replace them with other ads from a truste

Solution 1:

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.

Solution 2:

I made a custom WebViewClient like:

publicclassMyWebViewClientextendsWebViewClient {

    @OverridepublicvoidonPageFinished(WebView view, String url) { }

    @OverridepublicbooleanshouldOverrideUrlLoading(WebView view, String url) {
        if (url.endsWith(".mp4")) {
            Intent intent = newIntent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse(url), "video/*");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            view.getContext().startActivity(intent);
            returntrue;
        } elseif (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:")
                || url.startsWith("mms:") || url.startsWith("mmsto:")) {
            Intent intent = newIntent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            view.getContext().startActivity(intent);
            returntrue;
        } else {
            returnsuper.shouldOverrideUrlLoading(view, url);
        }
    }

    privateMap<String, Boolean> loadedUrls = newHashMap<>();

    @SuppressWarnings("deprecation")
    @OverridepublicWebResourceResponseshouldInterceptRequest(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:

publicclassAdBlocker {
privatestatic final Set<String> AD_HOSTS = newHashSet<>();

publicstaticbooleanisAd(String url) {
    try {
        returnisAdHost(getHost(url));
    } catch (MalformedURLException e) {
        Log.e("Devangi..", e.toString());
        returnfalse;
    }
}

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

publicstaticWebResourceResponsecreateEmptyResource() {
    returnnewWebResourceResponse("text/plain", "utf-8", newByteArrayInputStream("".getBytes()));
}

publicstaticStringgetHost(String url) throws MalformedURLException {
    returnnewURL(url).getHost();
}

}

And use this WebViewClient in your oncreate like:

 webview.setWebViewClient(newMyWebViewClient());

Solution 3:

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.

Post a Comment for "Android Block Ads In Webview"