Developing for Android is really fun, as you have probably noticed if you want to have a wide user base you will have to give your application for free on the Android Market. From there, you have different way to monetize your application, you can limit features and unlock them in a payed version, display ads in free version and provide a way to disable ads (in-app purchase for example). In this article I will explain how to detect ad blocking in your applications.

Ad blocking ?

The way you try to monetize app will not be well accepted by everyone. Often, people use an Ad-Blocker (the same we know in web browsers) and will use the application for free as if they bought your ad free version. A rapid search on the Android market will point you to free application allowing to block ads on rooted devices.

The system is quite simple, it consists in blocking ads by preventing DNS resolution process to work properly. Ads are loaded from a certain website on the internet. The system does a DNS query to resolve the IP adress of the remote site, the DNS resolution process can be accelerated by setting entries in the hosts file (/etc/hosts under *nix and so Android). If the system found a corresponding entry in the file, it does not waste time in querying DNS servers and use the specified address.

127.0.0.1 localhost
127.0.0.1 my.ad.server.tld

You can find an example above, my.ad.server.tld is blocked by making the system think the IP is the one corresponding to the device.

Workaround

I will explain by a few code snippets how to detect ad blocking using the AdMob SDK. The first thing to do is not bound to the use of AdMob, we will simply read and detect if your ad provider server is in the hosts file.

public static boolean isAdBlockerPresent(boolean showAd) {
        if (showAd){
           BufferedReader in = null;
           try {
               in = new BufferedReader(new InputStreamReader(
                                                            new FileInputStream("/etc/hosts")));
               String line;

               while ((line = in.readLine()) != null) {
                  if (line.contains("admob")) {
                      return true;
                  }
                }
           } catch (Exception e) {
           } finally {
               if (in != null) {
                   try {
                       in.close();
                   } catch (IOException e) {
                   }
               }
           }
        }
        return false;
    }

The code is pretty straightforward, the method takes a boolean parameter allowing to bypass checking, and checks if the keyword "admob" is present in the hosts file. The good thing is that it does not require any specific permission to read the hosts file where you have to request root to write to it.

To be efficient, you may want to check if ad blocking is enabled only when there is an error in ad download. The Admob SDK provides a convenient way to know when the download fail by implementing a listener. You can find a simple implementation below, you will only have to implements the behavior you want to adopt when ad blocking is detected (onAdBlocked()) and the logic to bypass adblocker checking (shouldCheckAdBlock())

.
import com.google.ads.AdListener;
public abstract class AdBlockerListener implements AdListener{

    public abstract void onAdBlocked();

    public boolean shouldCheckAdBlock(){
          return true;
    }

    public void onReceiveAd(final Ad ad) {
    }

    public void onFailedToReceiveAd(final Ad ad, final AdRequest.ErrorCode errorCode) {
        Log.e("AdBlockerListener", "Failed to receive ad, checking if network blocker is installed...");
        if (isAdBlockerPresent(shouldCheckAdBlock())) {
               Log.e("AdBlockerListener", "Ad blocking seems enabled, tracking attempt");
               onAdBlocked();
            }
        } else {
            Log.e("AdBlockerListener", "No ad blocking detected, silently fails");
        }
    }

    public void onPresentScreen(final Ad ad) {
    }

    public void onDismissScreen(final Ad ad) {
    }

    public void onLeaveApplication(final Ad ad) {
    }
}

In your activity displaying ads, you just have to register the listener in your AdView and you're gone. The code sample below shows how to do, feel free to nag your users and pointing them to the in-app purchase or force them to quit (do it every n-ad blocking).

    void initView(){
        adView = (AdView) findViewById(R.id.adView);
        adView.setAdListener(new AdBlockerListener(){
           public void onAdBlocked(){
                 showNagScreen();
           }

           public boolean shouldCheckAdBlock(){
                 return isFreeApp();
            }

        });
    }

That's all, you now have a simple way of detecting users using your applications without ads.

Swift macro : @VisibleForTesting

As an ancient Java developer, I’ve learned to use a set of annotations to bring meta programming in my projects. Meta programming can be ...… Continue reading

Dark Mode iOS Snapshot

Published on January 10, 2021

Git-gone

Published on December 31, 2020