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

An illustration of a smartphone showing an ad

要将广告添加到您的 Flutter 项目,请使用 AdMob,Google 的移动广告平台。本食谱演示了如何使用 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();
  }

}