This article is for those who have difficulty migrating from the firebase_admob plugin to google_mobile_ads. for convenience I will abbreviate the name firebase_admob as FA, and google_mobile_ads as GMA.
As we know that the FA plugin has been discontinued and replaced with the GMA plugin. One of the advantages of FA over GMA is, the FA banners will appear all over the page without having to rewrite code on other pages. However in GMA, the banner only appear on the page containing GMA code.
There are many disadvantages of GMA compared to FA, including:
- the app blingking when switching pages
- every page always initialize banner and this causes high performance
- each page must be assigned a GMA code
Then how can we implement GMA in our app so that problem does not occur? the way is very easy, which is to become a page as a tab. and this is just a way to show banner ads at the bottom (bottomNavigation). not rewarded or interstitial ad. Check out my method below..
My pages:
- main.dart
- home_tab.dart
- home_page.dart (is First Tab)
- page two.dart
- page three.dart
I will display all banners on the page above.
on pubspec.yaml
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
google_mobile_ads: ^1.0.1
on android\app\build.gradle
...
apply plugin: 'com.google.gms.google-services'
...
android {
compileSdkVersion 32
...
...
defaultConfig {
...
minSdkVersion 21
targetSdkVersion 32
...
multiDexEnabled true
}
...
dependencies {
...
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation platform('com.google.firebase:firebase-bom:29.0.4')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.android.support:multidex:1.0.3'
...
}
on ...\android\gradle\wrapper\gradle-wrapper.properties change to gradle 7.0.2
..
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
..
on ...\android\build.gradle change Kotlin version to 1.6.10 and gradle build to 7.0.0 like the following code:
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.support:multidex:1.0.3'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// await MobileAds.instance.initialize(); //uncomment this code if release
await MobileAds.instance.initialize().then((InitializationStatus status) {
MobileAds.instance.updateRequestConfiguration(
RequestConfiguration(testDeviceIds: <String>[
'0819A79F3F94F37FBABD456D6CF92101', // this is test device id, u can view on console
]),
);
}); // delete this code if release
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeTab(),
);
}
}
home_tab.dart
class HomeTab extends StatefulWidget {
const HomeTab({Key key}) : super(key: key);
static const String routeName = '/HomeTab';
@override
State<StatefulWidget> createState() => HomeTabState();
}
class HomeTabState extends State<HomeTab> {
static int currentTab = 0;
final List<HomeTabItem> tabs = [
HomeTabItem(
page: const HomePage(),
),
];
HomeTabState() {
tabs.asMap().forEach((index, details) {
details.setIndex(index);
});
}
void _selectTab(int index) {
if (index == currentTab) {
tabs[index].key.currentState.popUntil((route) => route.isFirst);
} else {
setState(() => currentTab = index);
}
}
// IKLAN
BannerAd myBanner;
bool adShow = false;
Future<void> _loadAd() async {
final AnchoredAdaptiveBannerAdSize size = await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(MediaQuery.of(context).size.width.truncate());
if (size == null) {
return;
}
myBanner = BannerAd(
adUnitId: 'your banner unit id',
size: size,
request: const AdRequest(
extras: {'rdp': '1'},
),
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
setState(() {
myBanner = ad as BannerAd;
adShow = true;
});
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
ad.dispose();
adShow = false;
},
),
);
return myBanner.load();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_loadAd();
}
@override
void initState() {
myBanner;
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final isFirstRouteInCurrentTab = !await tabs[currentTab].key.currentState.maybePop();
if (isFirstRouteInCurrentTab) {
if (currentTab != 0) {
_selectTab(0);
return false;
}
}
return isFirstRouteInCurrentTab;
},
child: Scaffold(
body: IndexedStack(
index: currentTab,
children: tabs.map((e) => e.page).toList(),
),
bottomNavigationBar: adShow == true
? SizedBox(
width: myBanner.size.width.toDouble(),
height: myBanner.size.height.toDouble(),
child: AdWidget(ad: myBanner),
)
: const SizedBox.shrink(),
),
);
}
}
class HomeTabItem {
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
int _index = 0;
Widget _page;
HomeTabItem({
@required Widget page,
}) {
_page = page;
}
void setIndex(int i) {
_index = i;
}
int getIndex() => _index;
Widget get page {
return Visibility(
visible: _index == HomeTabState.currentTab,
maintainState: true,
child: Navigator(
key: key,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (_) => _page,
);
},
),
);
}
}
we make HomePage as first Tab home_page.dart
// HomePage is FIRST TAB
class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
// we wrap the Scaffold with Willpopscope so that when we are on the main page an exit dialog will appear
return WillPopScope(
onWillPop: () {
return showDialog(
barrierColor: Colors.transparent,
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text(
"Exit App?",
textAlign: TextAlign.center,
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
SystemNavigator.pop();
},
child: const Text("Yes"),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("No"),
),
],
),
],
),
),
);
},
child: Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
titleSpacing: 0,
),
drawer: Drawer(),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 200,
color: Colors.grey,
child: const Center(
child: Text(
'this is\nHome Page',
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.white),
),
),
),
//
SizedBox(height: 20),
//
ElevatedButton(
child: const Text('Go to Page Two'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => const PageTwo()));
},
),
ElevatedButton(
child: const Text('Go to Page Three'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => const PageThree()));
},
),
],
),
),
),
);
}
}
page_two.dart
class PageTwo extends StatefulWidget {
const PageTwo({Key key}) : super(key: key);
@override
_PageTwoState createState() => _PageTwoState();
}
class _PageTwoState extends State<PageTwo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Page Two'),
titleSpacing: 0,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 200,
color: Colors.grey,
child: const Center(
child: Text(
'this is\nPage TWO',
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.white),
),
),
),
//
SizedBox(height: 20),
//
ElevatedButton(
child: const Text('Go to Page Three'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => const PageThree()));
},
),
//
ElevatedButton(
child: const Text('Go to Home Page'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => const HomePage()));
},
),
],
),
),
);
}
}
page_three.dart
class PageThree extends StatefulWidget {
const PageThree({Key key}) : super(key: key);
@override
_PageThreeState createState() => _PageThreeState();
}
class _PageThreeState extends State<PageThree> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Page Three'),
titleSpacing: 0,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 200,
color: Colors.grey,
child: const Center(
child: Text(
'this is\nPage THREE',
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.white),
),
),
),
//
SizedBox(height: 20),
//
ElevatedButton(
child: const Text('Go to Page TWO'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => const PageTwo()));
},
),
],
),
),
);
}
}
Thus the article on how to display the google_mobile_ads banner ad at the bottom of the page. I am very happy for the correction of all friends. I hope this article helps your problem. Have a nice day