开始通过广告创收。
借助 IMA SDK,您可以轻松地将多媒体广告集成到网站和应用中。IMA SDK 可以从任何 符合 VAST 标准的广告服务器请求广告,并在您的应用中管理广告播放。借助 IMA 客户端 SDK,您可以继续控制内容视频播放,而 SDK 则负责处理广告播放。广告在位于应用内容视频播放器顶部的单独视频播放器中播放。
本指南演示了如何将 IMA SDK 集成到视频播放器应用中。如果您想查看或跟随完成的示例集成,请从 GitHub 下载 BasicExample。
IMA 客户端概览
实现 IMA 客户端涉及四个主要 SDK 组件,本指南将对此进行演示:
IMAAdDisplayContainer
:一种容器对象,用于指定 IMA 呈现广告界面元素和衡量可见率(包括 Active View 和 Open Measurement)的位置。IMAAdsLoader
: 一个用于请求广告并处理广告请求响应中的事件的对象。您只需实例化一个广告加载程序,该加载程序可在整个应用生命周期内重复使用。IMAAdsRequest
: 用于定义广告请求的对象。广告请求会指定 VAST 广告代码的网址以及其他参数(例如广告尺寸)。IMAAdsManager
: 一个包含广告请求响应、控制广告播放并监听 SDK 触发的广告事件的对象。
前提条件
在开始之前,您需要做好以下准备:
- Xcode 13 或更高版本
- CocoaPods(首选)、Swift Package Manager 或下载的 IMA SDK for iOS 副本
1. 创建新的 Xcode 项目
在 Xcode 中,使用 Objective-C 或 Swift 创建新的 iOS 项目。使用 BasicExample 作为项目名称。
2. 将 IMA SDK 添加到 Xcode 项目
使用 CocoaPods 安装 SDK(推荐)
CocoaPods 是 Xcode 项目的依赖项管理器,也是安装 IMA SDK 的推荐方法。如需详细了解如何安装或使用 CocoaPods,请参阅 CocoaPods 文档。安装 CocoaPods 后,请按照以下说明安装 IMA SDK:
在 BasicExample.xcodeproj 文件所在的目录中,创建一个名为 Podfile 的文本文件,并添加以下配置:
Objective-C
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.26.1' end
Swift
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.26.1' end
在包含 Podfile 的目录中运行
pod install --repo-update
。打开 BasicExample.xcworkspace 文件,确认其中包含两个项目:BasicExample 和 Pods(由 CocoaPods 安装的依赖项),以验证安装是否成功。
使用 Swift Package Manager 安装 SDK
互动式媒体广告 SDK 支持 3.18.4 及更高版本的 Swift Package Manager。如需导入 Swift 软件包,请完成以下步骤:
在 Xcode 中,依次前往 File > Add Package Dependencies... 以安装 IMA SDK Swift 软件包。
在提示中,搜索 IMA iOS SDK Swift 软件包的 GitHub 代码库:
swift-package-manager-google-interactive-media-ads-ios
。选择您要使用的 IMA SDK Swift 软件包版本。 对于新项目,我们建议使用 Up to Next Major Version。
完成之后,Xcode 会解析您的软件包依赖项,并在后台下载它们。如需详细了解如何添加软件包依赖项,请参阅 Apple 的文章。
手动下载并安装 SDK
如果您不想使用 Swift Package Manager 或 CocoaPods,可以下载 IMA SDK 并手动将其添加到项目中。
3. 创建视频播放器
首先,实现一个视频播放器。最初,此播放器不使用 IMA SDK,也不包含任何用于触发播放的方法。
Objective-C
导入播放器依赖项:
#import "ViewController.h" @import AVFoundation;
设置播放器变量:
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate> /// Content video player. @property(nonatomic, strong) AVPlayer *contentPlayer; /// Play button. @property(nonatomic, weak) IBOutlet UIButton *playButton; /// UIView in which we will render our AVPlayer for content. @property(nonatomic, weak) IBOutlet UIView *videoView;
在视图加载时启动视频播放器:
@implementation ViewController // The content URL to play. NSString *const kTestAppContentUrl_MP4 = @"https://storage.googleapis.com/gvabox/media/samples/stock.mp4"; // Ad tag NSString *const kTestAppAdTagUrl = @"https://pubads.g.doubleclick.net/gampad/ads?" @"iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&" @"ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&" @"correlator="; - (void)viewDidLoad { [super viewDidLoad]; self.playButton.layer.zPosition = MAXFLOAT; [self setupAdsLoader]; [self setUpContentPlayer]; } #pragma mark Content Player Setup - (void)setUpContentPlayer { // Load AVPlayer with path to our content. NSURL *contentURL = [NSURL URLWithString:kTestAppContentUrl_MP4]; self.contentPlayer = [AVPlayer playerWithURL:contentURL]; // Create a player layer for the player. AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.contentPlayer]; // Size, position, and display the AVPlayer. playerLayer.frame = self.videoView.layer.bounds; [self.videoView.layer addSublayer:playerLayer]; // Set up our content playhead and contentComplete callback. self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayer]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.contentPlayer.currentItem]; } - (IBAction)onPlayButtonTouch:(id)sender { [self requestAds]; self.playButton.hidden = YES; }
Swift
导入播放器依赖项:
import AVFoundation
设置播放器变量:
class PlayerContainerViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate { static let contentURL = URL( string: "https://storage.googleapis.com/gvabox/media/samples/stock.mp4")! private var contentPlayer = AVPlayer(url: PlayerContainerViewController.contentURL) private lazy var playerLayer: AVPlayerLayer = { AVPlayerLayer(player: contentPlayer) }()
在视图加载时启动视频播放器:
private lazy var videoView: UIView = { let videoView = UIView() videoView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(videoView) NSLayoutConstraint.activate([ videoView.bottomAnchor.constraint( equalTo: view.safeAreaLayoutGuide.bottomAnchor), videoView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), videoView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), videoView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), ]) return videoView }() // MARK: - View controller lifecycle methods override func viewDidLoad() { super.viewDidLoad() videoView.layer.addSublayer(playerLayer) adsLoader.delegate = self NotificationCenter.default.addObserver( self, selector: #selector(contentDidFinishPlaying(_:)), name: .AVPlayerItemDidPlayToEndTime, object: contentPlayer.currentItem) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) playerLayer.frame = videoView.layer.bounds } override func viewWillTransition( to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator ) { coordinator.animate { _ in // do nothing } completion: { _ in self.playerLayer.frame = self.videoView.layer.bounds } } // MARK: - Public methods func playButtonPressed() { requestAds() }
4. 导入 IMA SDK
如需导入 IMA SDK,请执行以下操作:
Objective-C
导入 IMA SDK:
@import GoogleInteractiveMediaAds;
为应用中使用的
IMAAdsLoader
、IMAAVPlayerContentPlayhead
和IMAAdsManager
类创建变量:// SDK /// Entry point for the SDK. Used to make ad requests. @property(nonatomic, strong) IMAAdsLoader *adsLoader; /// Playhead used by the SDK to track content video progress and insert mid-rolls. @property(nonatomic, strong) IMAAVPlayerContentPlayhead *contentPlayhead; /// Main point of interaction with the SDK. Created by the SDK as the result of an ad request. @property(nonatomic, strong) IMAAdsManager *adsManager;
Swift
导入 IMA SDK:
import GoogleInteractiveMediaAds
为应用中使用的
IMAAdsLoader
、IMAAVPlayerContentPlayhead
和IMAAdsManager
类创建变量:static let adTagURLString = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/" + "single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&" + "gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&correlator=" private let adsLoader = IMAAdsLoader() private var adsManager: IMAAdsManager? private lazy var contentPlayhead: IMAAVPlayerContentPlayhead = { IMAAVPlayerContentPlayhead(avPlayer: contentPlayer) }()
5. 实现内容播放头跟踪器和流结束观察器
为了播放中贴片广告,IMA SDK 需要跟踪视频内容的当前位置。为此,请创建一个实现 IMAContentPlayhead
的类。如果您使用的是 AVPlayer
(如本例所示),SDK 会提供 IMAAVPlayerContentPlayhead
类,该类可为您执行此操作。如果您未使用 AVPlayer
,则需要在自己的类中实现 IMAContentPlayhead
。
您还需要告知 SDK 内容何时播放完毕,以便 SDK 可以展示后贴片广告。为此,请使用 AVPlayerItemDidPlayToEndTimeNotification
对 IMAAdsLoader 调用 contentComplete
方法。
Objective-C
在播放器设置中创建 IMAAVPlayerContentPlayhead
实例:
// Set up our content playhead and contentComplete callback. self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayer]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.contentPlayer.currentItem];
创建 contentDidFinishPlaying()
方法,以便在内容播放完毕时调用 IMAAdsLoader.contentComplete()
:
- (void)contentDidFinishPlaying:(NSNotification *)notification { // Make sure we don't call contentComplete as a result of an ad completing. if (notification.object == self.contentPlayer.currentItem) { [self.adsLoader contentComplete]; } }
Swift
在播放器设置中创建内容结束观察器:
NotificationCenter.default.addObserver( self, selector: #selector(contentDidFinishPlaying(_:)), name: .AVPlayerItemDidPlayToEndTime, object: contentPlayer.currentItem)
创建 contentDidFinishPlaying()
方法,以便在内容播放完毕时调用 IMAAdsLoader.contentComplete()
:
@objc func contentDidFinishPlaying(_ notification: Notification) { // Make sure we don't call contentComplete as a result of an ad completing. if notification.object as? AVPlayerItem == contentPlayer.currentItem { adsLoader.contentComplete() } }
6. 初始化广告加载程序并发出广告请求
如需请求一组广告,您需要创建 IMAAdsLoader
实例。此加载器可用于处理与指定广告代码网址关联的 IMAAdsRequest
对象。
最佳做法是在应用的整个生命周期内仅维护一个 IMAAdsLoader
实例。如需发出其他广告请求,请创建一个新的 IMAAdsRequest
对象,但重复使用同一 IMAAdsLoader
。如需了解详情,请参阅 IMA SDK 常见问题解答。
Objective-C
- (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] initWithSettings:nil]; self.adsLoader.delegate = self; } - (void)requestAds { // Create an ad display container for ad rendering. IMAAdDisplayContainer *adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView viewController:self companionSlots:nil]; // Create an ad request with our ad tag, display container, and optional user context. IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kTestAppAdTagUrl adDisplayContainer:adDisplayContainer contentPlayhead:self.contentPlayhead userContext:nil]; [self.adsLoader requestAdsWithRequest:request]; }
Swift
private func requestAds() { // Create ad display container for ad rendering. let adDisplayContainer = IMAAdDisplayContainer( adContainer: videoView, viewController: self, companionSlots: nil) // Create an ad request with our ad tag, display container, and optional user context. let request = IMAAdsRequest( adTagUrl: PlayerContainerViewController.adTagURLString, adDisplayContainer: adDisplayContainer, contentPlayhead: contentPlayhead, userContext: nil) adsLoader.requestAds(with: request) }
7. 设置广告加载程序代理
在成功加载事件发生时,IMAAdsLoader
会调用其已分配的委托的 adsLoadedWithData
方法,并向其传递 IMAAdsManager
的实例。然后,您可以初始化广告管理器,该管理器会根据广告代码网址的响应加载各个广告。
此外,请务必处理加载过程中可能发生的任何错误。如果广告未加载,请确保媒体播放继续进行(不含广告),以免干扰用户体验。
Objective-C
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData { // Grab the instance of the IMAAdsManager and set ourselves as the delegate. self.adsManager = adsLoadedData.adsManager; self.adsManager.delegate = self; // Create ads rendering settings to tell the SDK to use the in-app browser. IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init]; adsRenderingSettings.linkOpenerPresentingController = self; // Initialize the ads manager. [self.adsManager initializeWithAdsRenderingSettings:adsRenderingSettings]; } - (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData { // Something went wrong loading ads. Log the error and play the content. NSLog(@"Error loading ads: %@", adErrorData.adError.message); [self.contentPlayer play]; }
Swift
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) { // Grab the instance of the IMAAdsManager and set ourselves as the delegate. adsManager = adsLoadedData.adsManager adsManager?.delegate = self // Create ads rendering settings and tell the SDK to use the in-app browser. let adsRenderingSettings = IMAAdsRenderingSettings() adsRenderingSettings.linkOpenerPresentingController = self // Initialize the ads manager. adsManager?.initialize(with: adsRenderingSettings) } func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) { if let message = adErrorData.adError.message { print("Error loading ads: \(message)") } contentPlayer.play() }
8. 设置广告管理器委托人
最后,为了管理事件和状态变化,广告管理器需要自己的委托。IMAAdManagerDelegate
具有处理广告事件和错误的方法,以及触发视频内容播放和暂停的方法。
开始播放
监听 LOADED
事件,以开始播放内容和广告。如需了解详情,请参阅 didReceiveAdEvent
。
Objective-C
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event { // When the SDK notified us that ads have been loaded, play them. if (event.type == kIMAAdEvent_LOADED) { [adsManager start]; } }
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) { // When the SDK notifies us the ads have been loaded, play them. if event.type == IMAAdEventType.LOADED { adsManager.start() } }
处理错误
同时添加了广告错误的处理程序。如果发生错误(如上一步所示),请恢复内容播放。
Objective-C
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error { // Something went wrong with the ads manager after ads were loaded. Log the error and play the // content. NSLog(@"AdsManager error: %@", error.message); [self.contentPlayer play]; }
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) { // Something went wrong with the ads manager after ads were loaded. // Log the error and play the content. if let message = error.message { print("AdsManager error: \(message)") } contentPlayer.play() }
监听播放和暂停事件
您需要实现的最后两个委托方法用于在 IMA SDK 请求时触发底层视频内容上的播放和暂停事件。在需要时触发暂停和播放可防止用户在展示广告时错过部分视频内容。
Objective-C
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager { // The SDK is going to play ads, so pause the content. [self.contentPlayer pause]; } - (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager { // The SDK is done playing ads (at least for now), so resume the content. [self.contentPlayer play]; }
Swift
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) { // The SDK is going to play ads, so pause the content. contentPlayer.pause() } func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) { // The SDK is done playing ads (at least for now), so resume the content. contentPlayer.play() }
大功告成!您现在可以使用 IMA SDK 请求和展示广告了。如需了解其他 SDK 功能,请参阅其他指南或 GitHub 上的示例。
后续步骤
为了最大限度地提高 iOS 平台上的广告收入,请请求应用透明度和跟踪权限以使用 IDFA。