许多开发者通过广告将其移动应用和游戏变现。这使得他们的应用可以免费下载,从而提高了应用的普及度。

An illustration of a smartphone showing an ad

要向您的 Flutter 项目添加广告,请使用 Google 的移动广告平台 AdMob。本教程演示如何使用 google_mobile_ads 包向您的应用或游戏添加横幅广告。

1. 获取 AdMob 应用 ID

#
  1. 前往 AdMob 并设置一个帐户。这可能需要一些时间,因为您需要提供银行信息、签署合同等。

  2. AdMob 帐户准备就绪后,在 AdMob 中创建两个 应用:一个用于 Android,一个用于 iOS。

  3. 打开应用设置部分。

  4. 获取 Android 应用和 iOS 应用的 AdMob 应用 ID。它们类似于 ca-app-pub-1234567890123456~1234567890。请注意两个数字之间的波浪号 (~)。

    Screenshot from AdMob showing the location of the App ID

2. 平台专属设置

#

更新您的 Android 和 iOS 配置以包含您的应用 ID。

Android

#

将您的 AdMob 应用 ID 添加到您的 Android 应用。

  1. 打开应用的 android/app/src/main/AndroidManifest.xml 文件。

  2. 添加一个新的 <meta-data> 标签。

  3. android:name 元素的值设置为 com.google.android.gms.ads.APPLICATION_ID

  4. android:value 元素的值设置为您在上一步中获得的 AdMob 应用 ID。如所示将其包含在引号中

    xml
    <manifest>
        <application>
            ...
    
            <!-- Sample AdMob app ID: ca-app-pub-3940256099942544~3347511713 -->
            <meta-data
                android:name="com.google.android.gms.ads.APPLICATION_ID"
                android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
        </application>
    </manifest>

iOS

#

将您的 AdMob 应用 ID 添加到您的 iOS 应用。

  1. 打开应用的 ios/Runner/Info.plist 文件。

  2. key 标签包围 GADApplicationIdentifier

  3. string 标签包围您的 AdMob 应用 ID。您在第 1 步中创建了此 AdMob 应用 ID。

    xml
    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-################~##########</string>

3. 添加 google_mobile_ads 插件

#

要将 google_mobile_ads 插件添加为依赖项,请运行 flutter pub add

flutter pub add google_mobile_ads

4. 初始化移动广告 SDK

#

在加载广告之前,您需要初始化移动广告 SDK。

  1. 调用 MobileAds.instance.initialize() 初始化移动广告 SDK。

    dart
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      unawaited(MobileAds.instance.initialize());
    
      runApp(const MyApp());
    }

如上所示,在启动时运行初始化步骤,以便 AdMob SDK 在需要之前有足够的时间进行初始化。

5. 加载横幅广告

#

要展示广告,您需要向 AdMob 请求。

要加载横幅广告,请构造一个 BannerAd 实例,并调用其 load() 方法。

dart
/// Loads a banner ad.
void _loadAd() {
  final bannerAd = BannerAd(
    size: widget.adSize,
    adUnitId: widget.adUnitId,
    request: const AdRequest(),
    listener: BannerAdListener(
      // Called when an ad is successfully received.
      onAdLoaded: (ad) {
        if (!mounted) {
          ad.dispose();
          return;
        }
        setState(() {
          _bannerAd = ad as BannerAd;
        });
      },
      // Called when an ad request failed.
      onAdFailedToLoad: (ad, error) {
        debugPrint('BannerAd failed to load: $error');
        ad.dispose();
      },
    ),
  );

  // Start loading.
  bannerAd.load();
}

要查看完整示例,请查看本教程的最后一步。

6. 展示横幅广告

#

一旦您加载了 BannerAd 实例,请使用 AdWidget 来展示它。

dart
AdWidget(ad: _bannerAd)

最好将小部件包装在 SafeArea(以防止广告的任何部分被设备缺口遮挡)和 SizedBox(以便它在加载前后具有其指定的固定大小)中。

dart
@override
Widget build(BuildContext context) {
  return SafeArea(
    child: SizedBox(
      width: widget.adSize.width.toDouble(),
      height: widget.adSize.height.toDouble(),
      child: _bannerAd == null
          // Nothing to render yet.
          ? const SizedBox()
          // The actual ad.
          : AdWidget(ad: _bannerAd!),
    ),
  );
}

