Android block ads in webview

前端 未结 3 870
余生分开走
余生分开走 2020-12-06 03:07

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

相关标签:
3条回答
  • 2020-12-06 03:15

    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.
    0 讨论(0)
  • 2020-12-06 03:20

    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());
    
    0 讨论(0)
  • 2020-12-06 03:21

    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.

    0 讨论(0)
提交回复
热议问题