60

One of my users let the cat out of the bag and told me they were using one of my free apps, which is monetized by ads, but they were blocking the ads with an ad blocker. They told me this mockingly, as if I can't do anything about it.

Can I do something about it? Is there a way to detect that ads are being blocked?

newenglander
  • 2,019
  • 24
  • 55
Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
  • Could you possibly check for an installed adblocker and if there is one display a dialog that says disable the blocker or else your program wont run? – Mike Aug 10 '10 at 20:01
  • I have no idea but the thought of people doing this makes me sick. I'd have to know about every existing adblocker, so I don't think this solution would be a good one. – Christopher Perry Aug 10 '10 at 20:06
  • 6
    Another option is to put a picture with your logo or whatnot behind the ad, and a button that will direct them to your market page or some sort of advertising for yourself. Therefore even if the add doesn't show up they will still see an ad for your stuff. Sounds like the guy just wanted to be a jerk about it. – Mike Aug 10 '10 at 20:08
  • In my experience with Android Market, this just isn't enough to compensate me for my time. Most Android users won't pay for apps when there are free versions floating around, which is why I chose to monetize with ads. – Christopher Perry Aug 10 '10 at 20:25
  • What happened to the title of this question o.O? – Some Noob Student Mar 23 '12 at 20:31

15 Answers15

61

I am aware of one way that ad blocking works (on any computer really), they edit the hosts file to point to localhost for all known ad servers. For android this is located in the "etc/hosts" file.

For example, I use admob ads and a host file that I have taken from custom rom lists the folowing admob entries:

127.0.0.1 analytics.admob.com
127.0.0.1 mmv.admob.com
127.0.0.1 mm.admob.com
127.0.0.1 admob.com
127.0.0.1 a.admob.com
127.0.0.1 jp.admob.com
127.0.0.1 c.admob.com
127.0.0.1 p.admob.com
127.0.0.1 mm1.vip.sc1.admob.com
127.0.0.1 media.admob.com
127.0.0.1 e.admob.com

Now anytime a process tries to resolve the above addresses they are routed to the address listed to the left of them (localhost) in this case.

What I do in my apps is check this host file and look for any admob entries, if I find any I notify the user that I've detected ad blocking and tell them to remove admob entries from there and do't allow them use of the app.

After all what good does it do me if they're not seeing ads? No point in letting them use the app for free.

Here is a code snippet of how I achieve that:

        BufferedReader in = null;

    try 
    {
        in = new BufferedReader(new InputStreamReader(
                new FileInputStream("/etc/hosts")));
        String line;

        while ((line = in.readLine()) != null)
        {
            if (line.contains("admob"))
            {
                result = false;
                break;
            }
        }
    } 

I vow that all ad supported apps should check this file. You do not need to be root in order to access it, but writing to it might be a different story.

Also, not sure if there is any other files that act the same on a linux based OS, but at any rate we can always check all of those files.

Any suggestions on improving this are welcome.

Also the app called "Ad Free android" needs root access, meaning that it most likely changes the hosts file in order to achieve its goal.

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Ivan
  • 2,632
  • 1
  • 24
  • 12
  • 3
    So glad I'm not the only one doing this...I feel bad, but at the same time, I don't understand why if I choose to share my code with ads that someone has to block them therefore completely taking away any incentive I have to share my personal code for free in the first place. Before I started doing this I was sincerely considering releasing apps only for iPhone going forward. – AndrewPK Jun 27 '11 at 16:32
  • 4
    You might also want to check to make sure that the line in question isn't commented out. `if (line.contains("admob"))` would become `if(line.contains("admob") && !line.matches("^ *#"))` – Kevin Mark Jul 30 '13 at 00:41
  • After testing the above it turns out I needed to use a compiled pattern and matcher otherwise it would never match. Weird. – Kevin Mark Jul 30 '13 at 02:59
  • Thanks, I am using this solution. And displaying a bigger layout block than normal banner, that informs user why I need ads, with a long text. It works great :) – EvanBlack Jul 22 '15 at 11:10
23

My code for this issue is thusly: -

