开始使用

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: 一个对象,包含对广告请求的响应、控制广告播放以及监听广告 所有事件。

前提条件

在开始之前,您需要做好以下准备:

1. 创建新的 Xcode 项目

在 Xcode 中,使用 Objective-C 或 Swift 创建一个新的 tvOS 项目。使用 BasicExample 作为项目名称。

2. 将 IMA SDK 添加到 Xcode 项目

使用 CocoaPods 安装 SDK(首选)

CocoaPods 是适用于 Xcode 项目的依赖项管理器,建议使用 CocoaPods 安装 IMA SDK 的方法。如需详细了解如何安装或使用 CocoaPods,请参阅 CocoaPods 文档。在您 已安装 CocoaPods,请按照以下说明安装 IMA SDK:

  1. 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
    
  2. 从包含 Podfile 的目录中,运行 pod install --repo-update

  3. 打开 BasicExample.xcworkspace 文件并确认它包含两个项目: BasicExamplePods(由 CocoaPods 安装的依赖项)。

使用 Swift Package Manager 安装 SDK

互动式媒体广告 SDK 支持 Swift Package Manager 版本。按照 导入 Swift 软件包的步骤。

  1. 在 Xcode 中,前往 文件 >添加软件包...

  2. 在显示的提示中,搜索 IMA SDK Swift Package GitHub 代码库:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
    
  3. 选择您要使用的 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