What you'll build
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.
What you'll learn
- How to set up a Firebase project for a Flutter app
- How to configure the Firebase AdMob plugin
- How to use banner, interstitial, and rewarded ads in a Flutter app
What you'll need
- Android Studio 3.6 or higher
- Xcode (for iOS support)
How would you rate your level of experience with AdMob?
What would you like to learn from this codelab?
Set up the Flutter development environment
- Install the Flutter SDK on your machine by following the installation instructions on flutter.dev.
- Open Android Studio, and follow the steps on the configuration page to install the Flutter and Dart plugins for Android Studio.
Download the code
To download all the code for this codelab as a zip file, click the following button:
Extract the files from the zip file. This unpacks a root folder named admob-ads-in-flutter-master
.
Or, clone the GitHub repository from the command line.
$ git clone https://github.com/googlecodelabs/admob-ads-in-flutter
The repository contains two folders:
starter — Starting code that you use to build this codelab.
complete — Completed code for this codelab.
Import the starter project
- Open Android Studio.
- From the welcome screen, select Open an existing Android Studio project.
- Open the
starter folder from the code you downloaded in the previous step.
- You may see the following error messages from the Dart Analysis tab. This error happens only once when you imported the existing project to Android Studio because the packages being used in the sample project are not downloaded yet.
- To fix the error, click Get dependencies at the top of the editor pane. It will download the packages that the sample project depends on.
- Once the download is complete, you should see no errors from the Dart Analysis tab. Now your project is ready for development.
You need to set up a Firebase project to serve AdMob ads with the Firebase AdMob Plugin.
Create a Firebase project
- In the Firebase console, click Add project.
- Enter
Awesome Drawing Quiz
as the project name. - Enable Google Analytics for your project and click Continue.
- Choose the analytics location and settings that apply to your project. Read and accept the terms, and then click Create project.
- After a minute or so, your Firebase project is ready.
Register the app with Firebase
In the Firebase console, select the Awesome Drawing Quiz project that you created in the previous step.
Register an Android app
- In the center of the project overview page, click the Android icon to launch the setup workflow.
- Enter
com.codelab.awesomedrawingquiz
in the Android package name field. - Enter
Awesome Drawing Quiz (Android)
in the App nickname field. - Click Register app.
- Download the
google-services.json
file for future use.
Register an iOS app
- In the center of the project overview page, click the iOS icon or Add app (+) icon to launch the setup workflow.
- Enter
com.codelab.awesomedrawingquiz
in the iOS bundle ID field. - Enter
Awesome Drawing Quiz (iOS)
in the App nickname field. - Click Register app.
- Download the
GoogleService-Info.plist
file for future use.
Add a Firebase configuration file
The following instructions tell you how to configure Firebase for both Android and iOS.
Configure for Android
- Open the starter project in Android Studio by referring Import the starter project section in Set up the development environment step in this codelab.
- Move the
google-services.json
file into theandroid/app
directory of the Awesome Drawing Quiz Flutter project.
- In the root-level (project-level) Gradle file (
android/build.gradle
), add rules to include the Google Services Gradle plugin. Check that you have Google's Maven repository.
android/build.gradle
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
...
}
}
- In the module (app-level) Gradle file (
android/app/build.gradle
), apply the Google Services Gradle plugin.
android/app/build.gradle
...
// TODO: Apply google-services plugin
apply plugin: 'com.google.gms.google-services'
android {
...
}
...
Configure for iOS
- Open the starter project in Android Studio by referring Import the starter project section in Set up the development environment step in this codelab.
- Open any file under the
ios
directory. (for example,ios/Runner/AppDelegate.swift
) - Click Open iOS module in Xcode.
- In Xcode, drag the
GoogleService-Info.plist
file into theRunner
directory, to import the configuration file into the Xcode project.
Because Flutter is a multi-platform SDK, you need to add an app and ad units for both Android and iOS in AdMob.
Before you start, you want to be familiar with the following AdMob glossaries.
Ad unit
Ad unit is a set of ads displayed as a result of one piece of the AdMob ad code. You can create and customize an ad unit in your AdMob account.
Each ad unit has a unique identifier, called the ad unit ID. When you implement a new ad unit in your app, you'll reference the ad unit ID to tell ad networks where to send ads when requested.
Banner ad
Banner ads occupy a spot within an app's layout, either at the top or bottom of the device screen. They stay on screen while users are interacting with the app, and can refresh automatically after a certain period of time.
Interstitial ad
Interstitial ads are full-screen ads that cover the interface of their host app. They're typically displayed at natural transition points in the flow of an app, such as between activities or during the pause between levels in a game.
Rewarded ad
Rewarded ads are ads that users have the option of interacting with in exchange for in-app rewards.
Set up for Android
This section tells you how to add an Android app, and ad units, to AdMob.
Add an Android app
Use the following instructions to add an Android app to AdMob:
- In the AdMob console, click ADD APP from the Apps menu.
- When you're asked ‘Have you published your app on Google Play or the App Store?', click NO.
- Enter
Awesome Drawing Quiz
in the App name field, and select Android as the platform.
- Enabling user metrics is not mandatory to complete this codelab. However, it's recommended because enabling user metrics provides the analytics data with detailed user behavior. Click ADD to complete the process.
- Make a note of your new app ID (ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy). You'll need to add it to the sample project's source code to run ads.
Create ad units
To start adding ad units to AdMob:
- Select Awesome Drawing Quiz (Android) from the Apps menu in the AdMob console.
- Click the Ad units menu.
From the Ad units menu, follow the instructions to create a banner, an interstitial ad, and a rewarded ad unit.
Banner
|
Interstitial
|
Rewarded
|
Set up for iOS
This section tells you how to add an iOS app, and ad units, to AdMob.
Add an iOS app
Use the following instructions to add an iOS app to AdMob:
- In the AdMob console, click ADD APP from the Apps menu.
- When you're asked ‘Have you published your app on Google Play or the App Store?', click NO.
- Enter
Awesome Drawing Quiz
in the App name field, and select iOS as the platform.
- Enabling user metrics is not mandatory to complete this codelab. However, it's recommended because enabling user metrics provides the analytics data with detailed user behavior. Click ADD to complete the process.
- Make a note of your new app ID (ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy). You'll need to add it to the sample project's source code to run ads.
Create ad units
To start adding ad units:
- Select Awesome Drawing Quiz (iOS) from the Apps menu in the AdMob console.
- Click the Ad units menu.
From the Ad units menu, follow the instructions to create a banner, an interstitial ad, and a rewarded ad unit.
Banner
|
Interstitial
|
Rewarded
|
Use the preconfigured AdMob app and ad units (optional)
If you want to follow the codelab instead of creating a new application and ad units by yourself, you can use the following AdMob app ID and ad unit IDs prepared for this codelab instead.
Android
Test AdMob IDs for Android:
Item | app ID/ad unit ID |
AdMob app ID |
|
Banner |
|
Interstitial |
|
Rewarded |
|
iOS
Test AdMob IDs for 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.
Adding the Firebase AdMob plugin as a dependency
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.
pubspec.yaml
...
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.
Update AndroidManifest.xml (Android)
- Open the
android/app/src/main/AndroidManifest.xml
file in Android Studio. - Add your AdMob app ID by adding a
<meta-data>
tag and enteringcom.google.android.gms.ads.APPLICATION_ID
. If your AdMob app ID isca-app-pub-3940256099942544~3347511713
, then you need to add the following lines to theAndroidManifest.xml
file.
android/app/src/main/AndroidManifest.xml
<manifest>
...
<application>
...
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
</application>
</manifest>
Update Info.plist (iOS)
- Open the
ios/Runner/Info.plist
file in Android Studio. - Add a
GADApplicationIdentifier
key with the string value of your AdMob app ID. For example, if your AdMob app ID isca-app-pub-3940256099942544~1458002511
, then you need to add the following lines to theInfo.plist
file.
ios/Runner/Info.plist
...
<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.
Make sure that you replace the AdMob app ID (ca-app-pub-xxxxxx~yyyyy
) and the ad unit ID (ca-app-pub-xxxxxxx/yyyyyyyy
) with the IDs you created in the previous step.
lib/ad_manager.dart
import 'dart:io';
class AdManager {
static String get appId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_ADMOB_APP_ID>";
} else if (Platform.isIOS) {
return "<YOUR_IOS_ADMOB_APP_ID>";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_BANNER_AD_UNIT_ID";
} else if (Platform.isIOS) {
return "<YOUR_IOS_BANNER_AD_UNIT_ID>";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get interstitialAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_INTERSTITIAL_AD_UNIT_ID>";
} else if (Platform.isIOS) {
return "<YOUR_IOS_INTERSTITIAL_AD_UNIT_ID>";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get rewardedAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_REWARDED_AD_UNIT_ID>";
} else if (Platform.isIOS) {
return "<YOUR_IOS_REWARDED_AD_UNIT_ID>";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
}
Use the following code snippet if you want to use the preconfigured AdMob app ID and ad unit IDs for this codelab.
lib/ad_manager.dart
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.
lib/home_route.dart
// 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:
lib/game_route.dart
...
// 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.
lib/game_route.dart
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
).
lib/game_route.dart
@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.
lib/game_route.dart
@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.
lib/game_route.dart
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.
lib/game_route.dart
@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.
lib/game_route.dart
@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:
lib/game_route.dart
@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.
lib/game_route.dart
@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.
lib/game_route.dart
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.
lib/game_route.dart
@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.
lib/game_route.dart
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.
lib/game_route.dart
@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.