原生广告

原生广告是通过平台原本就有的界面组件向用户呈现的广告素材资源。这种广告使用您在构建布局时已经采用的同类视图进行展示,而且能以和周围视觉设计相称的形式呈现,让用户有浑然一体的使用体验。具体到代码编写层面,这意味着当原生广告加载时,您的应用会收到一个包含其素材资源的 NativeAd 对象,然后就由此应用(而不是 Google 移动广告 SDK)负责展示它们了。

总的来说,要想成功植入原生广告,需要完成两部分工作:一是通过 SDK 加载广告,二是在您的应用中展示广告内容。本指南将介绍如何使用 SDK 加载原生广告。

平台设置

原生广告通过平台原本就有的界面组件(例如,Android 中的 View 或 iOS 中的 UIView)向用户呈现。

由于原生广告需要使用平台原本就有的界面组件,因此此功能需要对 Android 和 iOS 进行额外的设置:

Android

在 Android 中实现 Google 移动广告插件需要一个可实现 NativeAdFactory 的类。NativeAdFactory 中包含一个可获取 NativeAd 和自定义选项并返回 NativeAdView 的方法。NativeAdView 是显示在应用中的视图。

您可以在 MainActivity.java 中实现此插件,也可以在 MainActivity.java 所在的同一目录中创建一个单独的类:

package my.app.path;

import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory;
import java.util.Map;

class NativeAdFactoryExample implements NativeAdFactory {
  @Override
  public NativeAdView createNativeAd(
      NativeAd nativeAd, Map<String, Object> customOptions) {
    // Create NativeAdView
  }
}

每个 NativeAdFactory 都需要使用 factoryId(一个唯一的 String 标识符)在 MainActivity.configureFlutterEngine(FlutterEngine) 中进行注册。您可以为应用所使用的每个唯一原生广告版式分别实现和注册一个 NativeAdFactory,也可以用单个 NativeAdFactory 处理所有版式。

在使用加入现有应用功能进行构建时,还应在 cleanUpFlutterEngine(engine) 中取消注册 NativeAdFactory

MainActivity.java 应类似于:

package my.app.path;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin;

public class MainActivity extends FlutterActivity {
  @Override
  public void configureFlutterEngine(FlutterEngine flutterEngine) {
    flutterEngine.getPlugins().add(new GoogleMobileAdsPlugin());
   super.configureFlutterEngine(flutterEngine);

    GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "adFactoryExample", NativeAdFactoryExample());
  }

  @Override
  public void cleanUpFlutterEngine(FlutterEngine flutterEngine) {
    GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample");
  }
}

在 Dart 中创建 NativeAd 时,factoryId 需要与将工厂添加到 GoogleMobileAdsPlugin 时所用的工厂 ID 相符。在上述代码段中,adFactoryExamplefactoryId 的名称。下面是一个 NativeAdFactory 示例:

package io.flutter.plugins.googlemobileadsexample;

import android.graphics.Color;
import android.view.LayoutInflater;
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.NativeAdFactory;
import java.util.Map;

/**
 * my_native_ad.xml can be found at
 * //github.com/googleads/googleads-mobile-flutter/tree/master/packages/google_mobile_ads/example/android/app/src/main/res/layout
 */
class NativeAdFactoryExample implements NativeAdFactory {
  private final LayoutInflater layoutInflater;

  NativeAdFactoryExample(LayoutInflater layoutInflater) {
    this.layoutInflater = layoutInflater;
  }

  @Override
  public NativeAdView createNativeAd(
      NativeAd nativeAd, Map<String, Object> customOptions) {
    final NativeAdView adView =
        (NativeAdView) layoutInflater.inflate(R.layout.my_native_ad, null);
    final TextView headlineView = adView.findViewById(R.id.ad_headline);
    final TextView bodyView = adView.findViewById(R.id.ad_body);

    headlineView.setText(nativeAd.getHeadline());
    bodyView.setText(nativeAd.getBody());

    adView.setBackgroundColor(Color.YELLOW);

    adView.setNativeAd(nativeAd);
    adView.setBodyView(bodyView);
    adView.setHeadlineView(headlineView);
    return adView;
  }
}

