IMA SDK 可让您轻松地将多媒体广告集成到您的网站和应用中。IMA SDK 可以 向任意 <ph type="x-smartling-placeholder"></ph> 符合 VAST 标准的广告服务器,并管理应用中的广告播放。借助 IMA 客户端 SDK 您控制内容视频播放,而 SDK 处理广告播放。广告播放 独立的视频播放器,位于应用的内容视频播放器之上。
本指南将演示如何将 IMA SDK 集成到简单的视频播放器中 应用。如果您想查看或了解已完成的示例 集成,请下载 BasicExample GitHub。
IMA 客户端概览
实施 IMA 客户端涉及四个主要 SDK 组件,它们是 演示:
IMAAdDisplayContainer
: 用于呈现广告的容器对象。IMAAdsLoader
: 用于请求广告并处理广告请求响应中事件的对象。您只能 实例化一个广告加载器,该加载器可在应用的整个生命周期内重复使用。IMAAdsRequest
: 用于定义广告请求的对象。广告请求会指定 VAST 广告代码的网址,以及 其他参数(例如广告尺寸)IMAAdsManager
: 一个对象,包含对广告请求的响应、控制广告播放以及监听广告 所有事件。
前提条件
在开始之前,您需要做好以下准备:
- Xcode 13 或更高版本
- CocoaPods(首选)、Swift Package Manager 或 下载了 适用于 tvOS 的 IMA SDK
1. 创建新的 Xcode 项目
在 Xcode 中,使用 Objective-C 或 Swift 创建一个新的 tvOS 项目。使用 BasicExample 作为项目名称。
2. 将 IMA SDK 添加到 Xcode 项目
使用 CocoaPods 安装 SDK(首选)
CocoaPods 是适用于 Xcode 项目的依赖项管理器,建议使用 CocoaPods 安装 IMA SDK 的方法。如需详细了解如何安装或使用 CocoaPods,请参阅 CocoaPods 文档。在您 已安装 CocoaPods,请按照以下说明安装 IMA SDK:
在 BasicExample.xcodeproj 文件所在的同一目录中,创建一个文本 名为 Podfile 的文件,并添加以下配置:
source 'https://github.com/CocoaPods/Specs.git' platform :tvos, '14' target "BasicExample" do pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.13.0' end
从包含 Podfile 的目录中,运行
pod install --repo-update
打开 BasicExample.xcworkspace 文件并确认它包含两个项目: BasicExample 和 Pods(由 CocoaPods 安装的依赖项)。
使用 Swift Package Manager 安装 SDK
互动式媒体广告 SDK 支持 Swift Package Manager 版本。按照 导入 Swift 软件包的步骤。
在 Xcode 中,前往 文件 >添加软件包...。
在显示的提示中,搜索 IMA SDK Swift Package GitHub 代码库:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
选择您要使用的 IMA SDK Swift 软件包版本。 对于新项目,我们建议使用 Up to Next Major Version。
完成上述操作后,Xcode 会解析您的软件包依赖项 并在后台下载它们如需详细了解如何添加软件包 请参阅 Apple 的文章。
手动下载并安装 SDK
如果您不想使用 CocoaPods,可以下载 IMA SDK 并手动 将其添加到您的项目。
3. 创建简单的视频播放器
首先,实施一个基本的视频播放器。最初,该播放器不会使用 IMA SDK 中,但尚未包含任何触发播放的方法。
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"; @interface ViewController () @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; } - (void)setupContentPlayer { // Create a content video player. NSURL *contentURL = [NSURL URLWithString:kContentURLString]; AVPlayer *player = [AVPlayer playerWithURL:contentURL]; self.contentPlayerViewController = [[AVPlayerViewController alloc] init]; self.contentPlayerViewController.player = player; self.contentPlayerViewController.view.frame = self.view.bounds; // Attach content video player to view hierarchy. [self showContentPlayer]; } // Add the content video player as a child view controller. - (void)showContentPlayer { [self addChildViewController:self.contentPlayerViewController]; self.contentPlayerViewController.view.frame = self.view.bounds; [self.view insertSubview:self.contentPlayerViewController.view atIndex:0]; [self.contentPlayerViewController didMoveToParentViewController:self]; } // Remove and detach the content video player. - (void)hideContentPlayer { // The whole controller needs to be detached so that it doesn't capture events from the remote. [self.contentPlayerViewController willMoveToParentViewController:nil]; [self.contentPlayerViewController.view removeFromSuperview]; [self.contentPlayerViewController removeFromParentViewController]; } @end
Swift
import AVFoundation import UIKit class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" var playerViewController: AVPlayerViewController! override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() } func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player showContentPlayer() } func showContentPlayer() { self.addChild(playerViewController) playerViewController.view.frame = self.view.bounds self.view.insertSubview(playerViewController.view, at: 0) playerViewController.didMove(toParent:self) } func hideContentPlayer() { // The whole controller needs to be detached so that it doesn't capture events from the remote. playerViewController.willMove(toParent:nil) playerViewController.view.removeFromSuperview() playerViewController.removeFromParent() } }
4. 导入 IMA SDK
接下来,使用 import 语句在现有的 导入。
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> #import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4";
Swift
import AVFoundation import GoogleInteractiveMediaAds import UIKit class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
5. 实现内容进度条指针跟踪器和流结束观察器
要播放中贴片广告,IMA SDK 需要跟踪
视频内容为此,请创建一个实现
IMAContentPlayhead
。如果您使用的是 AVPlayer
(如此例所示),
SDK 提供了 IMAAVPlayerContentPlayhead
类来为您执行此操作。
如果您没有使用 AVPlayer
,则需要在IMAContentPlayhead
是您自己的一个类。
您还需要在内容播放完毕后通知 SDK,以便 SDK
展示后贴片广告。可通过在contentComplete
IMAAdsLoader
,使用 AVPlayerItemDidPlayToEndTimeNotification
。
ViewController.m
Objective-C
... @interface ViewController () @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end ... - (void)setupContentPlayer { // Create a content video player. NSURL *contentURL = [NSURL URLWithString:kContentURLString]; AVPlayer *player = [AVPlayer playerWithURL:contentURL]; self.contentPlayerViewController = [[AVPlayerViewController alloc] init]; self.contentPlayerViewController.player = player; self.contentPlayerViewController.view.frame = self.view.bounds; self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayerViewController.player]; // Track end of content. AVPlayerItem *contentPlayerItem = self.contentPlayerViewController.player.currentItem; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(contentDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:contentPlayerItem]; // Attach content video player to view hierarchy. [self showContentPlayer]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification {} - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } @end
Swift
... class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! deinit { NotificationCenter.default.removeObserver(self) } ... func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player // Set up your content playhead and contentComplete callback. contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player) NotificationCenter.default.addObserver( self, selector: #selector(ViewController.contentDidFinishPlaying(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem); showContentPlayer() } ... @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
6. 初始化广告加载器并发出广告请求
为了请求一组广告,您需要创建一个 IMAAdsLoader
实例。
此加载器可用于处理IMAAdsRequest
与
指定的广告代码网址。
最佳做法是,在整个过程中只维护一个 IMAAdsLoader
实例,
应用的整个生命周期要发出更多广告请求,请创建新的
IMAAdsRequest
对象,但重复使用相同的 IMAAdsLoader
。有关
相关信息,请参阅 IMA SDK 常见问题解答。
ViewController.m
Objective-C
... NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"; NSString *const kAdTagURLString = @"https://pubads.g.doubleclick.net/gampad/ads?" @"iu=/21775744923/external/vmap_ad_samples&sz=640x480&" @"cust_params=sample_ar%3Dpremidpostlongpod&" @"ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&" @"env=vp&impl=s&cmsid=496&vid=short_onecue&correlator="; @interface ViewController () @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; [self setupAdsLoader]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self requestAds]; } - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; } - (void)requestAds { // Pass the main view as the container for ad display. IMAAdDisplayContainer *adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.view]; IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kAdTagURLString adDisplayContainer:adDisplayContainer contentPlayhead:self.contentPlayhead userContext:nil]; [self.adsLoader requestAdsWithRequest:request]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification { // Notify the SDK that the postrolls should be played. [self.adsLoader contentComplete]; } ... @end
Swift
... class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" 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&impl=s&correlator=" var adsLoader: IMAAdsLoader! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() setUpAdsLoader() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated); requestAds() } ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) } func requestAds() { // Create ad display container for ad rendering. let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view) // Create an ad request with your ad tag, display container, and optional user context. let request = IMAAdsRequest( adTagUrl: ViewController.AdTagURLString, adDisplayContainer: adDisplayContainer, contentPlayhead: contentPlayhead, userContext: nil) adsLoader.requestAds(with: request) } @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
7. 设置广告加载程序委托
在成功加载事件发生后,IMAAdsLoader
会调用 adsLoadedWithData
方法,并向其传递 IMAAdsManager
的实例。您
然后可以初始化广告管理器,该广告管理器将按照定义加载各个广告,
。
此外,请务必处理在加载过程中可能发生的任何错误 过程。如果广告无法加载,请确保媒体继续播放,而不 以免干扰用户体验。
ViewController.m
Objective-C
... @interface ViewController () <IMAAdsLoaderDelegate> @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAdsManager *adsManager; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController ... - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; self.adsLoader.delegate = self; } ... #pragma mark - IMAAdsLoaderDelegate - (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData { // Initialize and listen to the ads manager loaded for this request. self.adsManager = adsLoadedData.adsManager; [self.adsManager initializeWithAdsRenderingSettings:nil]; } - (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData { // Fall back to playing content. NSLog(@"Error loading ads: %@", adErrorData.adError.message); [self.contentPlayerViewController.player play]; } @end
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate { ... var adsLoader: IMAAdsLoader! var adsManager: IMAAdsManager! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) adsLoader.delegate = self } ... // MARK: - IMAAdsLoaderDelegate func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { adsManager = adsLoadedData.adsManager adsManager.initialize(with: nil) } func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) { print("Error loading ads: " + adErrorData.adError.message) showContentPlayer() playerViewController.player?.play() } }
8. 设置广告管理器委托
最后,为了管理事件和状态变化,广告管理器需要
自己的数据。IMAAdManagerDelegate
提供了用于处理广告事件和错误的方法,
以及触发视频内容的播放和暂停的方法。
正在开始播放
didReceiveAdEvent
方法可用于处理许多事件,
但对于这个基本示例,只需监听 LOADED
事件,让广告
来播放内容和广告。
ViewController.m
Objective-C
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate> ... - (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData { // Initialize and listen to the ads manager loaded for this request. self.adsManager = adsLoadedData.adsManager; self.adsManager.delegate = self; [self.adsManager initializeWithAdsRenderingSettings:nil]; } ... #pragma mark - IMAAdsManagerDelegate - (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event { // Play each ad once it has loaded. if (event.type == kIMAAdEvent_LOADED) { [adsManager start]; } } ...
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate { ... func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { // Grab the instance of the IMAAdsManager and set yourself as the delegate. adsManager = adsLoadedData.adsManager adsManager.delegate = self adsManager.initialize(with: nil) } ... // MARK: - IMAAdsManagerDelegate func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) { // Play each ad once it has been loaded if event.type == IMAAdEventType.LOADED { adsManager.start() } } ...
处理错误
同时为广告错误添加处理程序。如果出现错误,例如在上一个 继续播放内容。
ViewController.m
Objective-C
... - (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error { // Fall back to playing content. NSLog(@"AdsManager error: %@", error.message); [self showContentPlayer]; [self.contentPlayerViewController.player play]; } @end
Swift
... func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) { // Fall back to playing content print("AdsManager error: " + error.message) showContentPlayer() playerViewController.player?.play() }
触发播放和暂停事件
您需要实现的后两个委托方法用于触发播放, 暂停播放基础视频内容上的事件。 在收到请求时触发暂停和播放操作可防止用户遗漏部分内容 视频内容的播放速度。
ViewController.m
Objective-C
... - (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager { // Pause the content for the SDK to play ads. [self.contentPlayerViewController.player pause]; [self hideContentPlayer]; } - (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager { // Resume the content since the SDK is done playing ads (at least for now). [self showContentPlayer]; [self.contentPlayerViewController.player play]; } @end
Swift
... func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) { // Pause the content for the SDK to play ads. playerViewController.player?.pause() hideContentPlayer() } func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) { // Resume the content since the SDK is done playing ads (at least for now). showContentPlayer() playerViewController.player?.play() } }
大功告成!现在,您将通过 IMA SDK 请求并展示广告。学习内容 其他 SDK 功能,请参阅其他指南或 GitHub 上的示例。
后续步骤
若要最大限度地提高 tvOS 平台上的广告收入,请请求应用透明度和跟踪权限以使用 IDFA。