Advertising is a common way to monetize Flutter apps. Integrating ads involves handling ad events and callbacks to manage ad lifecycle, user interactions, and revenue tracking effectively. In this blog post, we’ll explore how to handle ad events and callbacks in Flutter using various ad formats.
Why Handle Ad Events and Callbacks?
Handling ad events and callbacks is crucial for several reasons:
- Ad Lifecycle Management: Properly loading, showing, and disposing of ads.
- User Experience: Ensuring ads don’t disrupt the app’s usability and providing a seamless experience.
- Revenue Tracking: Accurately tracking ad impressions, clicks, and revenue for analysis and optimization.
- Error Handling: Managing potential errors during ad loading or display to prevent crashes.
Setting Up AdMob in Flutter
Before handling ad events, you need to set up AdMob in your Flutter app.
Step 1: Add Dependencies
Add the google_mobile_ads package to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
google_mobile_ads: ^4.0.0
Step 2: Initialize Mobile Ads
Initialize the Mobile Ads SDK in your main.dart file:
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Ad Event Handling',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Event Handling'),
),
body: Center(
child: Text('Ad Content Here'),
),
);
}
}
Handling Banner Ad Events and Callbacks
Banner ads are simple rectangular ads that appear at the top, bottom, or within the app’s content.
Step 1: Create a Banner Ad
Create a BannerAd instance and load it:
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class BannerAdWidget extends StatefulWidget {
@override
_BannerAdWidgetState createState() => _BannerAdWidgetState();
}
class _BannerAdWidgetState extends State {
late BannerAd _bannerAd;
bool _isAdLoaded = false;
@override
void initState() {
super.initState();
_initBannerAd();
}
void _initBannerAd() {
_bannerAd = BannerAd(
adUnitId: 'ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyyy', // Replace with your AdUnit ID
size: AdSize.banner,
request: AdRequest(),
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
print('$ad loaded.');
setState(() {
_isAdLoaded = true;
});
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
print('Ad failed to load: ${error.message}');
ad.dispose();
},
onAdOpened: (Ad ad) => print('Ad opened.'),
onAdClosed: (Ad ad) => print('Ad closed.'),
),
);
_bannerAd.load();
}
@override
Widget build(BuildContext context) {
return Container(
child: _isAdLoaded
? Container(
alignment: Alignment.center,
child: AdWidget(ad: _bannerAd),
width: _bannerAd.size.width.toDouble(),
height: _bannerAd.size.height.toDouble(),
)
: Container(
height: 50,
child: Center(child: Text('Banner Ad is loading...')),
),
);
}
@override
void dispose() {
_bannerAd.dispose();
super.dispose();
}
}
Step 2: Implement Banner Ad Listener
The BannerAdListener provides callbacks for various ad events:
onAdLoaded: Called when the ad is successfully loaded.onAdFailedToLoad: Called when the ad fails to load.onAdOpened: Called when the ad opens an overlay.onAdClosed: Called when the user closes the ad overlay.
Step 3: Display the Banner Ad
Add the BannerAdWidget to your app’s UI:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Event Handling'),
),
body: Column(
children: [
Expanded(
child: Center(
child: Text('Ad Content Here'),
),
),
BannerAdWidget(), // Display the banner ad
],
),
);
}
}
Handling Interstitial Ad Events and Callbacks
Interstitial ads are full-screen ads that cover the entire app interface. They are typically displayed at natural transition points in an app, such as between activities or during a break in a game.
Step 1: Create and Load Interstitial Ad
Create and load the InterstitialAd and handle ad events:
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class InterstitialAdWidget extends StatefulWidget {
@override
_InterstitialAdWidgetState createState() => _InterstitialAdWidgetState();
}
class _InterstitialAdWidgetState extends State {
InterstitialAd? _interstitialAd;
bool _isAdLoaded = false;
@override
void initState() {
super.initState();
_initInterstitialAd();
}
void _initInterstitialAd() {
InterstitialAd.load(
adUnitId: 'ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyyy', // Replace with your AdUnit ID
request: AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (InterstitialAd ad) {
print('$ad loaded.');
_interstitialAd = ad;
_isAdLoaded = true;
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (Ad ad) =>
print('$ad onAdShowedFullScreenContent.'),
onAdDismissedFullScreenContent: (Ad ad) {
print('$ad onAdDismissedFullScreenContent.');
ad.dispose();
_initInterstitialAd(); // Load a new ad after dismissing
},
onAdFailedToShowFullScreenContent: (Ad ad, AdError error) {
print('$ad onAdFailedToShowFullScreenContent: $error');
ad.dispose();
_initInterstitialAd(); // Retry loading the ad
},
onAdClicked: (Ad ad) => print('$ad onAdClicked.'),
);
},
onAdFailedToLoad: (LoadAdError error) {
print('InterstitialAd failed to load: ${error.message}');
_interstitialAd = null;
_isAdLoaded = false;
},
),
);
}
void _showAd() {
if (_isAdLoaded && _interstitialAd != null) {
_interstitialAd!.show();
} else {
print('Interstitial ad is not ready yet.');
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _showAd,
child: Text('Show Interstitial Ad'),
);
}
@override
void dispose() {
_interstitialAd?.dispose();
super.dispose();
}
}
Step 2: Implement Ad Callbacks
The InterstitialAdLoadCallback and FullScreenContentCallback are used to handle interstitial ad events:
onAdLoaded: Called when the ad is successfully loaded. Assign the loaded ad and set thefullScreenContentCallback.onAdFailedToLoad: Called when the ad fails to load. Handle the error and retry loading the ad.onAdShowedFullScreenContent: Called when the ad is displayed in full screen.onAdDismissedFullScreenContent: Called when the ad is dismissed. Dispose of the ad and load a new one.onAdFailedToShowFullScreenContent: Called when the ad fails to show full screen. Dispose of the ad and retry loading.onAdClicked: Called when the ad is clicked.
Step 3: Show the Interstitial Ad
Add a button to trigger the interstitial ad display:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Event Handling'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Ad Content Here'),
SizedBox(height: 20),
InterstitialAdWidget(), // Button to show interstitial ad
],
),
),
);
}
}
Handling Rewarded Ad Events and Callbacks
Rewarded ads are ads that users can choose to view in exchange for in-app rewards. This is commonly used in gaming apps.
Step 1: Create and Load Rewarded Ad
Create and load the RewardedAd and handle ad events:
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class RewardedAdWidget extends StatefulWidget {
@override
_RewardedAdWidgetState createState() => _RewardedAdWidgetState();
}
class _RewardedAdWidgetState extends State {
RewardedAd? _rewardedAd;
bool _isAdLoaded = false;
@override
void initState() {
super.initState();
_initRewardedAd();
}
void _initRewardedAd() {
RewardedAd.load(
adUnitId: 'ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyyy', // Replace with your AdUnit ID
request: AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (RewardedAd ad) {
print('$ad loaded.');
_rewardedAd = ad;
_isAdLoaded = true;
_rewardedAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (Ad ad) =>
print('$ad onAdShowedFullScreenContent.'),
onAdDismissedFullScreenContent: (Ad ad) {
print('$ad onAdDismissedFullScreenContent.');
ad.dispose();
_initRewardedAd(); // Load a new ad after dismissing
},
onAdFailedToShowFullScreenContent: (Ad ad, AdError error) {
print('$ad onAdFailedToShowFullScreenContent: $error');
ad.dispose();
_initRewardedAd(); // Retry loading the ad
},
onAdClicked: (Ad ad) => print('$ad onAdClicked.'),
);
},
onAdFailedToLoad: (LoadAdError error) {
print('RewardedAd failed to load: ${error.message}');
_rewardedAd = null;
_isAdLoaded = false;
},
),
);
}
void _showAd() {
if (_isAdLoaded && _rewardedAd != null) {
_rewardedAd!.show(
onUserEarnedReward: (Ad ad, RewardItem rewardItem) {
print('Reward earned: ${rewardItem.amount} ${rewardItem.type}');
// Grant the reward to the user
},
);
} else {
print('Rewarded ad is not ready yet.');
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _showAd,
child: Text('Show Rewarded Ad'),
);
}
@override
void dispose() {
_rewardedAd?.dispose();
super.dispose();
}
}
Step 2: Implement Ad Callbacks and Reward Handling
The RewardedAdLoadCallback and FullScreenContentCallback, along with onUserEarnedReward, are used to handle rewarded ad events:
onAdLoaded: Called when the ad is successfully loaded. Set upfullScreenContentCallback.onAdFailedToLoad: Called when the ad fails to load. Handle the error.onAdShowedFullScreenContent: Called when the ad is displayed.onAdDismissedFullScreenContent: Called when the ad is dismissed. Dispose and reload the ad.onAdFailedToShowFullScreenContent: Called if the ad fails to show. Dispose and reload the ad.onAdClicked: Called when the ad is clicked.onUserEarnedReward: Called when the user has earned a reward by watching the ad. Grant the reward to the user in your app.
Step 3: Show the Rewarded Ad
Add a button to trigger the rewarded ad display:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Event Handling'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Ad Content Here'),
SizedBox(height: 20),
RewardedAdWidget(), // Button to show rewarded ad
],
),
),
);
}
}
Best Practices for Handling Ad Events
- Proper Ad Disposal: Always dispose of ad objects in the
dispose()method of your widgets to prevent memory leaks. - Error Handling: Implement proper error handling for ad loading failures to prevent app crashes and provide a better user experience.
- User Experience: Don’t interrupt the user experience with ads. Ensure ads are displayed at natural transition points.
- Ad Refresh Rate: Balance the ad refresh rate to avoid annoying users and to optimize revenue.
Conclusion
Handling ad events and callbacks is essential for effectively integrating ads into your Flutter apps. By properly managing ad lifecycles, tracking ad interactions, and handling potential errors, you can ensure a seamless user experience while maximizing your ad revenue. This guide covers handling banner, interstitial, and rewarded ad events with comprehensive code samples for each type, allowing you to effectively monetize your Flutter applications.