try {
    if (InetAddress.getByName("a.admob.com").getHostAddress().equals("127.0.0.1") ||
        InetAddress.getByName("mm.admob.com").getHostAddress().equals("127.0.0.1") ||
        InetAddress.getByName("p.admob.com").getHostAddress().equals("127.0.0.1") ||
        InetAddress.getByName("r.admob.com").getHostAddress().equals("127.0.0.1")) {
        //Naughty Boy - Punishing code goes here.
        // In my case its a dialog which goes to the pay-for version 
        // of my application in the market once the dialog is closed.
    }
} catch (UnknownHostException e) { } //no internet

Hope that helps.

Jon
  • 812
  • 2
  • 11
  • 18
  • 15
    -1 because can be easily hacked by redirecting those sites to 127.0.0.2 or 240.240.240.240. AdFree allows you to choose the IP :D. Of course I mean to be constructive, not punisher – usr-local-ΕΨΗΕΛΩΝ Oct 10 '12 at 21:26
11

As developers, we need to do the difficult job of empathizing with the users and find a middle ground between punishing the few who try to take advantage and the many who play by the rules. Mobile advertising is a reasonable way to allow someone to use a functional piece of software for free. The users who employ ad blocking techniques could be considered lost revenue, but if you take a look at the big picture, can also be those who spread the word about your application if they like it. A more gentle approach to running on systems with ads blocked is to display your own "house" ad. Create one or more banner images and display them in the same spot as your normal ad with an ImageView of the same height (e.g. 50dp). If you successfully receive an ad, then set your ImageView's visibility to View.GONE. You can even create a timer to cycle through several house ads to get the user's attention. Clicking on your ad can take the user to the market page to buy the full version.

BitBank
  • 8,500
  • 3
  • 28
  • 46
  • I am displaying a bigger block than normal adview, with a text explaining why I must display ads. Server costs etc. Got the base idea from you, so thanks! – EvanBlack Jul 22 '15 at 11:12
  • 3
    i doubt a person using an adblocker is the type of person who would buy your app they want everything for free – tsukimi Feb 15 '17 at 00:56
5

Can you check to see if the ad loaded in your app?

Ad blockers work by preventing your app from downloading data. You could check the content length of the data in your ad frame to make sure there is data there.

If there is no data throw up a message and exit or warn you with an email.

It might not be as big an issue as you think since only a small percentage of people block ads.

Byron Whitlock
  • 52,691
  • 28
  • 123
  • 168
  • 1
    A content blocker could "serve" long blank pages to your app instead of ads. – Borealid Aug 10 '10 at 22:48
  • It seems that the ad blocker blocks http requests to known ad servers. Couldn't we check if the request was even made? That seems different from the no-fill situation. – Christopher Perry Aug 10 '10 at 23:25
  • @Scienceprodigy yes. You could do a head request to your ad server and check the response headers. If the request wasn't blocked, you know that there is connectivity to the ads. This might help with the fill rate issue. – Byron Whitlock Aug 11 '10 at 02:51
4

The top two answers help you with only a particular (if, probably, the most popular) method of blocking ads. Root users can also block ads with a firewall on the device. WiFi users can block ads with an upstream firewall.

I suggest:

  1. Don't reward ad-blocking users. Ensure that your layout reserves part of the display for an ad even if one can't be loaded. Or if you have a full-screen ad that plays for a bit, ensure that your app waits for a bit even if the ad can't be played. If you use notifications as adverts (you scum), notify the user when you fail to get such an advert. This could be read as "annoy all of your users", but your normal users know what they're getting, and your ad-blocking 'users' aren't wanted.

  2. Ask ad-blockers to stop. The less proftable an industry that supplies what a user wants, the less that industry will supply what the user had wanted. An individual developer will find that he makes more money serving other users. You know this, and your users will think it obvious after you tell them, but it's still an economic argument - it's not intuitive. Have a backup ad that says something like, "This is my job. If you don't pay me, I'll get another one, and you won't get more apps like this from me."

