Add Ads to your App in a Snap!

The Dart Package, Ads. Revisited and Revised.

A year ago, the article, Ads in your App in a Snap!, introduced a library file offering an easy and extensive means to display Ads in your Flutter app using Google’s plugin, firebase_admob. It received such a positive reception, I chose to contribute it as a Dart package, ads. Simply put, it was a hit.

As with Life, things change. In this case, the plugin itself changed and evolved — and so, the Dart package had to keep up. Note, although it remains in beta, the plugin continues to be one of the few means to provided Admob ads. The Dart package, ads, merely serves to encourage the plugin’s implementation and to accentuate its use in Flutter applications. This article will review the latest version of the Dart package and will demonstrate its use.

Install the package, Ads, and you’re on your way to monetizing your Flutter app with Google’s AdMob ads. It’s merely a ‘wrapper’ for the plugin made by Google called, firebase_admob. It’s to quickly and easily implement Google’s AdMob ads into your Flutter app.

The Only Game In Town

It would seem, the other Dart package that I knew of will no longer be readily maintained. Youssef Kababe had also provided such a Dart package for AdMob ads, but he’s now looking to hand it over for another to support.

admob_flutter

Sign Up and Get Your ID’s

First and foremost, you have to sign up for AdMob. Please, turn to AdMob Help for further guidance on this. You’re going to have to go to your Google AdMob Dashboard and get your id’s as well. There’s the ‘app ID’ used to identify your individual app, and there’s individual unit ID’s unique to each ‘type’ of ad you decide to use. Currently, there are three types: a Banner ad, an Interstitial ad, and a Video ad. Might as well do all that now, and then come back here to learn how to display such ads in your Flutter app. I’ll wait.

Google AdMob

It’s A Test. Not For Real

Note, test id’s are supplied by the plugin to be used during development. Using your own id would violate ‘AdMob by Google’ policy. You can’t be clicking ads on your own app. They’ll know.

For Android. Modify AndroidManifest.xml

For Android users, a common error you may encounter when trying this Dart package out is Google complaining that the ‘AdMob was not properly initialized.’ Merely add your ‘app id’ to your AndroidManifest.xml file.

Further instructions for both iOS and Android platforms can be found on the plugin’s own website under the headings AndroidManifest changes and Info.plist changes.

failed to load ad : 3

failed to load ad : 3

Patience is a virtue. The only errors I consistently receive from users are not of the Dart package itself but are due to Google. Once the user has registered with Google, a common complaint is there are still only ‘test’ ads being displayed, but that’s because it’ll take some hours if not a day to receive production ads. Wait a day, and see for yourself.

A Walkthrough

Let’s examine this class from top to bottom in an attempt to provide some insight on how to use this Dart package. To supplement the process, we’ll also walk through an ‘example’ app that was written to highlight most if not all the functions and features available to you when using this Dart package. This example app literally accompanies the Dart package under the tab, example, on the pub.dev website.

Screenshots! Not Gists!

As always, I prefer using screenshots over gists to show code in my articles. I find them easier to work with, and easier to read. However, you can click/tap on them to see the code as a gist or in Github. Ironically, it’s better to read this article about mobile development on your computer than on your phone. Besides, we program mostly on our computers; not on our phones. For now.

Let’s begin.

Other Stories by Greg Perry

The First Parameter is a Biggy

A call to the static function, init(), is required to initialize the plugin, firebase_admob. You will see in the screenshot below, the only required parameter is the first one. It’s your ‘App id’ — the unique ID assigned to your app. It’s the ID you get from your Google AdMob Dashboard. The rest are named parameters and consequently are optional.

Highlighted with red arrows, you see you have the option to supply all the ‘unit id’ of the ‘type’ of ads you’ve chosen to display in you’re Flutter app. They’re named parameters and so you’ll easily assign the right parameter to the one you’ve gotten from your Google AdMob Dashboard. Also, notice how the function tests for an ‘invalid’ app id? If passed null or an empty string, the function won’t complain. It’ll simply supply a ‘test id’ instead. You’ll see ‘test ads’ appear in your Flutter app.

The last line in the function has the FirebaseAbMob plugin initialized finally supplying the app id. The parameter, testing, is evaluated to supply either your ‘app id’ or a ‘test id.’ Either real production ads or ‘test ads’ will be displayed accordingly.

