实现激励视频广告适配器

本指南适用于希望使用 AdMob 中介平台展示第三方广告联盟提供的激励视频广告吞吐量的发布商。

AdMob 支持的广告联盟和自定义事件

AdMob 中介平台直接支持的广告联盟实现的是标准中介适配器。而 AdMob 间接支持的广告联盟实现的是自定义事件适配器,但仍可用于请求和展示激励视频广告。下文概述了标准中介适配器与自定义事件适配器之间的区别。

定义服务器参数

对于通过 AdMob 中介平台进行中介的广告联盟,可能需要使用一个或多个标识符才能识别发布商。这些标识符以服务器参数的形式表示。当您在 AdMob 界面中配置用于中介的第三方广告联盟时,可以定义这些标识符。如果您要构建自定义事件适配器,请按照下文有关创建自定义事件的步骤操作。如果您要构建适配器,则会发现 AdMob 界面中已定义了您的广告联盟和相应的服务器参数。

创建自定义事件

要定义自定义事件,必须先在 AdMob 界面中创建自定义事件。有关说明,请参阅创建自定义事件。定义自定义事件后,它会指向您应用中某个通过实现 GADMRewardBasedVideoAdNetworkAdapter 来投放激励视频广告的类。此外,自定义事件还会列出传递给激励视频广告适配器的服务器参数。

以下屏幕截图显示的是自定义事件示例的部分设置:

上面显示的示例屏幕截图中的条目表示以下内容:

类名称 实现自定义事件的类的完全限定名称。
标签 事件的唯一名称。
参数 传递给自定义事件的可选参数。

实现中介适配器

本指南介绍了实现适配器所需执行的步骤。您可以使用示例广告联盟 SDK 了解实践中的适配器代码可能是什么样子。

初始化适配器

在应用发出初始激励视频广告请求后,Google 移动广告 SDK 会调用适配器的 initWithRewardBasedVideoAdNetworkConnector: 方法。您的适配器应对此方法提供的 GADMRewardBasedVideoAdNetworkConnector 保持弱引用,并使用此 GADMRewardBasedVideoAdNetworkConnector 对象与 Google 移动广告 SDK 进行互动。从这里开始,此对象也称为连接器。

下面展示了 initWithRewardBasedVideoAdNetworkConnector: 方法的实现示例:

Swift

required init!(rewardBasedVideoAdNetworkConnector connector: GADMRewardBasedVideoAdNetworkConnector!) {
  guard let connector = connector else {
    return nil
  }
  super.init()

  rewardBasedVideoAdConnector = connector
  adapterDelegate = SampleAdapterDelegate(rewardBasedVideoAdAdapter: self,
  rewardBasedVideoAdconnector: connector)
}

Objective-C

- (instancetype)initWithRewardBasedVideoAdNetworkConnector:
      (id)connector {
  if (!connector) {
    return nil;
  }

  self = [super init];
  if (self) {
    _rewardBasedVideoAdConnector = connector;
    _adapterDelegate = [[SampleAdapterDelegate alloc]
        initWithRewardBasedVideoAdAdapter:self
              rewardBasedVideoAdconnector:connector];
  }
  return self;
}

初始化完成后,Google 移动广告 SDK 会调用适配器的 setUp 方法,指示适配器应做好展示激励视频广告的准备。适配器负责通过实现此方法来初始化第三方广告联盟。此时,适配器还可以开始预加载激励视频广告吞吐量。通过连接器可以获取完成初始化所需的服务器参数。根据您要开发的是中介适配器还是自定义事件适配器,这些参数的获取方式略有不同。

对于中介适配器,服务器参数的密钥已预先配置,您可以逐个提取服务器参数。对于自定义事件,有一个参数可以通过 CUSTOM_EVENT_SERVER_PARAMETER 密钥获取。

中介适配器

Swift

let parameter1 = connector.credentials()["SERVER_PARAMETER_KEY1"] as? String
let parameter2 = connector.credentials()["SERVER_PARAMETER_KEY2"] as? String

Objective-C

NSString *parameter1 = [self.connector.credentials objectForKey:@"SERVER_PARAMETER_KEY1"];
NSString *parameter2 = [self.connector.credentials objectForKey:@"SERVER_PARAMETER_KEY2"];

自定义事件

Swift

let parameter = connector.credentials()[GADCustomEventParametersServer] as? String

Objective-C

NSString *parameter = [self.connector.credentials objectForKey:GADCustomEventParametersServer];