当您不再需要访问广告时,必须将其释放。调用 dispose() 的最佳实践是在 AdWidget 从小部件树中移除后,或者在 BannerAdListener.onAdFailedToLoad() 回调中。

dart
_bannerAd?.dispose();

7. 配置广告

#

要展示测试广告之外的任何内容,您必须注册广告单元。

  1. 打开 AdMob

  2. 为每个 AdMob 应用创建一个广告单元

    Screenshot of the location of Ad Units in AdMob web UI

    这将要求提供广告单元的格式。AdMob 提供了除横幅广告之外的许多格式——插页式广告、激励广告、应用开启广告等。这些广告的 API 类似,并在 AdMob 文档官方示例中有所记录。

  3. 选择横幅广告。

  4. 获取 Android 应用和 iOS 应用的广告单元 ID。您可以在广告单元部分找到这些 ID。它们看起来类似于 ca-app-pub-1234567890123456/1234567890。格式类似于应用 ID,但两个数字之间有一个斜杠 (/)。这区分了广告单元 ID应用 ID

    Screenshot of an Ad Unit ID in AdMob web UI

  5. 根据目标应用平台,将这些广告单元 ID 添加到 BannerAd 的构造函数中。

    dart
    final String adUnitId = Platform.isAndroid
        // Use this ad unit on Android...
        ? 'ca-app-pub-3940256099942544/6300978111'
        // ... or this one on iOS.
        : 'ca-app-pub-3940256099942544/2934735716';

8. 最终润色

#

要在已发布的应用程序或游戏中展示广告(与调试或测试场景相对),您的应用程序必须满足额外要求

  1. 您的应用必须经过审核和批准才能完全投放广告。请遵循 AdMob 的应用准备指南。例如,您的应用必须在至少一个受支持的应用商店(如 Google Play 商店或 Apple App Store)上架。

  2. 您必须创建 app-ads.txt 文件并将其发布到您的开发者网站上。

An illustration of a smartphone showing an ad

要了解更多关于应用和游戏变现的信息,请访问 AdMobAd Manager 的官方网站。

9. 完整示例

#

以下代码实现了一个简单的有状态小部件,用于加载并显示横幅广告。

dart
import 'dart:io';

import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

class MyBannerAdWidget extends StatefulWidget {
  /// The requested size of the banner. Defaults to [AdSize.banner].
  final AdSize adSize;

  /// The AdMob ad unit to show.
  ///
  /// TODO: replace this test ad unit with your own ad unit
  final String adUnitId = Platform.isAndroid
      // Use this ad unit on Android...
      ? 'ca-app-pub-3940256099942544/6300978111'
      // ... or this one on iOS.
      : 'ca-app-pub-3940256099942544/2934735716';

  MyBannerAdWidget({super.key, this.adSize = AdSize.banner});

  @override
  State<MyBannerAdWidget> createState() => _MyBannerAdWidgetState();
}

class _MyBannerAdWidgetState extends State<MyBannerAdWidget> {
  /// The banner ad to show. This is `null` until the ad is actually loaded.
  BannerAd? _bannerAd;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: SizedBox(
        width: widget.adSize.width.toDouble(),
        height: widget.adSize.height.toDouble(),
        child: _bannerAd == null
            // Nothing to render yet.
            ? const SizedBox()
            // The actual ad.
            : AdWidget(ad: _bannerAd!),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    _loadAd();
  }

  @override
  void dispose() {
    _bannerAd?.dispose();
    super.dispose();
  }

  /// Loads a banner ad.
  void _loadAd() {
    final bannerAd = BannerAd(
      size: widget.adSize,
      adUnitId: widget.adUnitId,
      request: const AdRequest(),
      listener: BannerAdListener(
        // Called when an ad is successfully received.
        onAdLoaded: (ad) {
          if (!mounted) {
            ad.dispose();
            return;
          }
          setState(() {
            _bannerAd = ad as BannerAd;
          });
        },
        // Called when an ad request failed.
        onAdFailedToLoad: (ad, error) {
          debugPrint('BannerAd failed to load: $error');
          ad.dispose();
        },
      ),
    );

    // Start loading.
    bannerAd.load();
  }

}