Ads class *

You Need Your ID’s

It’s suggested that, here at the init() function, you further supply the unit id’s for each individual ‘type’ of ad you wish to display in your Flutter app. As it's implied however, this Dart package allows you the option to supply those unit id’s later on in the process. Note, if you don’t ever supply them — test ads will be displayed instead.

Again, if your ‘app id’ is not provided correctly for some reason in production, the ‘test’ app id, FirebaseAdMob.testAppId, is used instead. You can see in the screenshot of the plugin’s source code above, a particular ‘test’ app id is supplied by the static variable, testAppId, depending on the platform used. Again, in the Dart package, the ‘test’ app id is used regardless if the named parameter, testing, is also passed and is set to true.

FirebaseAdMob class ^

The Others

Let’s quickly define what the other parameters do for you in the Dart package. Three of the five remaining parameters yet mentioned pertain to ‘the kind’ of ads you may wish to display in your Flutter app.

Ads class *

The Key Is Words

Starting from the top, there’s the parameter, keywords. It’s a List of String values. With this list of keywords, you are returned from Google’s inventory of ads those assigned such keywords. It’s suggested the developer explicitly supply keywords representing ‘the kind’ of ads they wish displayed. However, you do have another way to supply such keywords with the next parameter.

The Website’s Content

The next parameter is of type String and is called, contentUrl. Again, as part of the ‘keyword targeting’ used to determine the kind of ads to display on the Flutter app, this supplies a particular website to the plugin. You see, that website may have been visited by Google’s many search engine spiders and the information harvest for Google’s search engine index could then also be used to supply keywords to determine the kind of ads to display.

As it is, the parameter, contentUrl, need not be used. However, I would think a common approach is for developers would be to supply their own or their client’s own corporate website — with the idea that if Google has visited the website, the kind of ads suitable for the app will be displayed using the keywords harvested from their own website.

Directed To Children

You have the option to request for ads directed to children under the age of 13 The next boolean parameter, childDirected, when set to true makes this so.

Test Certain Devices

The next parameter, testDevices, is a list of String items describing specific devices that will only display test ads. While developing, either using an emulator or attached device, you can determine ‘the name’ of the device you’re using through your IDE. Taking those name(s) and listing them in a List object supplied then to the parameter, testDevices, will allow you to, for example, display test ads only on particular devices even if the app is running in production. To demo the app to clients on your phone for example. You don’t want clients clicking on production ads by mistake.

The Ads Listener

An interesting ability of the plugin, firebase_admob, is that the developer can put ‘listeners’ in place to fire code when a finite list of events involving the displaying and the interacting with ads are triggered. As for the Dart package, the last parameter, listener, provides a means to implement such a listener at the init() function.

The example app lists all the possible events, and we’ll go through those events later on in detail. For now, let’s take a look at the example app and demonstrate how one would implement the Dart package, ads.

CASE #1: Init Your Ads

There are three cases in the example app used to demonstrate the Dart package. Let’s take a look at the first case. By the way, it demonstrates a ‘listener’ being assigned to the plugin using the named parameter, listener, in the init() function.

main.dart *

The first case demonstrates an optional approach for implementing the AdMob ads to your Flutter app. As you see in the screenshot, this all takes place in the State object’s initState() function. You can see the id’s issued to you from your Google AdMob Dashboard are being passed to the init() function. In this example, I’m using the ‘test’ id’s issued to us by Google to be used while developing. There’s test id’s for Android and for iOS. This approach doesn’t actually display any ads at this point. The idea being that’s done elsewhere. Although, in most cases, it’s here where you’d call the command to show the banner ad.

Rewarded Watching Videos

Let’s run through this first case, but look solely at what happens with you press the button labelled, ‘SHOW REWARDED VIDEO.’ You’ll see, further on in the example code, a number of event listeners are assigned. You can see that by clicking/tapping on the screenshot above and viewing the source code.

You can see in the sequence of screenshots above, that when the video ad is played, an amount of ‘10 coins’ is collected and then displayed in the app. That was done by one of two handlers that are fired when the predefined ‘rewarded event’ was triggered. Again you’ll find these handlers in the source code, and you’ll see one of them increments the instance variable, _coins, by 10 within a setState() function so then that amount is displayed.