如果初始化成功,适配器应在连接器上调用 adapterDidSetUpRewardBasedVideoAd:。如果初始化失败,适配器应在连接器上调用 adapter:didFailToSetUpRewardBasedVideoAdWithError:。在初始化失败的情况下,每当有激励视频广告请求发出时,Google 移动广告 SDK 都会重新尝试初始化适配器。下面展示了 setUp 方法的实现示例:

Swift

func setUp() {
  rewardBasedVideoAd = SampleRewardBasedVideo.sharedInstance()
  if let delegate = adapterDelegate {
    rewardBasedVideoAd?.delegate = delegate
  }
  let adUnit = rewardBasedVideoAdConnector?.credentials()?["ad_unit"] as? String
  rewardBasedVideoAd?.adUnitID = adUnit
  let request = SampleAdRequest()
  // Set up request parameters.
  request.testMode = connector?.testMode() ?? false
  request.keywords = connector?.userKeywords() as! [String]
  rewardBasedVideoAd?.initialize(with: request, adUnitID: adUnit)
}

Objective-C

- (void)setUp {
  _rewardBasedVideoAd = [SampleRewardBasedVideo sharedInstance];
  _rewardBasedVideoAd.delegate = _adapterDelegate;
  NSString *adUnit = [_rewardBasedVideoAdConnector credentials][@"ad_unit"];
  _rewardBasedVideoAd.adUnit = adUnit;

  SampleAdRequest *request = [[SampleAdRequest alloc] init];
  // Set up request parameters.
  request.testMode = _connector.testMode;
  request.keywords = _connector.userKeywords;

  [_rewardBasedVideoAd initializeWithAdRequest:request adUnitID:adUnit];
}

加载激励视频广告吞吐量

在适配器调用 adapterDidSetUpRewardBasedVideoAd: 连接器方法后,Google 移动广告 SDK 便可以调用适配器的 requestRewardBasedVideoAd 方法。该方法会发出激励视频广告吞吐量请求。一旦有要展示的激励视频广告,适配器就会在连接器上调用 adapterDidReceiveRewardBasedVideoAd:。如果没有,适配器则在连接器上调用 adapter:didFailToLoadRewardBasedVideoAdWithError

对于激励视频广告,很多广告联盟会在不打算使用广告请求的情况下采用 API。在此类广告联盟完成初始化后,您可以检查对于当前用户是否有可用的广告资源,以及广告是否已准备就绪。如果条件满足,您就可以向用户展示广告了。下面展示了针对此类广告联盟的 requestRewardBasedVideoAd 实现示例:

Swift

func requestRewardBasedVideoAd() {
  guard let strongConnector = rewardBasedVideoAdConnector else {
    return
  }

  if rewardBasedVideoAd?.checkAdAvailability() == true {
    strongConnector.adapterDidReceiveRewardBasedVideoAd(self)
  }
  else {
    let description = "Failed to load ad."
    let userInfo = [NSLocalizedDescriptionKey: description,
                    NSLocalizedFailureReasonErrorKey: description]
    let error = NSError(domain: "com.google.mediation.sample", code: 0, userInfo: userInfo)
    strongConnector.adapter(self, didFailToLoadRewardBasedVideoAdwithError: error)
  }
}

Objective-C

- (void)requestRewardBasedVideoAd {
  id strongConnector = _rewardBasedVideoAdConnector;
  if ([_rewardBasedVideoAd checkAdAvailability]) {
    [strongConnector adapterDidReceiveRewardBasedVideoAd:self];
  } else {
    NSString *description = @"Failed to load ad.";
    NSDictionary *userInfo =
        @{NSLocalizedDescriptionKey : description,
        NSLocalizedFailureReasonErrorKey : description};
    NSError *error =
        [NSError errorWithDomain:@"com.google.mediation.sample" code:0 userInfo:userInfo];
    [strongConnector adapter:self didFailToLoadRewardBasedVideoAdwithError:error];
  }
}

展示激励视频广告吞吐量

在收到适配器发出的广告已成功加载的通知后,Google 移动广告 SDK 可能会随时调用适配器的 presentRewardBasedVideoAdWithRootViewController: 方法。每个成功完成的 loadAd 回调参数只能调用一次 presentRewardBasedVideoAdWithRootViewController: 方法。调用完此方法后,适配器就应该可以播放激励视频广告了。

Swift

