Flutter:如何在所有页面上显示google_mobile_ads横幅,而不需要像firebase_admob插件一样在每个页面上编写代码?

Ary*_*nzh 5 android admob flutter google-mobile-ads firebase-admob

本文适用于那些在从 firebase_admob 插件迁移到 google_mobile_ads 时遇到困难的用户。为方便起见,我将 firebase_admob 名称缩写为 FA,将 google_mobile_ads 缩写为 GMA。

据我们所知,FA 插件已停止使用并被 GMA 插件取代。FA 相对于 GMA 的优点之一是,FA 横幅将出现在整个页面上,而无需在其他页面上重写代码。但在 GMA 中,横幅仅出现在包含 GMA 代码的页面上。

与 FA 相比,GMA 有很多缺点,包括:

  • 切换页面时应用程序闪烁
  • 每个页面总是初始化横幅,这会带来高性能
  • 每页必须分配一个 GMA 代码

那么我们如何在我们的应用程序中实现 GMA 以避免出现问题呢?方式很简单,就是把一个页面变成一个tab。这只是在底部(bottomNavigation)显示横幅广告的一种方式。没有奖励或插页​​式广告。看看我下面的方法..

我的页面:

  • 主程序.dart
  • home_tab.dart
  • home_page.dart(是第一个选项卡)
  • 第二页.dart
  • 第三页.dart

我将在上面的页面上显示所有横幅。

在 pubspec.yaml 上

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  google_mobile_ads: ^1.0.1
Run Code Online (Sandbox Code Playgroud)

在 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'
...
}
Run Code Online (Sandbox Code Playgroud)

在 ...\android\gradle\wrapper\gradle-wrapper.properties 更改为 gradle 7.0.2

..
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
..
Run Code Online (Sandbox Code Playgroud)

在 ...\android\build.gradle 上将 Kotlin 版本更改为 1.6.10,将 gradle 版本更改为 7.0.0,如下代码所示:

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
}
Run Code Online (Sandbox Code Playgroud)

主程序.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(),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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,
          );
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我们将主页作为第一个选项卡 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()));
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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()));
              },
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

page_三.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()));
              },
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,本文介绍了如何在页面底部显示 google_mobile_ads 横幅广告。很高兴得到各位朋友的指正。我希望这篇文章可以帮助您解决问题。祝你今天过得愉快