開始使用 IMA DAI SDK

IMA SDK 可讓您輕鬆將多媒體廣告整合至您的網站和應用程式。IMA SDK 可以 向任何 與 VAST 相容的廣告伺服器,並管理您應用程式中的廣告播放方式。透過 IMA DAI SDK,應用程式會針對廣告和內容影片 (隨選影片或直播內容) 提出串流要求。接著,SDK 會傳回合併的影片串流,因此您不必在應用程式中管理廣告和內容影片之間的切換。

選取感興趣的動態廣告解決方案

全方位服務 DAI

本指南說明如何將 IMA DAI SDK 整合到簡易影片播放器中 應用程式。如果您要檢視或繼續完成樣本 請下載 GitHub 的 BasicExample

IMA DAI 總覽

實作 IMA DAI 時,需要使用三個主要 SDK 元件,如本指南所示:

  • IMAAdDisplayContainer: 這個容器物件位於影片播放元素上方,並存放廣告 UI 元素。
  • IMAAdsLoader:要求串流的物件,並處理由串流要求回應物件觸發的事件。您只應將一個廣告載入器執行個體化,且該載入器在整個生命週期內可以重複使用 應用程式。
  • IMAStreamRequest – 無論 IMAVODStreamRequest IMALiveStreamRequest: 定義串流要求的物件。串流要求可以是隨選影片或直播 串流。要求會指定內容 ID,以及 API 金鑰或驗證權杖和其他參數。
  • IMAStreamManager:處理動態廣告插播串流和與 DAI 後端的互動情形的物件。 串流管理員也會處理追蹤連線偵測 (ping),並將串流和廣告事件轉送至 內容。

必要條件

開始之前,請先備妥以下項目:

建立新的 Xcode 專案

在 Xcode 中,使用 Objective-C 建立新的 tvOS 專案。使用 BasicExample 做為 輸入專案名稱

將 IMA DAI SDK 加入 Xcode 專案

請使用下列三種方法之一安裝 IMA DAI SDK。

使用 CocoaPods 安裝 SDK (建議)

CocoaPods 是 Xcode 專案的依附元件管理工具,建議使用 方法,瞭解如何安裝 IMA DAI SDK。進一步瞭解如何安裝或使用 CocoaPods,請參閱 CocoaPods 說明文件。當您 已安裝 CocoaPods,請按照下列操作說明安裝 IMA DAI 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 檔案,並確認其中包含兩個 專案:BasicExamplePod (由 CocoaPods)。

使用 Swift Package Manager 安裝 SDK

互動式媒體廣告 SDK 支援 Swift 套件 Manager (自 4.8.2 版起)。請按照下列步驟匯入 Swift 套件。

  1. 在 Xcode 中,前往以下網址安裝 GoogleInteractiveMediaAds Swift 套件: 檔案 >新增套件

  2. 在出現的提示中,搜尋 GoogleInteractiveMediaAds Swift Package GitHub 存放區:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
    
  3. 選取要使用的 GoogleInteractiveMediaAds Swift 套件版本。如為新的 專案時,建議使用下一個主要版本

完成後,Xcode 會解析套件依附元件,並在背景下載這些套件。如要進一步瞭解如何新增套件依附元件,請參閱 Apple 的文章

手動下載並安裝 SDK

如果不想使用 Swift Package Manager 或 CocoaPods,您可以下載 然後手動將該檔案加到專案中。

建立簡單的影片播放器

首先,導入基本影片播放器。這個播放器一開始不會使用 IMA DAI SDK,也不包含任何觸發播放的做法。

ViewController.m

#import "ViewController.h"

#import <AVKit/AVKit.h>

@interface ViewController ()
@property(nonatomic) AVPlayerViewController *playerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor blackColor];

  // Create a stream video player.
  AVPlayer *player = [[AVPlayer alloc] init];
  self.playerViewController = [[AVPlayerViewController alloc] init];
  self.playerViewController.player = player;

  // Attach the video player to the view hierarchy.
  [self addChildViewController:self.playerViewController];
  self.playerViewController.view.frame = self.view.bounds;
  [self.view addSubview:self.playerViewController.view];
  [self.playerViewController didMoveToParentViewController:self];
}

@end

匯入 SDK 並新增 IMA 互動用的 Stub

將 IMA DAI SDK 加入專案後,請匯入 SDK 並將虛設常式 與 IMA 互動的主要互動點。

ViewController.m

#import "ViewController.h"

#import <AVKit/AVKit.h>
#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>

@interface ViewController ()
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) UIView *adContainerView;
@property(nonatomic) IMAStreamManager *streamManager;
@property(nonatomic) AVPlayerViewController *playerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor blackColor];

  [self setupAdsLoader];

  // Create a stream video player.
  AVPlayer *player = [[AVPlayer alloc] init];
  self.playerViewController = [[AVPlayerViewController alloc] init];
  self.playerViewController.player = player;

  // Attach the video player to the view hierarchy.
  [self addChildViewController:self.playerViewController];
  self.playerViewController.view.frame = self.view.bounds;
  [self.view addSubview:self.playerViewController.view];
  [self.playerViewController didMoveToParentViewController:self];

  [self attachAdContainer];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  [self requestStream];
}

- (void)setupAdsLoader {}

- (void)attachAdContainer {}

- (void)requestStream {}

@end

導入 IMAAdsLoader

接著,請將 IMAAdsLoader 例項化,並將廣告容器檢視畫面附加至檢視區塊階層。

ViewController.m

- (void)setupAdsLoader {
  self.adsLoader = [[IMAAdsLoader alloc] init];
  self.adsLoader.delegate = self;
}