Julian Fondren
  • 5,459
  • 17
  • 29
  • 2
    After going through the process of letting it go, then trying to not worry, and finally taking action, my experience teached me that those users don't give a # about your job. In my case, they were exactly the ones who used the app for free during a long long time, never took time to leave a positive review, but suddenly posted 1-star ratings after I implemented ad blockers blocking. No social engineering nor empathy can convince them that your time and technical knowledge costs money (pocket change for them). In my humble opinion, they're just freeloaders. So be it. – davidcesarino Dec 11 '14 at 01:57
3

Rather than checking for individual software installed or modified hosts file, my approach is using an AdListener like this and, if the ad fails to load due to NETWORK_ERROR, I just fetch some random always-online page (for the kicks, apple.com) and check if the pages loads successfully.

If so, boom goes the app.

To add some code, listener class would be something like:

public abstract class AdBlockerListener implements AdListener {

    @Override
    public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) {
        if (arg1.equals(ErrorCode.NETWORK_ERROR)) {
            try {
                URL url = new URL("http://www.apple.com/");
                URLConnection conn = url.openConnection();
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                reader.readLine();
                onAdBlocked();
            } catch (IOException e) {}
        }
    }

    public abstract void onAdBlocked();
}

And then each activity with an adView would do something like:

AdView adView = (AdView) findViewById(R.id.adView);
        adView.setAdListener(new AdBlockerListener() {
            @Override
            public void onAdBlocked() {
                AlertDialog ad = new AlertDialog.Builder(CalendarView.this)
                                    .setMessage("nono")
                                    .setCancelable(false)
                                    .setNegativeButton("OK", new OnClickListener() {
                                        public void onClick(DialogInterface dialog, int which) {
                                            System.exit(1);
                                        }
                                    })
                                    .show();
            }
        });
Filipe Pina
  • 2,201
  • 23
  • 35
  • 2
    The problem with this approach is it could lead to false alarms and annoy legitimate users easily due to ad network errors or unstable internet connection. It is way too aggresive. – Ahmet Noyan Kızıltan Sep 04 '16 at 15:10
  • Also, the AdBlockerListener implementation does not match with recent changes in AdListener. This code throws multiple errors. – CanCoder Nov 02 '19 at 22:29
3

There is nothing you can do that your users can't do better.

The only thing that comes to mind as remotely effective is to make the ads an inextricable part of the program, so that if they're blocked the user cannot make sense of/interact with the application.

Borealid
  • 95,191
  • 9
  • 106
  • 122
1

I think it depends on the content provider for the ads. I know the AdMob SDK provides a callback when an ad request fails. I suspect that you might be able to register for this, then check for a connection in the callback - if there is a connection and you did not receive an ad - take note, if it happens more than once or twice, chances are likely your ads are being blocked. I have not worked with the AdSense for Mobile toolset from Google but it wouldn't surprise me if there was a similar callback mechanism.

nEx.Software
  • 6,782
  • 1
  • 26
  • 34
  • I'm already implementing this on another app that uses Quattro, backed up by AdMob because of Quattro's low fill rate. When Quattro fails to serve an ad, I serve an AdMob ad. But how would I know if it's because of ad blocking vs. bad fill rate? – Christopher Perry Aug 10 '10 at 20:27
  • 1
    It doesn't look like there is any way to distinguish between a no-fill and blocked ad without resorting to other means such as checking for known ad-blocking applications. – nEx.Software Aug 10 '10 at 20:34
1

There are two ways for a user to by pass a advertisement:

1) Use app without internet on.

2) With rooted phone and modified host file.

I made two tools that you can implement, see code below.

checkifonline(); is for problem 1:

public void checkifonline() {
    boolean haveConnectedWifi = false;
    boolean haveConnectedMobile = false;

    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo[] netInfo = cm.getAllNetworkInfo();
    for (NetworkInfo ni : netInfo) {
        if (ni.getTypeName().equalsIgnoreCase("WIFI"))
            if (ni.isConnected())
                haveConnectedWifi = true;
        if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
            if (ni.isConnected())
                haveConnectedMobile = true;
    }

    if(haveConnectedWifi==false && haveConnectedMobile==false){

        // TODO (could make massage and than finish();
    }
}

