1. 简介
在此 Codelab 中,您将在 Flutter 应用中植入 AdMob 横幅广告和 AdMob 原生内嵌广告。
构建内容
此 Codelab 将指导您使用 Google 移动广告 Flutter 插件在 Flutter 应用中植入 AdMob 横幅内嵌广告和 AdMob 原生内嵌广告。
如果在此 Codelab 的操作期间遇到任何问题(代码错误、语法错误、措辞含义不明等),可以通过 Codelab 左下角的报告错误链接报告相应问题。
学习内容
- 如何配置 Google 移动广告 Flutter 插件
- 如何在 Flutter 应用中实现内嵌横幅激励广告
所需条件
- Android Studio 4.1 或更高版本
- Xcode 12 或更高版本(用于 iOS 开发)
您如何评价自己在 AdMob 方面的经验水平?
您如何评价自己在 Flutter 方面的经验水平?
<ph type="x-smartling-placeholder">2. 设置您的 Flutter 开发环境
您需要使用两款软件才能完成此 Codelab:Flutter SDK 和一款编辑器。
您可使用以下任一设备学习此 Codelab:
- 一台连接到计算机并设置为开发者模式的实体 Android 或 iOS 设备。
- iOS 模拟器(需要安装 Xcode 工具)。
- Android 模拟器(需要在 Android Studio 中设置)。
- 浏览器(需要使用 Chrome,以便进行调试)。
- 对于 Windows、Linux 或 macOS 桌面应用,您必须在打算部署到的平台上进行开发。因此,如果您要开发 Windows 桌面应用,则必须在 Windows 上进行开发,才能使用相应的构建链。如需详细了解针对各种操作系统的具体要求,请访问 docs.flutter.dev/desktop。
下载代码
下载 ZIP 文件后,解压其内容。您将会看到名为 admob-inline-ads-in-flutter-main
的文件夹。
或者,您也可以从命令行克隆 GitHub 代码库:
$ git clone https://github.com/googlecodelabs/admob-inline-ads-in-flutter
该代码库包含三个文件夹:
- starter:您将在此 Codelab 中构建的入门级代码。
- complete:此 Codelab 完成后的代码。(Java 和 Objective-C 版原生代码)
- complete_kotlin_swift:此 Codelab 完成后的代码。(Kotlin 和 Swift 版原生代码)
3. 设置 AdMob 应用和广告单元
由于 Flutter 是一个多平台 SDK,因此您需要在 AdMob 中添加对 Android 和 iOS 都适用的应用和广告单元。
针对 Android 进行设置
如需针对 Android 进行设置,您需要添加 iOS 应用并创建广告单元。
添加 Android 应用
- 在 AdMob 控制台中,点击应用菜单中的添加应用。
- 当系统询问“您是否已在 Google Play 或 App Store 中发布您的应用?”时,点击否。
- 在应用名称字段中输入
AdMob inline ads
,然后选择 Android 作为平台。
- 您不必启用用户指标就能完成此 Codelab。不过,我们仍建议您启用用户指标,以便更详细地了解用户行为。点击添加以完成该流程。
创建广告单元
如需添加广告单元,请按以下步骤操作:
- 在 AdMob 控制台的应用菜单中,选择 AdMob 内嵌广告应用。
- 点击广告单元菜单。
横幅广告
|
原生广告
|
新的广告单元需要过几小时才能开始投放广告。
如果您想立即测试广告的行为,请使用“Android 应用 ID/广告单元 ID”和“iOS 应用 ID/广告单元 ID”表格中列出的测试应用 ID 和广告单元 ID。
针对 iOS 进行设置
如需针对 iOS 进行设置,您需要添加 iOS 应用并创建广告单元。
添加 iOS 应用
- 在 AdMob 控制台中,点击应用菜单中的添加应用。
- 当系统询问“您是否已在 Google Play 或 App Store 中发布您的应用?”时,点击否。
- 在应用名称字段中输入
AdMob inline ads
,然后选择 iOS 作为平台。
- 您不必启用用户指标就能完成此 Codelab。不过,我们仍建议您启用用户指标,以便更详细地了解用户行为。点击添加以完成该流程。
创建广告单元
如需添加广告单元,请按以下步骤操作:
- 在 AdMob 控制台的应用菜单中,选择 AdMob 内嵌广告应用。
- 点击广告单元菜单。
横幅广告
|
原生广告
|
新的广告单元需要过几小时才能开始投放广告。
如果您想立即测试广告的行为,请使用下表中列出的测试应用 ID 和广告单元 ID。
可选:使用测试 AdMob 应用和广告单元
如果您希望按照此 Codelab 操作,而不是自行创建新的应用和广告单元,可以使用下表列出的测试 AdMob 应用 ID 和广告单元 ID。
Android 应用 ID/广告单元 ID
项目 | 应用 ID/广告单元 ID |
AdMob 应用 ID |
|
横幅广告 |
|
原生广告 |
|
iOS 应用 ID/广告单元 ID
项目 | 应用 ID/广告单元 ID |
AdMob 应用 ID |
|
横幅广告 |
|
原生广告 |
|
如需详细了解测试广告,请参阅 Android 测试广告和 iOS 测试广告开发者文档。
4. 添加 Google 移动广告 Flutter 插件
Flutter 使用插件提供对各类平台专用服务的访问权限。借助插件,您可以访问各个平台上的服务和 API。
google_mobile_ads 插件支持使用 AdMob API 加载和展示横幅广告、插页式广告、激励广告和原生广告。
由于 Flutter 是一个多平台 SDK,因此 google_mobile_ads 插件既适用于 iOS 也适用于 Android。因此,如果您将该插件添加到 Flutter 应用,Android 版和 iOS 版 AdMob 内嵌广告应用都会使用该插件。
将 Google 移动广告插件添加为依赖项
如需从 AdMob 内嵌广告项目访问 AdMob API,请将 google_mobile_ads
作为依赖项添加到项目根目录下的 pubspec.yaml
文件中。
pubspec.yaml
...
dependencies:
flutter:
sdk: flutter
google_fonts: ^0.3.9
# TODO: Add google_mobile_ads as a dependency
google_mobile_ads: ^1.2.0
...
点击 Pub get,以在 AdMob 内嵌广告项目中安装该插件。
更新 AndroidManifest.xml (Android)
- 在 Android Studio 中打开
android/app/src/main/AndroidManifest.xml
文件。 - 添加
<meta-data>
标签并将名称指定为com.google.android.gms.ads.APPLICATION_ID
,以 添加您的 AdMob 应用 ID。例如,如果您的 AdMob 应用 ID 为ca-app-pub-3940256099942544~3347511713
,则需要将以下行添加到AndroidManifest.xml
文件中。
AndroidManifest.xml
<manifest>
...
<application>
...
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
</application>
</manifest>
更新 Info.plist (iOS)
- 在 Android Studio 中打开
ios/Runner/Info.plist
文件。 - 添加一个
GADApplicationIdentifier
键,并将 AdMob 应用 ID 设为相应字符串值。例如,如果您的 AdMob 应用 ID 为ca-app-pub-3940256099942544~1458002511
,则需要将以下行添加到Info.plist
文件中。
ios/Runner/Info.plist
...
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
...
5. 为广告添加辅助类
在 lib
目录下创建名为 ad_helper.dart
的新文件。然后,实现 AdHelper
类,该类会提供对 Android 和 iOS 都适用的 AdMob 应用 ID 和广告单元 ID。
请务必将 AdMob 应用 ID (ca-app-pub-xxxxxx~yyyyy
) 和广告单元 ID (ca-app-pub-xxxxxxx/yyyyyyyy
) 替换为您在上一步中创建的 ID。
ad_helper.dart
import 'dart:io';
class AdHelper {
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_BANNER_AD_UNIT_ID";
} else if (Platform.isIOS) {
return "<YOUR_IOS_BANNER_AD_UNIT_ID>";
} else {
throw UnsupportedError("Unsupported platform");
}
}
static String get nativeAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_NATIVE_AD_UNIT_ID>";
} else if (Platform.isIOS) {
return "<YOUR_IOS_NATIVE_AD_UNIT_ID>";
} else {
throw UnsupportedError("Unsupported platform");
}
}
}
如果您希望使用测试 AdMob 应用 ID 和测试广告单元 ID,请使用以下代码段。
ad_helper.dart
import 'dart:io';
class AdHelper {
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-3940256099942544/6300978111';
} else if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/2934735716';
}
throw UnsupportedError("Unsupported platform");
}
static String get nativeAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-3940256099942544/2247696110';
} else if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/3986624511';
}
throw UnsupportedError("Unsupported platform");
}
}
6. 初始化 Google 移动广告 SDK
加载广告之前,您需要初始化 Google 移动广告 SDK。打开 lib/home_page.dart
文件,并修改 _initGoogleMobileAds()
以在加载首页之前初始化 SDK。
请注意,您需要将 _initGoogleMobileAds()
方法的返回值类型从 Future<dynamic>
更改为 Future<InitializationStatus>
,以在完成后获取 SDK 初始化结果。
home_page.dart
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:flutter/material.dart';
...
class HomePage extends StatelessWidget {
...
Future<InitializationStatus> _initGoogleMobileAds() {
// TODO: Initialize Google Mobile Ads SDK
return MobileAds.instance.initialize();
}
}
7. 添加横幅广告
在该部分中,您将在列表中间展示横幅广告,如下面的屏幕截图所示。
- 打开
lib/banner_inline_page.dart
文件。 - 添加以下行以导入
ad_helper.dart
和google_mobile_ads.dart
:
banner_inline_page.dart
...
// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
class BannerInlinePage extends StatefulWidget {
...
}
- 在
_BannerInlinePageState
类中,为横幅广告添加以下组件和方法。
请注意,_kAdIndex
表示将展示横幅广告的索引,此索引可用于通过 _getDestinationItemIndex()
方法计算项目索引。
banner_inline_page.dart
class _BannerInlinePageState extends State<BannerInlinePage> {
// TODO: Add _kAdIndex
static final _kAdIndex = 4;
// TODO: Add a banner ad instance
BannerAd? _ad;
...
// TODO: Add _getDestinationItemIndex()
int _getDestinationItemIndex(int rawIndex) {
if (rawIndex >= _kAdIndex && _ad != null) {
return rawIndex - 1;
}
return rawIndex;
}
...
}
- 在
initState()
方法中,为 320x50 横幅广告 (AdSize.banner
) 创建并加载BannerAd
。请注意,广告事件监听器已配置为在加载广告时更新界面 (setState()
)。
banner_inline_page.dart
@override
void initState() {
super.initState();
// TODO: Load a banner ad
BannerAd(
adUnitId: AdHelper.bannerAdUnitId,
size: AdSize.banner,
request: AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() {
_ad = ad as BannerAd;
});
},
onAdFailedToLoad: (ad, error) {
// Releases an ad resource when it fails to load
ad.dispose();
print('Ad load failed (code=${error.code} message=${error.message})');
},
),
).load();
}
- 修改
build()
方法,以展示横幅广告(如果可用)。 - 更新
itemCount,
以计为一个横幅广告条目,并更新itemBuilder,
以便加载横幅广告后在广告索引 (_kAdIndex
) 处呈现该广告。 - 更新代码,以使用
_getDestinationItemIndex()
方法检索内容项的索引。
banner_inline_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: ListView.builder(
// TODO: Adjust itemCount based on the ad load state
itemCount: widget.entries.length + (_ad != null ? 1 : 0),
itemBuilder: (context, index) {
// TODO: Render a banner ad
if (_ad != null && index == _kAdIndex) {
return Container(
width: _ad!.size.width.toDouble(),
height: 72.0,
alignment: Alignment.center,
child: AdWidget(ad: _ad!),
);
} else {
// TODO: Get adjusted item index from _getDestinationItemIndex()
final item = widget.entries[_getDestinationItemIndex(index)];
return ListTile(
...
);
}
},
),
);
}
- 调用
dispose()
回调方法中的BannerAd.dispose()
方法,释放与BannerAd
对象关联的资源。
banner_inline_page.dart
@override
void dispose() {
// TODO: Dispose a BannerAd object
_ad?.dispose();
super.dispose();
}
大功告成!运行项目,然后点击首页上的横幅内嵌广告按钮。广告加载后,您将在列表中间看到横幅广告。
8. 添加原生广告
在该部分中,您将在列表中间展示原生广告,如下面的屏幕截图所示。
系统使用平台原生的界面组件(例如,Android 上的 View
或 iOS 上的 UIView
)向用户展示原生广告。
不过,您无法使用 Flutter 微件直接创建原生界面组件。因此,您必须针对各平台实现 NativeAdFactory
,此类可用于通过原生广告对象(Android 上的 NativeAd
和 iOS 上的 GADNativeAd
)构建平台专用原生广告视图(Android 上的 NativeAdView
和 iOS 上的 GADNativeAdView
)。
针对 Android (Java) 实现 NativeAdFactory
- 打开
android/build.gradle
文件(或 android 文件夹下的任何文件),然后点击 Open in Edit for Android Studio 以打开 Android 项目。
- 如果系统要求您选择一个窗口以打开新项目,请点击 New Window,以确保您在处理 Android 项目时保持 Flutter 项目处于打开状态。
创建原生广告布局
- 打开 Android 项目后,在 Android Studio 的项目窗格中右键点击 app,然后从上下文菜单中依次选择 New > Android Resource File。
- 在 New Resource File 对话框中,输入
list_tile_native_ad.xml
作为文件名。 - 选择 Layout 作为资源类型,并输入
com.google.android.gms.ads.nativead.NativeAdView
作为根元素。 - 点击 OK 以创建新的布局文件。
- 按以下方式实现广告布局。请注意,布局应该与布局面向的平台的用户体验视觉设计相匹配。
list_tile_native_ad.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F19938"
android:text="Ad"
android:textColor="#FFFFFF"
android:textSize="12sp" />
<ImageView
android:id="@+id/iv_list_tile_native_ad_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:scaleType="fitXY"
tools:background="#EDEDED" />
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_large"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:background="#F19938"
android:gravity="center"
android:text="Ad"
android:textColor="#FFFFFF"
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="80dp"
android:layout_marginLeft="80dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_list_tile_native_ad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#000000"
android:textSize="16sp"
tools:text="Headline" />
<TextView
android:id="@+id/tv_list_tile_native_ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#828282"
android:textSize="14sp"
tools:text="body" />
</LinearLayout>
</FrameLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
创建 ListTileNativeAdFactory 类
- 在 Project 窗格中,右键点击 com.codelab.flutter.admobinlineads 软件包,然后依次选择 New > Java Class。
- 输入
ListTileNativeAdFactory
作为名称,然后从列表中选择 Class。
- 出现 New Class 对话框后,将所有字段留空,然后点击 OK。
您会看到软件包 com.codelab.flutter.admobinlineads
中已创建 ListTileNativeAdFactory
类。
- 按如下方式实现
ListTileNativeAdFactory
类。请注意,该类会在GoogleMobileAdsPlugin.NativeAdFactory
接口中实现createNativeAd()
方法。
该工厂类负责创建用于呈现原生广告的视图对象。从代码可以看出,该工厂类创建了一个 UnifiedNativeAdView
,然后用 NativeAd
对象进行填充。
ListTileNativeAdFactory.java
// TODO: Implement ListTileNativeAdFactory class
package com.codelab.flutter.admobinlineads;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Map;
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin;
class ListTileNativeAdFactory implements GoogleMobileAdsPlugin.NativeAdFactory {
private final Context context;
ListTileNativeAdFactory(Context context) {
this.context = context;
}
@Override
public NativeAdView createNativeAd(
NativeAd nativeAd, Map<String, Object> customOptions) {
NativeAdView nativeAdView = (NativeAdView) LayoutInflater.from(context)
.inflate(R.layout.list_tile_native_ad, null);
TextView attributionViewSmall = nativeAdView
.findViewById(R.id.tv_list_tile_native_ad_attribution_small);
TextView attributionViewLarge = nativeAdView
.findViewById(R.id.tv_list_tile_native_ad_attribution_large);
ImageView iconView = nativeAdView.findViewById(R.id.iv_list_tile_native_ad_icon);
NativeAd.Image icon = nativeAd.getIcon();
if (icon != null) {
attributionViewSmall.setVisibility(View.VISIBLE);
attributionViewLarge.setVisibility(View.INVISIBLE);
iconView.setImageDrawable(icon.getDrawable());
} else {
attributionViewSmall.setVisibility(View.INVISIBLE);
attributionViewLarge.setVisibility(View.VISIBLE);
}
nativeAdView.setIconView(iconView);
TextView headlineView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_headline);
headlineView.setText(nativeAd.getHeadline());
nativeAdView.setHeadlineView(headlineView);
TextView bodyView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_body);
bodyView.setText(nativeAd.getBody());
bodyView.setVisibility(nativeAd.getBody() != null ? View.VISIBLE : View.INVISIBLE);
nativeAdView.setBodyView(bodyView);
nativeAdView.setNativeAd(nativeAd);
return nativeAdView;
}
}
注册 ListTileNativeAdFactory 类
NativeAdFactory
的实例应注册到 GoogleMobileAdsPlugin
,然后才能从 Flutter 端使用。
- 打开
MainActivity.java
文件,并替换configureFlutterEngine()
方法和cleanUpFlutterEngine()
方法。 - 在
configureFlutterEngine()
方法中使用唯一字符串 ID (listTile
) 注册ListTileNativeAdFactory
类。
MainActivity.java
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
// TODO: Register the ListTileNativeAdFactory
GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "listTile",
new ListTileNativeAdFactory(getContext()));
}
...
}
- 在清理流程中,应取消注册每个
NativeAdFactory
实例。取消注册cleanUpFlutterEngine()
方法中的ListTileNativeAdFactory
类。
MainActivity.java
public class MainActivity extends FlutterActivity {
...
@Override
public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.cleanUpFlutterEngine(flutterEngine);
// TODO: Unregister the ListTileNativeAdFactory
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile");
}
}
现在,您可以使用 ListTileNativeAdFactory
类在 Android 上呈现原生广告了。
针对 Android (Kotlin) 实现 NativeAdFactory
- 打开
android/build.gradle
文件(或 android 文件夹下的任何文件),然后点击 Open in Edit for Android Studio 以打开 Android 项目。
- 如果系统要求您选择一个窗口以打开新项目,请点击 New Window,以确保您在处理 Android 项目时保持 Flutter 项目处于打开状态。
创建原生广告布局
- 打开 Android 项目后,在 Android Studio 的项目窗格中右键点击 app,然后从上下文菜单中依次选择 New > Android Resource File。
- 在 New Resource File 对话框中,输入
list_tile_native_ad.xml
作为文件名。 - 选择 Layout 作为资源类型,并输入
com.google.android.gms.ads.nativead.NativeAdView
作为根元素。 - 点击 OK 以创建新的布局文件。
- 按以下方式实现广告布局。请注意,布局应该与布局面向的平台的用户体验视觉设计相匹配。
list_tile_native_ad.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F19938"
android:text="Ad"
android:textColor="#FFFFFF"
android:textSize="12sp" />
<ImageView
android:id="@+id/iv_list_tile_native_ad_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:scaleType="fitXY"
tools:background="#EDEDED" />
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_large"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:background="#F19938"
android:gravity="center"
android:text="Ad"
android:textColor="#FFFFFF"
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="80dp"
android:layout_marginLeft="80dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_list_tile_native_ad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#000000"
android:textSize="16sp"
tools:text="Headline" />
<TextView
android:id="@+id/tv_list_tile_native_ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#828282"
android:textSize="14sp"
tools:text="body" />
</LinearLayout>
</FrameLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
创建 ListTileNativeAdFactory 类
- 在 Project 窗格中,右键点击 com.codelab.flutter.admobinlineads 软件包,然后依次选择 New > Kotlin File/Class。
- 输入
ListTileNativeAdFactory
作为名称,然后从列表中选择 Class。
- 您会看到软件包
com.codelab.flutter.admobinlineads
中已创建ListTileNativeAdFactory
类。 - 按如下方式实现
ListTileNativeAdFactory
类。请注意,该类会在GoogleMobileAdsPlugin.NativeAdFactory
接口中实现createNativeAd()
方法。
该工厂类负责创建用于呈现原生广告的视图对象。从代码可以看出,该工厂类创建了一个 NativeAdView
,然后用 NativeAd
对象进行填充。
ListTileNativeAdFactory.kt
// TODO: Implement ListTileNativeAdFactory class
package com.codelab.flutter.admobinlineads
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 ListTileNativeAdFactory(val context: Context) : GoogleMobileAdsPlugin.NativeAdFactory {
override fun createNativeAd(
nativeAd: NativeAd,
customOptions: MutableMap<String, Any>?
): NativeAdView {
val nativeAdView = LayoutInflater.from(context)
.inflate(R.layout.list_tile_native_ad, null) as NativeAdView
with(nativeAdView) {
val attributionViewSmall =
findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_small)
val attributionViewLarge =
findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_large)
val iconView = findViewById<ImageView>(R.id.iv_list_tile_native_ad_icon)
val icon = nativeAd.icon
if (icon != null) {
attributionViewSmall.visibility = View.VISIBLE
attributionViewLarge.visibility = View.INVISIBLE
iconView.setImageDrawable(icon.drawable)
} else {
attributionViewSmall.visibility = View.INVISIBLE
attributionViewLarge.visibility = View.VISIBLE
}
this.iconView = iconView
val headlineView = findViewById<TextView>(R.id.tv_list_tile_native_ad_headline)
headlineView.text = nativeAd.headline
this.headlineView = headlineView
val bodyView = findViewById<TextView>(R.id.tv_list_tile_native_ad_body)
with(bodyView) {
text = nativeAd.body
visibility = if (nativeAd.body.isNotEmpty()) View.VISIBLE else View.INVISIBLE
}
this.bodyView = bodyView
setNativeAd(nativeAd)
}
return nativeAdView
}
}
注册 ListTileNativeAdFactory 类
NativeAdFactory
的实例应注册到 GoogleMobileAdsPlugin
,然后才能从 Flutter 端使用。
- 打开
MainActivity.kt
文件,并替换configureFlutterEngine()
方法和cleanUpFlutterEngine()
方法。 - 在
configureFlutterEngine()
方法中使用唯一字符串 ID (listTile
) 注册ListTileNativeAdFactory
类。
MainActivity.kt
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// TODO: Register the ListTileNativeAdFactory
GoogleMobileAdsPlugin.registerNativeAdFactory(
flutterEngine, "listTile", ListTileNativeAdFactory(context))
}
...
}
- 在清理流程中,应取消注册每个
NativeAdFactory
实例。取消注册cleanUpFlutterEngine()
方法中的ListTileNativeAdFactory
类。
MainActivity.kt
class MainActivity: FlutterActivity() {
...
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
super.cleanUpFlutterEngine(flutterEngine)
// TODO: Unregister the ListTileNativeAdFactory
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile")
}
}
现在,您可以使用 ListTileNativeAdFactory
类在 Android 上呈现原生广告了。
针对 iOS (Objective-C) 实现 NativeAdFactory
打开 ios/Podfile
文件(或 ios 文件夹中的任意文件),然后点击 Open iOS module in Xcode 以打开一个 iOS 项目。
准备原生广告布局
您需要配置自定义视图 (*.xib
) 来布局原生广告素材资源。在此 Codelab 中,可借助预配置视图减轻工作量。
在 Xcode 中打开的 iOS 项目后,请确认 Runner 项目中存在 ListTileNativeAdView.xib。
创建 ListTileNativeAdFactory 类
- 在项目导航器中,右键点击 Runner 组,然后选择 New File 以便为新类创建头文件。
- 在模板对话框中,选择 Header File,并将其命名为
ListTileNativeAdFactory
。 - 创建
ListTileNativeAdFactory.h
文件后,按以下方式定义ListNativeAdFactory
类:
ListTileNativeAdFactory.h
#ifndef ListTileNativeAdFactory_h
#define ListTileNativeAdFactory_h
// TODO: Import FLTGoogleMobileAdsPlugin.h
#import "FLTGoogleMobileAdsPlugin.h"
// TODO: Declare ListTileNativeAdFactory
@interface ListTileNativeAdFactory : NSObject<FLTNativeAdFactory>
@end
#endif /* ListTileNativeAdFactory_h */
- 从 Runner 组中选择 New File 以创建 Objective-C 文件。
- 在下一个对话框中,在 File 字段中输入
ListTileNativeAdFactory
,然后选择 Empty File 作为文件类型。
- 点击 Next 后,系统会提示您选择要在其中创建新文件的文件夹。无需更改任何设置,点击 Create。
- 按如下方式实现
ListTileNativeFactory
类。请注意,该类会在FLTNativeAdFactory
协议中实现createNativeAd()
方法。
该工厂类负责创建用于呈现原生广告的视图对象。从代码可以看出,该工厂类创建了一个 GADNativeAdView
,然后用 GADNativeAd
对象进行填充。
ListTileNativeAdFactory.m
// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"
// TODO: Implement ListTileNativeAdFactory
@implementation ListTileNativeAdFactory
- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
customOptions:(NSDictionary *)customOptions {
GADNativeAdView *nativeAdView =
[[NSBundle mainBundle] loadNibNamed:@"ListTileNativeAdView" owner:nil options:nil].firstObject;
((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
nativeAdView.bodyView.hidden = nativeAd.body ? NO : YES;
((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
nativeAdView.iconView.hidden = nativeAd.icon ? NO : YES;
nativeAdView.callToActionView.userInteractionEnabled = NO;
nativeAdView.nativeAd = nativeAd;
return nativeAdView;
}
@end
注册 ListTileNativeAdFacotry 类
FLTNativeAdFactory
的实现应注册到 FLTGoogleMobileAdsPlugin
,然后才能从 Flutter 端使用。
打开 AppDelegate.m
文件,通过调用 [FLTGoogleMobileAdsPlugin registerNativeAdFactory]
方法,使用唯一字符串 ID (listTile
) 注册 ListTileNativeAdFactory
。
AppDelegate.m
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// TODO: Register ListTileNativeAdFactory
ListTileNativeAdFactory *listTileFactory = [[ListTileNativeAdFactory alloc] init];
[FLTGoogleMobileAdsPlugin registerNativeAdFactory:self
factoryId:@"listTile"
nativeAdFactory:listTileFactory];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
现在,您可以使用 ListTileNativeAdFactory
在 iOS 上呈现原生广告了。
针对 iOS (Swift) 实现 NativeAdFactory
打开 ios/Podfile
文件(或 ios 文件夹中的任意文件),然后点击 Open iOS module in Xcode 以打开一个 iOS 项目。
准备原生广告布局
您需要配置自定义视图 (*.xib
) 来布局原生广告素材资源。在此 Codelab 中,可借助预配置视图减轻工作量。
在 Xcode 中打开的 iOS 项目后,请确认 Runner 项目中存在 ListTileNativeAdView.xib。
创建 ListTileNativeAdFactory 类
- 在项目导航器中,右键点击 Runner 组,然后选择 New File 以便为新类创建头文件。
- 在模板对话框中,选择 Swift File,并将其命名为
ListTileNativeAdFactory
。 - 创建
ListTileNativeAdFactory.swift
文件后,请实现ListNativeAdFactory
类。
请注意,该类会在 FLTNativeAdFactory
协议中实现 createNativeAd()
方法。
该工厂类负责创建用于呈现原生广告的视图对象。从代码可以看出,该工厂类创建了一个 GADNativeAdView
,然后用 GADNativeAd
对象进行填充。
ListTileNativeAdFactory.swift
// TODO: Import google_mobile_ads
import google_mobile_ads
// TODO: Implement ListTileNativeAdFactory
class ListTileNativeAdFactory : FLTNativeAdFactory {
func createNativeAd(_ nativeAd: GADNativeAd,
customOptions: [AnyHashable : Any]? = nil) -> GADNativeAdView? {
let nibView = Bundle.main.loadNibNamed("ListTileNativeAdView", owner: nil, options: nil)!.first
let nativeAdView = nibView as! GADNativeAdView
(nativeAdView.headlineView as! UILabel).text = nativeAd.headline
(nativeAdView.bodyView as! UILabel).text = nativeAd.body
nativeAdView.bodyView!.isHidden = nativeAd.body == nil
(nativeAdView.iconView as! UIImageView).image = nativeAd.icon?.image
nativeAdView.iconView!.isHidden = nativeAd.icon == nil
nativeAdView.callToActionView?.isUserInteractionEnabled = false
nativeAdView.nativeAd = nativeAd
return nativeAdView
}
}
注册 ListTileNativeAdFacotry 类
FLTNativeAdFactory
的实现应注册到 FLTGoogleMobileAdsPlugin
,然后才能从 Flutter 端使用。
打开 AppDelegate.m
文件,通过调用 FLTGoogleMobileAdsPlugin.registerNativeAdFactory()
方法,使用唯一字符串 ID (listTile
) 注册 ListTileNativeAdFactory
。
AppDelegate.swift
import UIKit
import Flutter
// TODO: Import google_mobile_ads
import google_mobile_ads
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// TODO: Register ListTileNativeAdFactory
let listTileFactory = ListTileNativeAdFactory()
FLTGoogleMobileAdsPlugin.registerNativeAdFactory(
self, factoryId: "listTile", nativeAdFactory: listTileFactory)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
现在,您可以使用 ListTileNativeAdFactory
在 iOS 上呈现原生广告了。
将原生广告与 Flutter 微件集成
- 打开
lib/native_inline_page.dart
文件。然后,通过添加以下行导入ad_helper.dart
和google_mobile_ads.dart
:
native_inline_page.dart
...
// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
class NativeInlinePage extends StatefulWidget {
...
}
- 在
_NativeInlinePageState
类中,为原生广告添加以下组件和方法。
请注意,_kAdIndex
表示将展示横幅广告的索引,此索引可用于通过 _getDestinationItemIndex()
方法计算项目索引。
native_inline_page.dart
class _NativeInlinePageState extends State<NativeInlinePage> {
// TODO: Add _kAdIndex
static final _kAdIndex = 4;
// TODO: Add a native ad instance
NativeAd? _ad;
...
// TODO: Add _getDestinationItemIndex()
int _getDestinationItemIndex(int rawIndex) {
if (rawIndex >= _kAdIndex && _ad != null) {
return rawIndex - 1;
}
return rawIndex;
}
...
}
- 在
initState()
方法中,创建并加载使用ListTileNativeAdFactory
生成原生广告视图的NativeAd
。
请注意,以下代码中使用了用于将工厂注册到插件的同个工厂 ID (listTile
)。
native_inline_page.dart
@override
void initState() {
super.initState();
// TODO: Create a NativeAd instance
_ad = NativeAd(
adUnitId: AdHelper.nativeAdUnitId,
factoryId: 'listTile',
request: AdRequest(),
listener: NativeAdListener(
onAdLoaded: (ad) {
setState(() {
_ad = ad as NativeAd;
});
},
onAdFailedToLoad: (ad, error) {
// Releases an ad resource when it fails to load
ad.dispose();
print('Ad load failed (code=${error.code} message=${error.message})'); },
),
);
_ad.load();
}
- 修改
build()
方法,以展示横幅广告(如果可用)。 - 更新
itemCount,
以计为一个横幅广告条目,并更新itemBuilder,
以便加载横幅广告后在广告索引 (_kAdIndex
) 处呈现该广告。 - 更新代码,以使用
_getDestinationItemIndex()
方法检索内容项的索引。
native_inline_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: ListView.builder(
// TODO: Adjust itemCount based on the ad load state
itemCount: widget.entries.length + (_ad != null ? 1 : 0),
itemBuilder: (context, index) {
// TODO: Render a banner ad
if (_ad != null && index == _kAdIndex) {
return Container(
height: 72.0,
alignment: Alignment.center,
child: AdWidget(ad: _ad!),
);
} else {
// TODO: Get adjusted item index from _getDestinationItemIndex()
final item = widget.entries[_getDestinationItemIndex(index)];
return ListTile(
...
);
}
},
),
);
}
- 调用
dispose()
回调方法中的NativeAd.dispose()
方法,释放与NativeAd
对象关联的资源。
native_inline_page.dart
@override
void dispose() {
// TODO: Dispose a NativeAd object
_ad?.dispose();
super.dispose();
}
大功告成!运行项目,然后点击首页上的原生内嵌广告按钮。广告加载后,您将在列表中间看到原生广告。
9. 全部完成!
您已完成此 Codelab。您可以在 complete 或 complete_kotlin_swift 文件夹中找到此 Codelab 的完整代码。