- (void)attachAdContainer {
  self.adContainerView = [[UIView alloc] init];
  [self.view addSubview:self.adContainerView];
  self.adContainerView.frame = self.view.bounds;
}

提出串流要求

建立幾個常數來保留串流資訊,然後實作 透過串流要求函式提出要求

ViewController.m

#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>

static NSString *const kAssetKey = @"sN_IYUG8STe1ZzhIIE_ksA";
static NSString *const kContentSourceID = @"2548831";
static NSString *const kVideoID = @"tears-of-steel";

@interface ViewController ()
...

- (void)requestStream {
  IMAAVPlayerVideoDisplay *videoDisplay =
      [[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.playerViewController.player];
  IMAAdDisplayContainer *adDisplayContainer =
      [[IMAAdDisplayContainer alloc] initWithAdContainer:self.adContainerView];
  IMALiveStreamRequest *request = [[IMALiveStreamRequest alloc] initWithAssetKey:kAssetKey
                                                              adDisplayContainer:adDisplayContainer
                                                                    videoDisplay:videoDisplay];
  // VOD request. Comment out the IMALiveStreamRequest above and uncomment this IMAVODStreamRequest
  // to switch from a livestream to a VOD stream.
  // IMAVODStreamRequest *request =
  //     [[IMAVODStreamRequest alloc] initWithContentSourceId:kContentSourceID
  //                                                  videoId:kVideoID
  //                                       adDisplayContainer:adDisplayContainer
  //                                             videoDisplay:videoDisplay];
  [self.adsLoader requestStreamWithRequest:request];
}

處理串流事件

用於處理的 IMAAdsLoaderIMAStreamManager 觸發事件 初始化、錯誤及串流狀態變更這些事件會透過 IMAAdsLoaderDelegateIMAStreamManagerDelegate 通訊協定。監聽廣告載入事件,並初始化串流。如果廣告無法載入,請改為播放備用串流。

ViewController.m

static NSString *const kAssetKey = @"sN_IYUG8STe1ZzhIIE_ksA";
static NSString *const kContentSourceID = @"2548831";
static NSString *const kVideoID = @"tears-of-steel";
static NSString *const kBackupStreamURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8";

@interface ViewController () <IMAAdsLoaderDelegate, IMAStreamManagerDelegate>

...
  [self.adsLoader requestStreamWithRequest:request];
}

- (void)playBackupStream {
  NSURL *backupStreamURL = [NSURL URLWithString:kBackupStreamURLString];
  AVPlayerItem *backupStreamItem = [AVPlayerItem playerItemWithURL:backupStreamURL];
  [self.playerViewController.player replaceCurrentItemWithPlayerItem:backupStreamItem];
  [self.playerViewController.player play];
}

#pragma mark - IMAAdsLoaderDelegate

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  // Initialize and listen to stream manager's events.
  self.streamManager = adsLoadedData.streamManager;
  self.streamManager.delegate = self;
  [self.streamManager initializeWithAdsRenderingSettings:nil];
  NSLog(@"Stream created with: %@.", self.streamManager.streamId);
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Fall back to playing the backup stream.
  NSLog(@"Error loading ads: %@", adErrorData.adError.message);
  [self playBackupStream];
}

#pragma mark - IMAStreamManagerDelegate

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {}

- (void)streamManager:(IMAStreamManager *)streamManager
  adDidProgressToTime:(NSTimeInterval)time
           adDuration:(NSTimeInterval)adDuration
           adPosition:(NSInteger)adPosition
             totalAds:(NSInteger)totalAds
      adBreakDuration:(NSTimeInterval)adBreakDuration {}

@end

處理記錄和錯誤事件

有幾個事件可由串流管理員委派處理,但對於基本實作而言,最重要的用途是執行事件記錄,以便在廣告播放期間防止尋找動作,並處理錯誤。

ViewController.m

#pragma mark - IMAStreamManagerDelegate

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
  NSLog(@"StreamManager event (%@).", event.typeString);
  switch (event.type) {
    case kIMAAdEvent_STARTED: {
      // Log extended data.
      NSString *extendedAdPodInfo = [[NSString alloc]
          initWithFormat:@"Showing ad %zd/%zd, bumper: %@, title: %@, description: %@, contentType:"
                         @"%@, pod index: %zd, time offset: %lf, max duration: %lf.",
                         event.ad.adPodInfo.adPosition, event.ad.adPodInfo.totalAds,
                         event.ad.adPodInfo.isBumper ? @"YES" : @"NO", event.ad.adTitle,
                         event.ad.adDescription, event.ad.contentType, event.ad.adPodInfo.podIndex,
                         event.ad.adPodInfo.timeOffset, event.ad.adPodInfo.maxDuration];

      NSLog(@"%@", extendedAdPodInfo);
      break;
    }
    case kIMAAdEvent_AD_BREAK_STARTED: {
      // Prevent user seek through when an ad starts and show the ad controls.
      self.adContainerView.hidden = NO;
      break;
    }
    case kIMAAdEvent_AD_BREAK_ENDED: {
      // Allow user seek through after an ad ends and hide the ad controls.
      self.adContainerView.hidden = YES;
      break;
    }
    default:
      break;
  }
}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
  // Fall back to playing the backup stream.
  NSLog(@"StreamManager error: %@", error.message);
  [self playBackupStream];
}

@end

大功告成!您現在可以使用 IMA DAI SDK 請求及顯示廣告。如要進一步瞭解更進階的 SDK 功能,請參閱其他指南或 GitHub 上的範例