本指南适用于希望使用 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 { idstrongConnector = _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 { idstrongConnector = _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]; }
其他定位参数
连接器包含一些常用的定位信息(如 testMode
、userKeywords
和 childDirectedTreatment
),可供您在定位广告时参考:
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
。