iOS

在 iOS 中实现 Google 移动广告插件需要一个可实现 FLTNativeAdFactory 的类。FLTNativeAdFactory 中包含一个可获取 GADNativeAd 和自定义选项并返回 GADNativeAdView 的方法。GADNativeAdView 是显示在应用中的视图。

您可以通过 AppDelegate 实现 FLTNativeAdFactory 协议,也可以创建一个单独的类:

/* AppDelegate.m */
#import "FLTGoogleMobileAdsPlugin.h"
@interface NativeAdFactoryExample : NSObject<FLTNativeAdFactory>
@end

@implementation NativeAdFactoryExample
- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
                             customOptions:(NSDictionary *)customOptions {
  // Create GADNativeAdView
}
@end

每个 FLTNativeAdFactory 都需要使用 factoryId(一个唯一的 String 标识符)在 registerNativeAdFactory:factoryId:nativeAdFactory: 中进行注册。

您可以为应用所使用的每个唯一原生广告版式分别实现和注册一个 FLTNativeAdFactory,也可以用单个 FLTNativeAdFactory 处理所有版式。为此,您需要导入 FLTGoogleMobileAdsPlugin.h 并使用 FlutterPluginRegistry(工厂的唯一标识符)和工厂本身调用 registerNativeAdFactory:factoryId:nativeAdFactory:,还必须在调用 GeneratedPluginRegistrant registerWithRegistry:self]; 后添加工厂。

如果 AppDelegate.m 中的操作完成,应显示如下:

#import "FLTGoogleMobileAdsPlugin.h"

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  NativeAdFactoryExample *nativeAdFactory = [[NativeAdFactoryExample alloc] init];
  [FLTGoogleMobileAdsPlugin registerNativeAdFactory:self
                                          factoryId:@"adFactoryExample"
                                    nativeAdFactory:nativeAdFactory];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

在 Dart 中创建 NativeAd 时,factoryID 需要与将工厂添加到 FLTGoogleMobileAdsPlugin 时所用的工厂 ID 相符。在上述代码段中,adFactoryExamplefactoryID 的名称。请查看以下 FLTNativeAdFactory 示例:

/**
 * The example NativeAdView.xib can be found at
 * //github.com/googleads/googleads-mobile-flutter/blob/master/packages/google_mobile_ads/example/ios/Runner/NativeAdView.xib
 */
@interface NativeAdFactoryExample : NSObject <FLTNativeAdFactory>
@end

@implementation NativeAdFactoryExample
- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
                             customOptions:(NSDictionary *)customOptions {
  // Create and place ad in view hierarchy.
  GADNativeAdView *adView =
      [[NSBundle mainBundle] loadNibNamed:@"NativeAdView" owner:nil options:nil].firstObject;

  // Associate the native ad view with the native ad object. This is
  // required to make the ad clickable.
  adView.nativeAd = nativeAd;

  // Populate the native ad view with the native ad assets.
  // The headline is guaranteed to be present in every native ad.
  ((UILabel *)adView.headlineView).text = nativeAd.headline;

  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  ((UILabel *)adView.bodyView).text = nativeAd.body;
  adView.bodyView.hidden = nativeAd.body ? NO : YES;

  [((UIButton *)adView.callToActionView) setTitle:nativeAd.callToAction
                                         forState:UIControlStateNormal];
  adView.callToActionView.hidden = nativeAd.callToAction ? NO : YES;

  ((UIImageView *)adView.iconView).image = nativeAd.icon.image;
  adView.iconView.hidden = nativeAd.icon ? NO : YES;

  ((UILabel *)adView.storeView).text = nativeAd.store;
  adView.storeView.hidden = nativeAd.store ? NO : YES;

  ((UILabel *)adView.priceView).text = nativeAd.price;
  adView.priceView.hidden = nativeAd.price ? NO : YES;

  ((UILabel *)adView.advertiserView).text = nativeAd.advertiser;
  adView.advertiserView.hidden = nativeAd.advertiser ? NO : YES;

  // In order for the SDK to process touch events properly, user interaction
  // should be disabled.
  adView.callToActionView.userInteractionEnabled = NO;

  return adView;
}
@end