Set Your Listener

Below is one of the event listeners that caught the event. You can see you have the option of using a setter in the Dart package called, videoListener, to assigned an event handler only to the video ad. In this case, it’s an anonymous function, and it has to take in three parameters. The first parameter is required as it’s the ‘RewardedVideoAdEvent’ enumerated value — representing one of eight possible events (You can see all eight below. Read the print() functions that describe each triggered event.)

The next two parameters are optional, but are pertinent to us because they‘re involved in presenting a reward. Looking at their descriptive names, you can tell the first describes the type of reward; the second provides the numerical amount. When it involves ‘reward callback events’, the type returned is the String, “coins.” Hence, the name of the instance variable in the example app, _coins.

main.dart *

Further along in the example app, you’ll find the second event listener or event handler that’s called when the ‘reward event’ is triggered. It’s highlighted with a red arrow. It’s this handler that increments the _coins variable within a setState() function. Note, looking at the screenshot, you’re able to get even more specific and assign a VoidCallback anonymous function to a particular setter and catch seven of the eight events triggered by a video ad. However, when it comes to rewards, you have to assign an anonymous function to the video setter, rewardedListener, which again involves the parameters, rewardType and rewardAmount.

main.dart *

Loop Through Listeners

And so, back in the Dart package, ads, there was a for loop that went through any ‘RewardedVideoAdEvent.rewarded’ event listeners, and in this case, fired the code of these two event listeners one after the other. Neat, no?

Ads class *

Get With Getters

The next stretch of code in the Ads class has a number of ‘library-private’ variables only accessible within this dart file. The first four are those that will contain the id’s from your Google AdMob Dashboard. There next four involve the settings for the kind of ads to be displayed on your Flutter app. While the last one determines whether we’re testing or not. These last five all have corresponding getters allowing for external access to their values.

Ads class *

Get The Ads

As we continue on, there’s still more library-private variables. Some with accompanying getters. You’ll note, however, these getters are deprecated. I’ve deemed these values not for public consumption. They’re references to the actual ad objects, and I don’t readily see the need to make them externally accessible anymore. The last two class variables, _screenLoaded and _showVideo, is used for control flow. The first determines if the InterstitialAd (Full-Screen) ad type needs to be loaded. The second one determines if the Video is ready to be played.

Ads class *

The Three Types of Ads

By the way, below is a screenshot of the currently available types of ads. The first one is the banner ad and is displayed on the bottom of the screen. The next is the ‘full-screen’ or interstitial ad, while the last one is a screenshot of a running video ad.

Dispose of it All

The next bit of code in the Dart package is the function, dispose(). It cleans things up. The ads and any event listeners are cleared from memory. Lastly, the resource-heavy ‘video ad’ reference is nullified. This function should always be called in the State object’s corresponding dispose() function.

Ads class *

Case #2: Set Your Ads

The second case found in the example app uses instead of the lone init() function to specify the kind of ads to be displayed on this app, but the three ‘set’ functions supporting each type of ad currently available. They are the setBannerAd(), the setFullScreenAd(), and the setVideoAd() functions.

main.dart *

You can readily see this allows you to supply different settings to each type of ad currently supported if you like. This means you don’t necessarily need to initialize the ads settings in a State object’s init() function. You can do it elsewhere in your app if you must — and you can do it more than once elsewhere in your app if you must. You have options. Love options.

Each ‘set’ function, of course, must be passed their designated ‘unit id’ but after that, the rest of the settings could be specific to that type of ad. You’ve options. You can see in the example code above, different event listeners are being defined for each type of ad. Two involve local variables; one does not.

Show the Banner

What then follows in the Ads class is the showBannerAd() function. It has an optional State parameter used at times to determine if the ad should be displayed in the first place. If the State object is not mounted this means that the app is terminating. There’d be no need to continue with showing an ad. Note how cascade notation is used to first load and then show the Banner Ad.

Notice it’s got the same parameters you’d find in the setBannerAd() function. This means you can set the Banner ad settings in either the init() function, in the setBannerAd() function, or in this function. Right before you show it.

As you can see highlighted by the little red arrow, if any of the eight parameters are passed to the function, the banner object if any is first disposed of, and the _bannerAd property set to null. It’s then free to set the Banner ad again with the settings provided. Make sense?

Ads class *