func presentRewardBasedVideoAd(withRootViewController viewController: UIViewController) {
  if rewardBasedVideoAd?.checkAdAvailability() == true {
    // The reward based video ad is available, present the ad.
    rewardBasedVideoAd?.present(fromRootViewController: viewController)
  }
  else {
    // Because publishers are expected to check that an ad is available before
    // trying to show one, the above conditional should always hold true. If for
    // any reason the adapter is not ready to present an ad, however, it should
    // log an error with reason for failure.
    print("No ads to show.")
  }
}

Objective-C

- (void)presentRewardBasedVideoAdWithRootViewController:(UIViewController *)viewController {
  if ([_rewardBasedVideoAd checkAdAvailability]) {
    // The reward based video ad is available, present the ad.
    [_rewardBasedVideoAd presentFromRootViewController:viewController];
  } else {
    // Because publishers are expected to check that an ad is available before
    // trying to show one, the above conditional should always hold true. If for
    // any reason the adapter is not ready to present an ad, however, it should
    // log an error with reason for failure.
    NSLog(@"No ads to show.");
  }
}

向 Google 移动广告 SDK 转发广告事件

当发生以下任一广告事件时,适配器都必须通过调用相应的连接器方法来通知 Google 移动广告 SDK:

连接器方法 调用时间
adapterDidOpenRewardBasedVideoAd: 当应用内容之上叠加全屏叠加层时
adapterDidStartPlayingRewardBasedVideoAd: 当视频广告开始播放时
adapterDidGetAdClick: 当用户点击视频广告时
adapterWillLeaveApplication: 当用户因为要观看视频广告而退出应用(例如,转到浏览器)时
adapter:didRewardUserWithReward: 当视频广告奖励用户时
adapterDidCloseRewardBasedVideoAd: 当视频广告关闭时

通常情况下,广告联盟也有类似的一组可以转发给 Google 移动广告 SDK 的回调。示例 SDK 中的 SampleRewardBasedVideoDelegate 类就包含激励视频广告的回调。下面的示例展示了如何将这些回调转发给 Google 移动广告 SDK:

Swift

weak var rewardBasedVideoAdConnector : GADMRewardBasedVideoAdNetworkConnector?
weak var rewardBasedVideoAdAdapter : GADMRewardBasedVideoAdNetworkAdapter?

// MARK: SampleRewardBasedVideoDelegate methods
func rewardBasedVideoAdInitialized(_ rewardBasedVideo: SampleRewardBasedVideo) {
    guard let strongConnector = rewardBasedVideoAdConnector,
      let strongAdapter = rewardBasedVideoAdAdapter else {
        return
    }
    strongConnector.adapterDidSetUpRewardBasedVideoAd(strongAdapter)
}

func rewardBasedVideoAdDidReceiveAd(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
    strongConnector.adapterDidReceiveRewardBasedVideoAd(strongAdapter)
}

func rewardBasedVideoAdDidOpen(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
    strongConnector.adapterDidOpenRewardBasedVideoAd(strongAdapter)
}

func rewardBasedVideoAdDidStartPlaying(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
    strongConnector.adapterDidStartPlayingRewardBasedVideoAd(strongAdapter)
}
func rewardBasedVideoAdDidClose(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  strongConnector.adapterDidCloseRewardBasedVideoAd(strongAdapter)
}

func rewardBasedVideoAdWillLeaveApplication(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  strongConnector.adapterWillLeaveApplication(strongAdapter)
}

func rewardBasedVideoAdDidReceiveAdClick(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  strongConnector.adapterDidGetAdClick(strongAdapter)
}

func rewardBasedVideoAdDidReceiveAdClick(_ rewardBasedVideo: SampleRewardBasedVideo) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  strongConnector.adapterDidGetAdClick(strongAdapter)
}

func rewardBasedVideoAd(_ rewardBasedVideo: SampleRewardBasedVideo,
                        rewardUserWithReward reward: Int) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  // An empty string is passed to the reward type parameter because the Sample
  // SDK doesn't use a reward type and the reward type parameter cannot be nil.
  let rewardItem = GADAdReward(rewardType: "", rewardAmount: NSDecimalNumber(value:reward))
    strongConnector.adapter(strongAdapter, didRewardUserWith: rewardItem)
}

