AdWords is Google’s main source of income and provides pay-per-click advertising to its users

AdSense is AdWords’ counterpart and provides website and app publishers with an opportunity to earn money by showing ads

This post requires an existing app in the Play Store. It will add AdSense to DbTradeAlert and the first step is to create an AdMob account.

1. Create an AdMob Account

To create an AdMob account follow these steps and be aware that some of the information cannot be changed later:

Navigate to the Firebase console at console.firebase.google.com

Select your project

On the navigation bar click AdMob

In the center click Register for AdMob

In the next step select a Google account you want to connect to AdMob

In the next step enter information for your AdSense account:

Country will for example determine the payment currency

Individual / business account determines whether payments will be made to the account holder or a company

Full address, email and phone of payee

In the next step enter the timezone and billing currency information for your AdWords account

In the next step agree to the fine print and click Create AdMob Account

The next step is to register an app with AdMob.

2. Register an App with AdMob

You normally register an app with AdMob by searching the Play Store. That search will only return indexed apps and indexing can take a day or more after initially publishing an app. This is not ideal as it makes publishing an app a two-step process with possibly a multi-day delay.

It seems Google created a new option because of this where you add an app by typing in its Id. But for me that created an new Play Store listing with the same app Id (de.dbremes.dbtradealert.withads) and a lot of confusion. Also note that you cannot delete an AdMob registration. So here is the safe way of selecting an app by searching the Play Store:

The “common” flavor is gone – it just served to let Android Studio create the folder hierarchy. And the new sourceSets closure makes the playStore flavor use the files in the “commmon” package. After this the playStore flavor should build like before.

Like the playStore flavor this one sets the applicationId, adds Firebase core as a dependency, and uses the common package’s java sources. In addition to that it adds Firebase Ads as a dependency and specifies an additional package for its source set.

You probably remember from creating the previous flavor that the new one won’t build yet – the Google Services plugin for Gradle will search in vain for the google-services.json file and this file also doesn’t contain the flavor’s applicationId yet.

After clicking Add App a file named google-services.json is downloaded

When you compare this file to the previous one you’ll find that it has the same information plus data for a new client – de.dbremes.dbtradealert.withAds.

This file will be used by both the playStore and the withAds flavor and therefore needs to be in the app directory above them. And of course the playStore flavor’s google-services.json needs to go.

The withAds flavor should now compile providing the same functionality as the playStore flavor. To test that generate signed APKs for both flavors – the naked flavor won’t build with the Google Services plugin applied of course.

After that create a strings.xml file for the withAds flavor, too:

Let Android Studio create a new resource directory for the withAds source set

Let Android Studio create a new resource file named strings.xml in that directory

Copy the app_name element from one of the existing strings.xml files and change its value to “DbTradeAlert A”

6. Add Flavor Specific Functionality

The withAds flavor’s only addition to the playStore flavor is a banner ad on the main screen which involves three tasks:

Connnect an AdView control to AdMob

Inject that control into the main screen

Make the other flavors work without tying them to AdMob

6.1 Connnect an AdView Control to AdMob

To connnect an AdView control to AdMob you’ll have to specify an ad unit Id which looks like this: “ca-app-pub-3940256099942544/6300978111”. An ad unit was obtained in the previous sections and lets Google know whom to pay. It also allows you to track the source of your income if you have multiple adverts in an app.

But while I didn’t find any best practices it seems to be worthwhile to keep your ad unit Id secret because it contains your publisher Id – that’s the part before the “/”. Off the top of my head I can think of two misuses and I’m not even a security guy:

Someone could use your publisher Id in frivolous actions and get your account banned

With some social engineering they could also take over your account

For this reason my ad unit Id is not in the Git repository but loaded from an external file. Another twist regarding the ad unit Id is that you should only use test ads during development because tapping a real ad for test reasons can get your AdMob account suspended. Gradle takes care of both:

The defaultConfig defines a buildConfigField named “AD_UNIT_ID” providing an ad unit Id that was copied from one of Google’s samples and will only deliver test ads. Note that you have to generate quotes around its value because Gradle would otherwise read it as an integer type which results in an “integer number too large” error.

The release build type creates the same field which overrides the default one. The actual value is read from a file named “project.properties” which has just one line – with a proper ad unit Id of course:ad_unit_id=ca-app-pub-1234567891234567/1234567891

Of course the publisher Id can still be extracted from the APK. But why make a crook’s life easier …

Now comes a second preparation step – create the AdHelper class. And make shure to put it in the right package …

Android Studio’s Project view will show two packages named “de.dbremes.dbtradealert (withAds)”. That’s because the previous section specified two source directories in build.gradle. The new AdHelper class needs to go in the empty package in the withAds directory.

After performing the existing initialization WatchlistListActivity.onCreate() now calls AdHelper.initialize() and AdHelper.getAdView(). In this case AdHelper.initialize() probably doesn’t help much to speed up showing the first ad because that is requested only split seconds afterwards.

The AdView control receives some layout information so it shows up at the bottom of the screen and finally it gets added to its parent view. I had to add this parent view to prevent the AdView from blocking the actual content.

That parent view is a LinearLayout with its orientation attribute set to vertical and it wraps the CoordinatorLayout which was originally the outermost control. The CoordinatorLayout also lost its layout_height which was set to match_parent and made it grab the whole screen. As a replacement it got a layout_weight attribute with a value of 1. That makes it still grab the screen as long as it’s alone but it will leave room to other controls when necessary.

Time to enjoy ads flying in your face. To test vertical scroll behavior it’s a good idea to add two more securities – I added CSGN.VX (Credit Suisse) and UBSG.VX (UBS Group) to the CH watchlist.

The line with addTestDevice(“xyz”) reports a hash code for your device. Use that to request test ads if you use a real ad unit Id. Google confirmed the Uncaught ReferenceError is a bug and they are workng on it.

The test ad should show up at the bottom of the screen:

AdMob in action

Note that I scrolled all the way up to see if the last report is still accessible. Title and toolbar look a bit messed up but that is actually a feature as that area moves out of the way to give more space to the actual content.

6.3 Make the Other Flavors Work Without Tying them to AdMob

Like previously seen with the playStore flavor the existing non-withAds flavors need their own empty implementation of an AdHelper class. And ideally an interface or abstract base class would make shure those AdHelpers are implemented correctly.

But neither of them work with static methods. As I don’t like to change code for technical reasons I’ll leave it to the build server to point out diverging AdHelper implementations and just create two identical copies.

Let’s start with an AdHelper class for the playStore flavor:

Add “src/playStore/java” to playStore.java.srcDirs in build.gradle and let Gradle sync

Switch to the playStoreDebug variant

In the app context menu select New | Folder | Java Folder

In the Configure Component window select playStore as the Target Source Set and click Finish

In the New Package window enter “de.dbremes.dbtradealert” and click OK

In the new package’s context menu select New | Java Class

In the Create New Class window enter “AdHelper” and click OK

After that copy the contents of the existing AdHelper class into the new one and:

Remove all “com.google.android.gms.ads” imports

Remove the code in getAdView() and return null

Remove the code in initialize()

Finally build the project to see if it likes the new AdHelper class.

Fixing the naked flavor is a lot easier. Just copy the new AdHelper.java to the respective directory, switch to the nakedDebug variant and Android Studio should pick up the file. Just remember to comment the line applying the Google services plugin out in build.gradle before starting the build.

Next post: more finishing touches (add Firebase Crash reporting, Firebase Remote Config, an About box, and perform Play Store optimization)