Set the Banner Ad

The next function listed is setBannerAd(). This function allows you to set those options you first saw in the init() function above, but these options are only for the Banner Ad. Again, the init() function is used to initialize all three types of ads, but you’re free to further use these three other separate ‘set’ functions to initialize or the three ‘show’ functions to set each type of ad individually.

The remaining parameters are those you’ve seen before in the init() function. In setBannerAd(), the function, _targetInfo(), takes in those parameters and replaces any values not passed as parameters and set to null with those possibly provided by the init() function first called in the State object’s initState().

Like the init() function, the last parameter describes the event listener, AdEventListener(MobileAdEvent event). If one is passed in, it is added to the List object inside the ‘public’ class variable, banner. It will contain a list of event listeners dedicated to only the Banner Ad.

Lastly, the BannerAd class instantiated. It is assigned to the class variable, _bannerAd. If there’s to be testing, the id, BannerAd.testAdUnitId, is to be used. Otherwise, if available, it’ll be your banner’s unit id.

Ads class *

The next function you see the Ads class screenshot is, hideBannerAd(). It has the Banner Ad call its dispose() function; the property is then nullified.

Note, in the setBannerAd() function, the size of the Banner Ad is required, and so a default value of, AdSize.banner, is assigned if not provided to the named parameter, size. Currently, there are six possible sizes available to you.

AdSize const class variables

Show the Full Screen Ad

The InterstitialAd class (the Full-Screen ad type), like the Banner Ad, is referenced by a class variable. In this case, it’s the variable, _fullScreenAd. Like the Banner Ad’s class variable, this variable can to set to null when its ad is closed, and so this ad may have to be ‘reloaded’ first when called on to be displayed again in your Flutter app. The ‘library-private’ variable, _screenLoaded, is set to true in the function, setFullScreenAd(), when the ad is indeed loaded in memory, and then set to false after it is shown in the function, showFullScreenAd().

Ads class *

Also, like the Banner Ad, you can pass the settings to this function, dispose of any existing ad in memory, and reapply those settings before displaying the ad. You’ll find the same approach taken with the video ad presented later.

Set the Full Screen Ad

The next function is, setFullScreenAd(). An InterstitialAd object is created with the options supplied by its parameters. Those not supplied as parameters are further provided by the _targetInfo() function. The event listener, if any, is added to the List of event listeners dedicated only to the Full-Screen Ad. Next, an InterstitialAd object is instantiated and then explicitly ‘loaded’ with the variable, _screenLoaded, set to true.

The function, hideFullScreenAd(), disposes of the InterstitialAd object setting its reference to null. Just like that of its Banner ad counterpart.

Ads class *

Show the Video Ad

The next few functions are concerned with the third and final type of ad, the Video Ad. You’ll recognize the code is very much like the two other types of ads allowing settings to be issued first before the video is actually displayed.

Ads class *

The next function after that is indeed the setVideoAd() function. Again, it loads the Video ad calling on function, _targetInfo(), to supply any remaining options. An event listener specific to this type of ad is repeatedly defined here and assigned to the class variable, _videoAd.

Ads class *

Case#3: Setting Your Show

Here is the third and final case found in the example app. It’s here where you see the init() function assigns the app id, but the ads are then shown using the settings passed directly to the ‘show’ functions. This may be the most likely approach when starting up your Flutter app.

In this case, all three types of ads will be displayed. Each ‘show’ function is supplied the appropriate ‘unit id’ as you see highlighted with red arrows as well as their own individual setting dictating the kind of ads to be displayed by each type of ad. Further, each is assigned their own event listeners.

Target the Ad Info

The next function is called three times in this class library. It’s used to create the ‘MobileAdTargetingInfo’ object necessary to load the three types of ads. Note, the assert statement. Again, the _appId can not be null. Further, you can see in this function the assignment operator, ??=, is used repeatedly to assign what’s found in the ‘Ads’ class variables only if the parameter’s value is null. In some cases, they may both be null, but that’s ok. In the end, the object, MobileAdTargetingInfo, is successfully created.

Ads class *

It’s All An Event!

