Flutter is a versatile framework for building cross-platform applications, and one common requirement is integrating advertisements for monetization. Displaying different types of ads can increase revenue streams and provide a better user experience by mixing various ad formats. This article guides you through displaying banner ads, native ads, and rewarded ads in your Flutter application.
Introduction to Ad Integration in Flutter
Integrating ads in your Flutter app allows you to monetize your application through various formats. Some common ad formats include banner ads (small, rectangular ads displayed at the top or bottom of the screen), native ads (ads that match the look and feel of your app), and rewarded ads (ads that users can watch in exchange for in-app rewards).
Why Use Different Types of Ads?
- Increased Revenue: Mixing different ad formats can optimize revenue generation.
- Better User Experience: Some ads are less intrusive and provide a better experience.
- Variety: Prevents ad fatigue by showing different types of ads.
Prerequisites
Before diving into implementation, ensure you have:
- Flutter SDK installed.
- An active AdMob account and Ad Units set up.
- The
google_mobile_ads
Flutter package installed.
Add the following dependency to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
google_mobile_ads: ^4.0.0
Then run flutter pub get
to install the package.
Step-by-Step Implementation
Step 1: Initialize Mobile Ads
Before displaying any ads, initialize the Mobile Ads SDK. It’s best to do this when the app starts.
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 Integration Demo',
home: AdScreen(),
);
}
}
class AdScreen extends StatefulWidget {
@override
_AdScreenState createState() => _AdScreenState();
}
class _AdScreenState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Integration Demo'),
),
body: Center(
child: Text('Displaying Ads'),
),
);
}
}
Step 2: Implement Banner Ads
Banner ads are rectangular ads that occupy a portion of the screen. Create a BannerAd
object and load it.
class _AdScreenState extends State {
BannerAd? _bannerAd;
bool _isBannerAdReady = false;
@override
void initState() {
super.initState();
_loadBannerAd();
}
void _loadBannerAd() {
_bannerAd = BannerAd(
adUnitId: '', // Replace with your Ad Unit ID
request: AdRequest(),
size: AdSize.banner,
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
print('$BannerAd loaded.');
setState(() {
_isBannerAdReady = true;
});
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
print('$BannerAd failed to load: ${error.message}');
ad.dispose();
},
onAdOpened: (Ad ad) => print('$BannerAd opened.'),
onAdClosed: (Ad ad) => print('$BannerAd closed.'),
),
);
_bannerAd!.load();
}
@override
void dispose() {
_bannerAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Integration Demo'),
),
body: Column(
children: [
Expanded(
child: Center(
child: Text('Displaying Ads'),
),
),
if (_isBannerAdReady && _bannerAd != null)
SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
),
],
),
);
}
}
Replace <YOUR_BANNER_AD_UNIT_ID>
with your actual Ad Unit ID.
Step 3: Implement Native Ads
Native ads match the look and feel of your application. Implement a NativeAd
and use a NativeAdView
to display it.
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'dart:io' show Platform;
class _AdScreenState extends State {
// Banner Ad implementation...
NativeAd? _nativeAd;
bool _isNativeAdReady = false;
@override
void initState() {
super.initState();
_loadBannerAd();
_loadNativeAd();
}
void _loadNativeAd() {
_nativeAd = NativeAd(
adUnitId: '', // Replace with your Ad Unit ID
factoryId: 'adFactoryExample',
request: AdRequest(),
listener: NativeAdListener(
onAdLoaded: (Ad ad) {
print('$NativeAd loaded.');
setState(() {
_isNativeAdReady = true;
});
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
print('$NativeAd failed to load: ${error.message}');
ad.dispose();
},
onAdOpened: (Ad ad) => print('$NativeAd opened.'),
onAdClosed: (Ad ad) => print('$NativeAd closed.'),
),
);
_nativeAd!.load();
}
@override
void dispose() {
_bannerAd?.dispose();
_nativeAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Integration Demo'),
),
body: Column(
children: [
if (_isNativeAdReady && _nativeAd != null)
Container(
height: 300,
child: AdWidget(ad: _nativeAd!),
alignment: Alignment.center,
),
Expanded(
child: Center(
child: Text('Displaying Ads'),
),
),
if (_isBannerAdReady && _bannerAd != null)
SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
),
],
),
);
}
}
Remember to replace <YOUR_NATIVE_AD_UNIT_ID>
with your Native Ad Unit ID.
You will need to register the NativeAdFactory, in MainActivity.kt (android/app/src/main/kotlin/your/package/name/MainActivity.kt)
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// Pass the MainActivity instance to the plugin.
GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "adFactoryExample", MyNativeAdFactory(layoutInflater))
}
override fun onDestroy() {
// Destroy the native ad factory
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample")
super.onDestroy()
}
}
You will also need to create the layout for your native ad, res/layout/native_ad_layout.xml:
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@android:color/black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:maxWidth="40dp"
android:maxHeight="40dp"/>
<TextView
android:id="@+id/ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginStart="8dp"
android:layout_gravity="center_vertical"
android:textColor="@android:color/darker_gray"/>
</LinearLayout>
<Button
android:id="@+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"/>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
Next, you will need to create MyNativeAdFactory:
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
class MyNativeAdFactory(private val layoutInflater: LayoutInflater): GoogleMobileAdsPlugin.NativeAdFactory {
override fun createNativeAd(
nativeAd: NativeAd,
customOptions: MutableMap<String, Any>?
): NativeAdView {
val adView = layoutInflater.inflate(R.layout.native_ad_layout, null) as NativeAdView
// Set the media view.
adView.mediaView = adView.findViewById(R.id.ad_media)
// Set other ad assets.
adView.headlineView = adView.findViewById(R.id.ad_headline)
adView.bodyView = adView.findViewById(R.id.ad_body)
adView.callToActionView = adView.findViewById(R.id.ad_call_to_action)
adView.iconView = adView.findViewById(R.id.ad_app_icon)
adView.priceView = adView.findViewById(R.id.ad_price)
adView.starRatingView = adView.findViewById(R.id.ad_stars)
adView.storeView = adView.findViewById(R.id.ad_store)
adView.advertiserView = adView.findViewById(R.id.ad_advertiser)
// The headline and mediaContent are guaranteed to be here.
(adView.headlineView as TextView).text = nativeAd.headline
adView.mediaView.mediaContent = nativeAd.mediaContent
// These assets aren't guaranteed to be present. Check that they are before
// showing or hiding them.
if (nativeAd.body == null) {
adView.bodyView.visibility = View.INVISIBLE
} else {
adView.bodyView.visibility = View.VISIBLE
(adView.bodyView as TextView).text = nativeAd.body
}
if (nativeAd.callToAction == null) {
adView.callToActionView.visibility = View.INVISIBLE
} else {
adView.callToActionView.visibility = View.VISIBLE
(adView.callToActionView as TextView).text = nativeAd.callToAction
}
if (nativeAd.icon == null) {
adView.iconView.visibility = View.GONE
} else {
(adView.iconView as ImageView).setImageDrawable(
nativeAd.icon.drawable
)
adView.iconView.visibility = View.VISIBLE
}
// This method tells the Google Mobile Ads SDK that you have finished populating your
// native ad view with this native ad.
adView.setNativeAd(nativeAd)
return adView
}
}
Step 4: Implement Rewarded Ads
Rewarded ads provide in-app rewards to users who watch the ad. Implement a RewardedAd
object and handle reward events.
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class _AdScreenState extends State {
RewardedAd? _rewardedAd;
bool _isRewardedAdReady = false;
@override
void initState() {
super.initState();
_loadBannerAd();
_loadNativeAd();
_loadRewardedAd();
}
void _loadRewardedAd() {
RewardedAd.load(
adUnitId: '', // Replace with your Ad Unit ID
request: AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (RewardedAd ad) {
print('$RewardedAd loaded.');
setState(() {
_rewardedAd = ad;
_isRewardedAdReady = true;
});
_rewardedAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (Ad ad) =>
print('$ad onAdShowedFullScreenContent.'),
onAdDismissedFullScreenContent: (Ad ad) {
print('$ad onAdDismissedFullScreenContent.');
setState(() {
_isRewardedAdReady = false;
});
_loadRewardedAd();
},
onAdFailedToShowFullScreenContent: (Ad ad, LoadAdError error) {
print('$ad onAdFailedToShowFullScreenContent: ${error.message}');
setState(() {
_isRewardedAdReady = false;
});
},
);
},
onAdFailedToLoad: (LoadAdError error) {
print('RewardedAd failed to load: ${error.message}');
setState(() {
_isRewardedAdReady = false;
});
},
),
);
}
void _showRewardedAd() {
if (_isRewardedAdReady && _rewardedAd != null) {
_rewardedAd!.show(
onUserEarnedReward: (Ad ad, RewardItem reward) {
print(
'$ad with reward ${reward.amount} ${reward.type}');
},
);
} else {
print('Rewarded Ad is not ready yet!');
}
}
@override
void dispose() {
_bannerAd?.dispose();
_nativeAd?.dispose();
_rewardedAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ad Integration Demo'),
),
body: Column(
children: [
if (_isNativeAdReady && _nativeAd != null)
Container(
height: 300,
child: AdWidget(ad: _nativeAd!),
alignment: Alignment.center,
),
Expanded(
child: Center(
child: ElevatedButton(
onPressed: _showRewardedAd,
child: Text('Show Rewarded Ad'),
),
),
),
if (_isBannerAdReady && _bannerAd != null)
SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
),
],
),
);
}
}
Remember to replace <YOUR_REWARDED_AD_UNIT_ID>
with your Rewarded Ad Unit ID.
Best Practices for Ad Integration
- Don’t Be Intrusive: Avoid placing ads in areas that disrupt user experience.
- Frequency Capping: Implement frequency capping to limit how often users see ads.
- Testing: Test different ad placements and formats to optimize performance.
Conclusion
Displaying different types of ads in Flutter is an effective strategy for monetizing your app while maintaining a good user experience. By integrating banner ads, native ads, and rewarded ads, you can optimize revenue and keep users engaged. Following the steps outlined in this guide will help you seamlessly integrate these ad formats into your Flutter application.