务必用测试广告进行测试

在构建和测试应用时,请确保使用的是测试广告,而不是实际投放的广告。否则,可能会导致您的帐号被暂停。

对于原生广告,加载测试广告最简便的方法就是使用我们的专用测试广告单元 ID:

这些测试广告单元 ID 已经过专门配置,可确保每个请求返回的都是测试广告。您可以在自己应用的编码、测试和调试过程中随意使用这些测试广告单元 ID。只是一定要在发布应用前用您自己的广告单元 ID 替换这些测试广告单元 ID。

实例化广告

NativeAd 需要 adUnitIdfactoryIdAdRequestNativeAdListener。以下示例实例化了一个原生广告:

final NativeAd myNative = NativeAd(
  adUnitId: '<ad unit id>',
  factoryId: 'adFactoryExample',
  request: AdRequest(),
  listener: NativeAdListener(),
);

工厂 ID

factoryId 需要与将工厂添加到 Android 中的 GoogleMobileAdsPlugin 和/或 iOS 中的 FLTGoogleMobileAdsPlugin 时所用的工厂 ID 相符。两个平台可以使用同一 factoryId,每个平台也可以使用自己的工厂 ID。

原生广告事件

通过使用 NativeAdListener,您可以监听各种广告生命周期事件,例如广告何时加载。以下示例实现了每个方法,并将消息记录到控制台:

final NativeAdListener listener = NativeAdListener(
 // Called when an ad is successfully received.
 onAdLoaded: (Ad ad) => print('Ad loaded.'),
 // Called when an ad request failed.
 onAdFailedToLoad: (Ad ad, LoadAdError error) {
   // Dispose the ad here to free resources.
   ad.dispose();
   print('Ad failed to load: $error');
 },
 // Called when an ad opens an overlay that covers the screen.
 onAdOpened: (Ad ad) => print('Ad opened.'),
 // Called when an ad removes an overlay that covers the screen.
 onAdClosed: (Ad ad) => print('Ad closed.'),
 // Called when an impression occurs on the ad.
 onAdImpression: (Ad ad) => print('Ad impression.'),
 // Called when a click is recorded for a NativeAd.
 onNativeAdClicked: (NativeAd ad) => print('Ad clicked.'),
);

加载广告

实例化 NativeAd 之后,必须先调用 load(),然后才能将其展示在屏幕上。

myNative.load();

展示广告

要以微件形式展示 NativeAd,您必须在调用 load() 之后实例化含有受支持广告的 AdWidget。您可以在调用 load() 之前创建微件,但必须先调用 load(),然后才能将该微件添加到微件树中。

final AdWidget adWidget = AdWidget(ad: myBanner);

AdWidget 继承自 Flutter 的 Widget 类,可以像其他任何微件一样使用。在 iOS 中,请确保将该微件放置在具有指定宽度和高度的容器中。否则,您的广告可能不会展示。

final Container adContainer = Container(
  alignment: Alignment.center,
  child: adWidget,
  width: 500,
  height: 500,
);

广告调用 load() 后,如果不再需要访问该方法,则必须调用 dispose()。调用 dispose() 的最佳做法是,在将 AdWidget 从微件树中移除后调用,或在 AdListener.onAdFailedToLoad 回调中调用。

大功告成!您的应用现在就可以展示原生广告了。

后续步骤