This codelab guides you through adding an AdMob banner, an interstitial ad, and a rewarded ad to an app called Awesome Drawing Quiz, a game that lets players guess the name of the drawing.
If you run into any issues (code bugs, grammatical errors, unclear wording) as you work through this codelab, please report the issue by clicking the Report a mistake link in the lower, left corner of the codelab.
You need to set up a Firebase project to serve AdMob ads with the Firebase AdMob Plugin.
Awesome Drawing Quiz
as the project name. In the Firebase console, select the Awesome Drawing Quiz project that you created in the previous step.
com.codelab.awesomedrawingquiz
in the Android package name field.Awesome Drawing Quiz (Android)
in the App nickname field.google-services.json
file for future use.com.codelab.awesomedrawingquiz
in the iOS bundle ID field.Awesome Drawing Quiz (iOS)
in the App nickname field.GoogleService-Info.plist
file for future use.The following instructions tell you how to configure Firebase for both Android and iOS.
google-services.json
file into the android/app
directory of the Awesome Drawing Quiz Flutter project.android/build.gradle
), add rules to include the Google Services Gradle plugin. Check that you have Google's Maven repository.buildscript {
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
}
...
dependencies {
...
// TODO: Add Google Services plugin
classpath 'com.google.gms:google-services:4.3.3'
}
}
allprojects {
...
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
...
}
}
android/app/build.gradle
), apply the Google Services Gradle plugin....
// TODO: Apply google-services plugin
apply plugin: 'com.google.gms.google-services'
android {
...
}
...
ios
directory. (for example, ios/Runner/AppDelegate.swift
)GoogleService-Info.plist
file into the Runner
directory, to import the configuration file into the Xcode project.Use the following AdMob app ID and ad unit ID prepared for this codelab.
Android
Item | app ID/ad unit ID |
AdMob app ID |
|
Banner |
|
Interstitial |
|
Rewarded |
|
iOS
Item | app ID/ad unit ID |
AdMob app ID |
|
Banner |
|
Interstitial |
|
Rewarded |
|
Flutter uses plugins to provide access to a wide range of platform-specific services. Plugins include platform-specific code to access services and APIs on each platform.
The firebase_admob plugin supports loading and displaying banner, interstitial, and rewarded ads by using the AdMob API.
Because Flutter is a multi-platform SDK, the firebase_admob plugin is applicable for both iOS and Android. So, if you add the plugin to your Flutter app, it is used by both the Android and iOS versions of the Awesome Drawing Quiz app.
To access the AdMob APIs from the Awesome Drawing Quiz project, add the firebase_admob plugin as a dependency to the pubspec.yaml
file located at the root of the project.
...
dependencies:
flutter:
sdk: flutter
google_fonts: ^0.3.9
# Add the following line
firebase_admob: ^0.9.3
...
Click Packages get to install the plugin into the Awesome Drawing Quiz project.
android/app/src/main/AndroidManifest.xml
file in Android Studio.<meta-data>
tag and entering com.google.android.gms.ads.APPLICATION_ID
. If your AdMob app ID is ca-app-pub-3940256099942544~3347511713
, then you need to add the following lines to the AndroidManifest.xml
file.<manifest>
...
<application>
...
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
</application>
</manifest>
ios/Runner/Info.plist
file in Android Studio.GADApplicationIdentifier
key with the string value of your AdMob app ID. For example, if your AdMob app ID is ca-app-pub-3940256099942544~1458002511
, then you need to add the following lines to the Info.plist
file....
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
...
Create a new file named ad_manager.dart
under the lib
directory. Then, implement the AdManager
class which provides an AdMob app ID and ad unit IDs for Android and iOS.
import 'dart:io';
class AdManager {
static String get appId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544~4354546703";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544~2594085930";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544/8865242552";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544/4339318960";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get interstitialAdUnitId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544/7049598008";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544/3964253750";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get rewardedAdUnitId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544/8673189370";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544/7552160883";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
}
Before loading ads, you need to initialize the AdMob SDK. Open the lib/home_route.dart
file, and modify _initAdMob()
to initialize the SDK before the game starts.
// TODO: Import ad_manager.dart
import 'package:awesome_drawing_quiz/ad_manager.dart';
import 'package:awesome_drawing_quiz/app_theme.dart';
// TODO: Import firebase_admob.dart
import 'package:firebase_admob/firebase_admob.dart';
import 'package:flutter/material.dart';
...
class _HomeRouteState extends State<HomeRoute> {
...
Future<void> _initAdMob() {
// TODO: Initialize AdMob SDK
return FirebaseAdMob.instance.initialize(appId: AdManager.appId);
}
}
In this section, you add a banner ad at the top of the game screen, as shown.
Open the lib/game_route.dart
file, and import ad_manager.dart
and firebase_admob.dart
by adding the following lines:
...
// TODO: Import ad_manager.dart
import 'package:awesome_drawing_quiz/ad_manager.dart';
// TODO: Import firebase_admob.dart
import 'package:firebase_admob/firebase_admob.dart';
class GameRoute extends StatefulWidget {
...
}
Next, in the _GameRouteState
class, add the following member and methods for the banner ad.
class _GameRouteState extends State<GameRoute> implements QuizEventListener {
...
// TODO: Add _bannerAd
BannerAd _bannerAd;
...
// TODO: Implement _loadBannerAd()
void _loadBannerAd() {
_bannerAd
..load()
..show(anchorType: AnchorType.top);
}
...
}
In the initState()
method, create a BannerAd
object, and load the banner ad. Note that the banner displays a 320x50 banner (AdSize.banner
).
@override
void initState() {
...
// TODO: Initialize _bannerAd
_bannerAd = BannerAd(
adUnitId: AdManager.bannerAdUnitId,
size: AdSize.banner,
);
// TODO: Load a Banner Ad
_loadBannerAd();
}
Finally, release the resource associated with the BannerAd
object by calling the BannerAd.dispose()
method in the dispose()
callback method.
@override
void dispose() {
// TODO: Dispose BannerAd object
_bannerAd?.dispose();
...
super.dispose();
}
That's it! Run the project, to see a banner ad shown at the top of the game screen.
In this section, you display an interstitial ad after the game (5 levels in total) finishes.
First, add the following members and methods for the interstitial ad in the _GameRouteState
class.
class _GameRouteState extends State<GameRoute> implements QuizEventListener {
...
// TODO: Add _interstitialAd
InterstitialAd _interstitialAd;
// TODO: Add _isInterstitialAdReady
bool _isInterstitialAdReady;
...
// TODO: Implement _loadInterstitialAd()
void _loadInterstitialAd() {
_interstitialAd.load();
}
// TODO: Implement _onInterstitialAdEvent()
void _onInterstitialAdEvent(MobileAdEvent event) {
switch (event) {
case MobileAdEvent.loaded:
_isInterstitialAdReady = true;
break;
case MobileAdEvent.failedToLoad:
_isInterstitialAdReady = false;
print('Failed to load an interstitial ad');
break;
case MobileAdEvent.closed:
_moveToHome();
break;
default:
// do nothing
}
}
...
}
Next, initialize _isInterstitialAdReady
and _interstitialAd
in the initState()
method. Because _onInterstitialAdEvent
is configured as an ad event listener for _interstitialAd
, every ad event from _interstitialAd
is delivered to the _onInterstitialAdEvent
method.
@override
void initState() {
...
// TODO: Initialize _isInterstitialAdReady
_isInterstitialAdReady = false;
// TODO: Initialize _interstitialAd
_interstitialAd = InterstitialAd(
adUnitId: AdManager.interstitialAdUnitId,
listener: _onInterstitialAdEvent,
);
}
In this codelab, an interstitial ad is displayed after a user completes 5 levels. To minimize unnecessary ad requests, we start loading an ad when a user reaches level 3.
In the onNewLevel()
method, add the following lines.
@override
void onNewLevel(int level, Drawing drawing, String clue) {
...
// TODO: Load an Interstitial Ad
if (level >= 3 && !_isInterstitialAdReady) {
_loadInterstitialAd();
}
}
When a game finishes, the game score dialog is displayed. When a user closes the dialog, it routes a user to the home screen of the Awesome Drawing Quiz.
Because interstitial ads should be displayed between screen transitions, we show the interstitial ad when a user clicks the CLOSE button.
Modify the onGameOver()
method as follows:
@override
void onGameOver(int correctAnswers) {
showDialog(
context: _scaffoldKey.currentContext,
builder: (context) {
return AlertDialog(
title: Text('Game over!'),
content: Text('Score: $correctAnswers/5'),
actions: <Widget>[
FlatButton(
child: Text('close'.toUpperCase()),
onPressed: () {
// TODO: Display an Interstitial Ad
if (_isInterstitialAdReady) {
_interstitialAd.show();
}
_moveToHome();
},
),
],
);
},
);
}
Finally, release the resource associated with the InterstitialAd
object by calling the InterstitialAd.dispose()
method in the dispose()
callback method.
@override
void dispose() {
...
// TODO: Dispose InterstitialAd object
_interstitialAd?.dispose();
...
super.dispose();
}
That's it! Run the project to see an interstitial ad displayed after the game finishes.
In this section, you add a rewarded ad which gives a user an additional hint as a reward.
First, add the members and methods for the rewarded ad in the _GameRouteState
class. Note that RewardedVideoAd
is a singleton object, so you don't need to have a member for managing the instance of the RewardedVideoAd
class.
RewardedVideoAdEvent.rewarded
is the most important ad event in a rewarded ad. It's triggered when a user becomes eligible to receive a reward (for example., finished watching a video). In this codelab, RewardedVideoAdEvent.rewarded
calls the QuizManager.instance.useHint()
method which reveals one more character in the hint string.
Also, according to the ad event, RewardedVideoAdEvent.rewarded
updates the UI by changing the value of _isRewardedAdReady
. Note that _isRewardedAdReady
reloads the ad when a user closes the ad, to make sure the ad is ready as early as possible.
class _GameRouteState extends State<GameRoute> implements QuizEventListener {
...
// TODO: Add _isRewardedAdReady
bool _isRewardedAdReady;
...
// TODO: Implement _loadRewardedAd()
void _loadRewardedAd() {
RewardedVideoAd.instance.load(
targetingInfo: MobileAdTargetingInfo(),
adUnitId: AdManager.rewardedAdUnitId,
);
}
// TODO: Implement _onRewardedAdEvent()
void _onRewardedAdEvent(RewardedVideoAdEvent event,
{String rewardType, int rewardAmount}) {
switch (event) {
case RewardedVideoAdEvent.loaded:
setState(() {
_isRewardedAdReady = true;
});
break;
case RewardedVideoAdEvent.closed:
setState(() {
_isRewardedAdReady = false;
});
_loadRewardedAd();
break;
case RewardedVideoAdEvent.failedToLoad:
setState(() {
_isRewardedAdReady = false;
});
print('Failed to load a rewarded ad');
break;
case RewardedVideoAdEvent.rewarded:
QuizManager.instance.useHint();
break;
default:
// do nothing
}
}
...
}
Next, initialize _isRewardedAdReady
and set _onRewardedAdEvent
as an ad event listener. Then, call _loadRewardedAd()
to request a rewarded ad.
@override
void initState() {
...
// TODO: Initialize _isRewardedAdReady
_isRewardedAdReady = false;
// TODO: Set Rewarded Ad event listener
RewardedVideoAd.instance.listener = _onRewardedAdEvent;
// TODO: Load a Rewarded Ad
_loadRewardedAd();
}
Next, allow users to watch a rewarded ad by clicking the floating action button. The button shows only if a user hasn't used a hint at the current level and a rewarded ad is loaded.
Modify the _buildFloatingActionButton()
method, as follows, to display the floating action button. Note that returning null
hides the button from the screen.
Widget _buildFloatingActionButton() {
// TODO: Return a FloatingActionButton if a Rewarded Ad is available
return (!QuizManager.instance.isHintUsed && _isRewardedAdReady)
? FloatingActionButton.extended(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Need a hint?'),
content: Text('Watch an Ad to get a hint!'),
actions: <Widget>[
FlatButton(
child: Text('cancel'.toUpperCase()),
onPressed: () {
Navigator.pop(context);
},
),
FlatButton(
child: Text('ok'.toUpperCase()),
onPressed: () {
Navigator.pop(context);
RewardedVideoAd.instance.show();
},
),
],
);
},
);
},
label: Text('Hint'),
icon: Icon(Icons.card_giftcard),
)
: null;
}
Finally, remove the rewarded ad event listener in the dispose()
callback method.
@override
void dispose() {
...
// TODO: Remove Rewarded Ad event listener
RewardedVideoAd.instance.listener = null;
...
super.dispose();
}
That's it! Run the project and watch a rewarded ad, to get an additional hint.
You've found something special!
You have completed the codelab. You can find the completed code for this codelab in the complete folder.
To learn more, try the other Flutter codelabs.