adblockcheck(); is for problem 2

private void adblockcheck() {
    BufferedReader in = null;
    boolean result = true;

    try 
    {
        in = new BufferedReader(new InputStreamReader(
                new FileInputStream("/etc/hosts")));
        String line;

        while ((line = in.readLine()) != null)
        {
            if (line.contains("admob"))
            {
                result = false;
                break;
            }
        }
    } catch (UnknownHostException e) { }
      catch (IOException e) {e.printStackTrace();}  

    if(result==false){

        // TODO (could make massage and than finish();

    }
}
John
  • 878
  • 11
  • 21
  • The first thing I do with an app that doensn't need internet to work, but still demands it - is throwing that piece of stinking junk away from my device. – Oleg V. Volkov Apr 06 '17 at 12:04
  • It could be that you want to retrieve analytics for improvement and or show ads to be able to buy a sandwich and beer, for no programmer can program without a sandwich and beer. – John Apr 07 '17 at 12:16
0

For the case when there is no internet connection, I have followed this tutorial and I've build a "network state listener" like so:

private BroadcastReceiver mConnReceiver = new BroadcastReceiver() 
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);

        if (noConnectivity == true)
        {
            Log.d(TAG, "No internet connection");
            image.setVisibility(View.VISIBLE);
        }
        else
        {
            Log.d(TAG, "Interet connection is UP");
            image.setVisibility(View.GONE);
            add.loadAd(new AdRequest());
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState)
{
    //other stuff
    private ImageView image = (ImageView) findViewById(R.id.banner_main);
    private AdView add = (AdView) findViewById(R.id.ad_main);
    add.setAdListener(new AdListener());
}