Next, is the listing of the setters that define all the ‘event listeners’ used in this class. The first ‘event listener’ type, AdEventListener, is used by all three types of ads. It’s the ‘grandaddy’ event listener. Define a listener of that type, and you’ll know that, if you’ve all three ads available on your app, then all three will have that listener fire when called on to load, to display and to finally close back to your app. Also, you’ll see the code below provides a means for the developer ‘to add’ and ‘to remove’ any sort of event listener.

Ads class *

Tyedef’s

Let’s stop here and go back up the Dart file and look at the typedef statements defined just after the import statements. They’re concerned with the event listeners used in the class library. At a glance, you can see the type of parameters required by each ‘type’ of event listener. Lastly, listed is the List object to store all the listeners that may be added for the ‘grandaddy’ event listener.

typedefs in this class.

The Type of Events

Taking a peek inside the plugin, firebase_admob, we can see there are up to 15 separate events that are possibly triggered during the operation of these ads. It is these event listeners that allow you ‘to catch’ a specific event. You then run some code as part of your app’s interaction with the displayed ads.

The Event Types in the Plugin, firebase_admob

Listening for the Ads

Let’s continue on in this Ads class. Next listed is the event listener class, _AdListener. At first glance, you’ll see it’s only visible within the Dart file with its leading underscore. It has a number of List objects defined one after the other — the first used to address up to seven possible ‘MobileAdEvent’ events triggered by the Plugin. The remaining List objects pertain to one specific event from the seven. What follows, is the ‘event listener’ function, _eventListener(MobileAdEvent event).

_AdListener class *

Lastly, you see above the function, clearAll(), will ‘empty’ and clear memory of all the List objects of possible event listeners.

Video Ad Event Listener

Next is the ‘Video ads’ event listener. You’ll see it is very much like the previous event listener class, but this one works with the ‘RewardedVideoAdEvent’ object. Its event listener will take in that event object and also the following named parameters: {String rewardType, int rewardAmount}. You can see listed below the eight events currently defined for a Video Ad. I’ll notice each has a corresponding ‘clear’ function to remove any listeners for a particular event.

_VidListener class *

RewardAd to MobileAd

This final ‘library-private’ function, _toMobileAdEvent(), is there so to allow the Video Ad to use the same event handler List object, _adEventListeners, that is used by the both the Banner Ad and the Full-Screen Ad. Given a particular ‘RewardVideoAdEvent’, the function will return the appropriate corresponding ‘MobileAdEvent’ object otherwise the null value is returned.

_toMobileAdEvent class *

A Follow Up

I’ve made a big change to the Dart package and wrote about it in an additional article called, My Code’s No Good! Here’s Why. It will have further insight in the use of the Dart package and its class library, Ads.

My Code’s No Good! Here’s Why.

TL;DR

The rest of the example app supplies you with a plethora of ‘how to set event listeners.’ That’s what we’ll end with. What follows, I think, gives all the possible ways to implement listeners. In the screenshots below, I’ve included breakpoints. That means I’m inviting you to do the same when running the example app yourself. It’s a really go way to appreciate the ‘flow of control’ and the what events fire and in the order that they fire when your users do, in fact, interact with your ads.

main.dart *
main.dart *
main.dart *
main.dart *
main.dart *

Made For Public Consumption

Like any good library file, the goal is always to make a Dart package resilient for public use. It’s all about ‘how’ the developer is to use the code. In this case, for example, I’ve chosen the Utility Class idiom. Hence, the class offered is just a series of public static properties and public static functions that you can then access application-wide simply by placing the prefix, ‘Ads.’, on the front. However, such an approach is not without considerations. Making code resilient for ‘public consumption’ means ensuring any parameters provided by the outside world are acceptable values. Therefore, you’ve seen a lot of ‘checking for null’ in the code.

However, there’s still some work to be done. For example, I don’t feel any developer who happens to come onto your team should readily be able to define event handlers without you knowing. Currently, this Dart package allows for that. I’m thinking you would have to supply them the appropriate ‘unit id’ first, and they then supply that to a function that defines an event handler. It’s a means of ‘regulating’ that capability. It’s what one has to consider when making such code for other developers. It doesn’t matter if your app is for e-commerce or for cake recipes — some reliability and security is always a consideration. Watch for such changes in the Dart package in future versions to come.

Cheers.

*Source code as of June 21, 2019
^Source code as of May 29, 2019

→ Other Stories by Greg Perry

DECODE Flutter on YouTube

Freelance Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store