func rewardBasedVideoAd(_ rewardBasedVideo: SampleRewardBasedVideo,
                        didFailToLoadWithError error: SampleErrorCode) {
  guard let strongConnector = rewardBasedVideoAdConnector,
    let strongAdapter = rewardBasedVideoAdAdapter else {
      return
  }
  let adapterError = NSError(domain: "kAdapterErrorDomain",
                      code: error.rawValue, userInfo: nil)
    strongConnector.adapter(strongAdapter,
                        didFailToLoadRewardBasedVideoAdwithError: adapterError)
}

Objective-C

#pragma mark SampleRewardBasedVideoDelegate methods

- (void)rewardBasedVideoAdInitialized:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidSetUpRewardBasedVideoAd:strongAdapter];
}

- (void)rewardBasedVideoAdDidReceiveAd:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidReceiveRewardBasedVideoAd:strongAdapter];
}

- (void)rewardBasedVideoAdDidOpen:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidOpenRewardBasedVideoAd:strongAdapter];
}

- (void)rewardBasedVideoAdDidStartPlaying:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidStartPlayingRewardBasedVideoAd:strongAdapter];
}

- (void)rewardBasedVideoAdDidClose:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidCloseRewardBasedVideoAd:strongAdapter];
}

- (void)rewardBasedVideoAdWillLeaveApplication:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterWillLeaveApplication:strongAdapter];
}

- (void)rewardBasedVideoAdDidReceiveAdClick:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidGetAdClick:strongAdapter];
}

- (void)rewardBasedVideoAdDidReceiveAdClick:(SampleRewardBasedVideo *)rewardBasedVideo {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  [strongConnector adapterDidGetAdClick:strongAdapter];
}

- (void)rewardBasedVideoAd:(SampleRewardBasedVideo *)rewardBasedVideo
      rewardUserWithReward:(int)reward {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  // An empty string is passed to the reward type parameter because the Sample
  // SDK doesn't use a reward type and the reward type parameter cannot be nil.
  GADAdReward *rewardItem =
      [[GADAdReward alloc] initWithRewardType:@""
                                 rewardAmount:[NSDecimalNumber numberWithInteger:reward]];
  [strongConnector adapter:strongAdapter didRewardUserWithReward:rewardItem];
}

- (void)rewardBasedVideoAd:(SampleRewardBasedVideo *)rewardBasedVideo
      didFailToLoadWithError:(SampleErrorCode)error {
  id strongConnector = _rewardBasedVideoAdConnector;
  id strongAdapter = _rewardBasedVideoAdAdapter;
  NSError *adapterError = [NSError errorWithDomain:kAdapterErrorDomain code:error userInfo:nil];
  [strongConnector adapter:strongAdapter
didFailToLoadRewardBasedVideoAdwithError:adapterError];
}

其他定位参数

连接器包含一些常用的定位信息(如 testModeuserKeywordschildDirectedTreatment),可供您在定位广告时参考:

Swift

// Set up request parameters.
let request = SampleAdRequest()
request.testMode = connector?.testMode() ?? false
request.keywords = connector?.userKeywords() as? [String]

Objective-C

// Setup request parameters.
SampleAdRequest *request = [[SampleAdRequest alloc] init];
request.testMode = self.connector.testMode;
request.keywords = self.connector.userKeywords;

接受适配器的自定义参数

对于适配器通过中介联系的广告联盟而言,可支持连接器中提供的选项所未涉及的额外定位参数或输入内容。如果您的适配器也属于这种情况,可以要求发布商通过实现符合 GADAdNetworkExtras 协议要求的类来提供额外参数。

下面展示了 SampleAdNetworkExtras 类的示例:

Swift

class SampleAdNetworkExtras: NSObject, GADAdNetworkExtras {
  /// Should ad volume audio be muted.
  var isMuteAudio = false
}

Objective-C

@interface SampleAdNetworkExtras : NSObject 
/// Should ad volume audio be muted.
@property(nonatomic, assign) BOOL muteAudio;

@end

发布商必须在发出广告请求时传递 GADAdNetworkExtras 子类的实例。您可以通过连接器访问 GADAdNetworkExtras 子类的实例。下面展示了适配器如何提取发布商提供的额外参数,并使用这些参数构建面向第三方广告联盟的广告请求:

Swift

public static func networkExtrasClass() -> GADAdNetworkExtras.Type {
  return SampleAdNetworkExtras.self
}

Objective-C

+ (Class)networkExtrasClass {
  return [SampleAdNetworkExtras class];
}

如果您的适配器不使用中介额外参数,networkExtrasClass 方法应返回 Nil

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面