@Override
protected void onResume()
{
    registerReceiver(mConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    super.onResume();
}

@Override
protected void onPause()
{
    unregisterReceiver(mConnReceiver);
    super.onPause();
}

registerReceiver and unregisterReceiver have to be called in onResume and onPause respectively, as described here.

In your layout xml set up the AdView and an ImageView of your own choice, like so:

<com.google.ads.AdView xmlns:googleads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_alignParentBottom="true"
    android:id="@+id/ad_main"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    googleads:adSize="BANNER"
    googleads:adUnitId="@string/admob_id" />

<ImageView
    android:id="@+id/banner_main"
    android:layout_centerInParent="true"
    android:layout_alignParentBottom="true"
    android:layout_width="379dp"
    android:layout_height="50dp"
    android:visibility="gone"
    android:background="@drawable/banner_en_final" />

Now, whenever the internet connection is available the ad will display and when its off the ImageView will pop-up, and vice-versa. This must be done in every activity in which you want ads to display.

Community
  • 1
  • 1
Goran Horia Mihail
  • 3,536
  • 2
  • 29
  • 40
0

I'm sure this answer won't be entirely popular with certain segments of developers, however consider if you fall into this category that perhaps your app doesn't deserve to exist on the app store. Please note that these are all implementable as code changes, no hackery or spyware like behavior required.

Basically, change the economics of your app. The User is Always Right - this is the attitude taken by one of the most successful advertising companies ever (Google). If your ads are being blocked by users, its because you suck, not because ads or ad-blockers suck.

http://books.google.com/books/about/The_User_is_Always_Right.html?id=gLjPMUjVvs0C

  • Make ads less annoying and in-your-face. Users react to poor/annoying advertisement, and the seedier your app looks and becomes, the more likely they are to ditch it anyways. I don't mind apps with ads in them as long as they aren't significantly impeding the functionality, and even better I like ads which are relevant to me. (http://www.nngroup.com/articles/most-hated-advertising-techniques/)
  • To detect that ads aren't being loaded, its not necessary to implement the spyware like activities mentioned by previous posters. Load an ad that has a confirmation code, and every once in awhile, insert a prompt asking for the confirmation code. The code doesn't have to be long or annoying, in fact it'd be enough to implement a captcha service with 3 or 4 letters/numbers. (http://textcaptcha.com/api)
  • In addition to detecting failure of ads to load, make better ads. Instead of using an API like mobads (Do you even realize how seedy that sounds? Mobs? Really? Are we developers, the Russian Mafia?), enter a partnership with an ad company that allows you to embed ads directly from your app. It will make your overall app larger to install, and no, you can't guard against manual modification, but the changes suggested above don't guard against that either. And this will better support any paid versions of your app, which will be much more lightweight (and faster).
  • Thoroughly vet the ads you are displaying to the user, be open and transparent about your ad policies, and even allow users to inspect your ads and ad sources. The primary reason I'm ever concerned about ads is not because I hate ads, but because I worry that the poor quality developer responsible for this app is letting in viruses or other malware as well. Ask that an exception be made to the installed adblocker. Team up with ad blockers like AdBlock to get on their exceptions list. If you are a legit application, this shouldn't be a problem. (http://www.cio.com/article/699970/6_Ways_to_Defend_Against_Drive_by_Downloads?page=1&taxonomyId=3089)

I re-iterate: all of the above changes are things you can legitimately do in code to prevent anti-ad behaviors. Ads are blocked for security reasons and visceral reactions, primarily, and sometimes bandwidth and performance, so make sure your ads don't invoke any of these problems, at the code level.

Finally I did want to touch on what Borealid said, which I re-iterated above; in the end it is a 'cat and mouse' game, because the user has ultimate authority and responsibility, both legally and morally, over their own property. A user can do whatever, including directly modify code on the fly. Of course, there are restrictions you can implement etc. but there are always ways to get around the problem. This is the ultimate problem (technically) with DRM (which is what you're trying to do). Rather than waste time and effort on this game, it is better to encourage users to keep ads around; they'll become your best, smartest anti-ad-blockers, for free.

smaudet
  • 609
  • 8
  • 17
  • This doesn't solve the original problem. If I create the greatest app ever with the most convenient ad usage possible, it won't make any difference if the user has blocked ads system-wide as they won't see the ads in the first place. – TheBestBigAl Aug 03 '15 at 08:19
  • 1
    I would argue that it does, because it solves the root of the problem (ads being inconvenient). Adblockers would not have been so prominent if ads were not so invasive/problematic in the first place. – smaudet Aug 03 '15 at 19:54
  • 1
    The user is not right, the user is cheap. In my case, I had 20,000 downloads yesterday by educational institutions who all block ads. I enjoy being in schools, but 20,000 is OTT. The app wouldn't exist if it wasn't for the ads. I offer choice, there are paid versions of the app, if you don't like ads, well, choose another inferior app. So your attitude to developers sucks basically. The user isn't right, the user is just cheap, and in this case they are extremely cheap. I am going to hard code something in the spot left by the blocked ad to discourage this behaviour. – Peter Smith Feb 04 '16 at 22:42
  • 'So your attitude to developers sucks basically.' No. Your personal experience is clouding your judgement. You have metrics, great, use them, reach out to the institution(s) and see if you can't work something out. By all means, piss your remaining educational users off. They will go out and use the 'inferior' product, you will lose users, and you will no longer be the 'superior' product. Your product *is* your users. Code does not rot, only the user base and the developer minds do. – smaudet Feb 05 '16 at 16:22
  • 1
    I doubt that ad blocking users leave it enabled and then disable specific apps. They disable ALL ads from ALL sources in ALL apps as a blanket measure. You could have the most unintrusive appealing ads that block users would be happy to click on and they wouldn't be seen. This isn't your fault, at this point it's just users wanting something for nothing, and the OP's desire is perfectly reasonable. – Tom May 17 '17 at 23:24
  • That's not entirely accurate - users aren't generally blocking "all" ads - they're doing the minimum necessary to be 'more' secure. Those users who do run blanket blocks do so because that's the easiest option for them. You're asking them to distinguish between good and bad ads. Why should they? - I don't usually install an adblocker personally...I usually only do that as an added precaution if I'm visiting a shady website, or if a particularly annoying ad pops up. I configure my adblocker even less. I don't mind if an add or two slips through, as long as its not doing shady things. – smaudet May 18 '17 at 18:38
  • 1
    Most android adblockers edit the host file and blocks all ads without any distinction aren't only for specific App or specific websites and are banned by GooglePlay guidelines but are downloaded from others websites. You don't know what are you talking about. – Silverstorm Dec 12 '17 at 14:40
  • Ads are blocked because cheapskate users don't want to buy the ad-free version, and don't want to see them. Talking about "security" and all that stuff is overestimating the average clueless Joe that installs anything just to see what it does. Users are cheap, will not hesitate to make a lot of negative comments and will never hesitate to install ad blockers. Never forget that. – theAnonymous Jan 05 '18 at 07:20
  • @user3635998 So here's a challenge - I've purchased apps before to get rid of ads. And yet, the apps were still bundles of trash downloading all sorts of crap from the internet (that they really didn't need to be downloading). So maybe there's an element to this you're not bothering to consider - developers are cheap too, and will never hesitate to attempt to download ads. There are better apps than some in this regard, but in general if I see any hint of network activity or ads in your app, automatically I'm thinking 'low quality app made by low quality dev'. – smaudet Jan 08 '18 at 22:57
  • The truth is here that if all the apps were good to great, there wouldn't be as much of an impetus for a user to visit some third party site and side-load some special hosts based blocking. And if you really can't afford to do a free/paid version properly, rather than forcing everyone to load some malware ridden version before you can 'upgrade', then maybe you shouldn't be releasing your app as free at all. That's a valid option. And, maybe its just me, but I'm tired of crap developers such as yourselves - if you have ads, I just don't use your junk. – smaudet Jan 08 '18 at 23:04
0

This is an extension of a previous answer. The user has informed me that the app they are using is called AdFree Android. It can be found on the market. The app says it works by "nullifying requests to known hostnames serving ads."

I suggest that if you monetize any of your apps with ads, you check at startup for this program and give the user a nasty message, then terminate your app.

Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
0

As well as checking if admob can be resolved, what I do is present a page that basically advises that I have detected an adblocker, state that i understand the possible reasons why, then show some inbuilt ads of my own apps and ask for their kind support for continued development. :)

pvella
  • 190
  • 1
  • 9
0

First, let me say that I believe that Ad Blocking, when it comes to applications, is actually a form of piracy. These apps are supported by the ads, and sometimes, a "paid license" to turn off ads and/or add features. By blocking ads, users are stealing potential revenue from the developer that took the time to create the app that you are using.

Anyhow, I want to add a way to help prevent the use of Ad Blockers. I use this method and I do not allow users to use the app if I detect an ad blocker. People get very angry and will give you poor ratings for it. But I also state very clearly in my applications descriptions that you will not be able to use the app if you have an adblocker.

I use the package manager to check if a specific package is installed. While this will not get all of the adblockers, if you keep "up to date" on some of the popular ones, you can get most of them.

PackageManager pm = activity.getPackageManager ();
Intent intent = pm.getLaunchIntentForPackage ( "de.ub0r.android.adBlock" );
if ( Reflection.isPackageInstalled ( activity, intent ) ) {
  // they have adblock installed
}
Ryan Conrad
  • 6,870
  • 2
  • 36
  • 36
  • 1
    Bare in mind, this only handles one test case. There are many apps out there today that block ads :( – Jared Burrows Sep 02 '14 at 17:13
  • 1
    This above example, yes, only handles one case. I was answering the question, not supplying a list of all the ad blocking packages. My actual solution has a much larger list than one package name. My example also doesn't show you the code for "isPackageInstalled". It was not provided to be production code, it was provided as something that could be done and a start to their own solution. – Ryan Conrad Sep 03 '14 at 22:02
-1

Give your users a way to use the app without the ads. I personally find ads one of the most annoying things that could possibly happen on my computer, and I will gladly pay for an application if it spares me the insult of having ads thrown into my face. And I'm sure I'm not the only one.

drmirror
  • 3,698
  • 26
  • 26