開始使用 IMA DAI SDK

IMA SDK 可讓您輕鬆將多媒體廣告整合至您的網站和應用程式。IMA SDK 可以從任何 符合 VAST 規定的廣告伺服器請求廣告,並管理在應用程式中播放的廣告。使用 IMA DAI SDK 時,應用程式會向廣告和內容影片 (VOD 或直播內容) 發出串流請求。接著,SDK 會傳回合併的影片串流,因此您不必在應用程式中切換廣告和內容影片。

選取所需的 DAI 解決方案

完整服務 DAI

本指南說明如何將 IMA DAI SDK 整合到簡單的影片播放器應用程式中。如果您要查看或按照完成整合的範例整合,請從 GitHub 下載 BasicExample

IMA DAI 總覽

導入 IMA DAI 包含四個主要 SDK 元件,如本指南所示:

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

先備知識

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

  • Xcode 13 以上版本
  • CocoaPods (建議使用)、Swift 套件管理工具,或下載的 IMA DAI SDK 下載副本

建立新的 Xcode 專案

在 Xcode 中,使用 Objective-C 建立新的 iOS 專案。使用 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 :ios, '14'
    target "BasicExample" do
      pod 'GoogleAds-IMA-iOS-SDK', '~> 3.23.0'
    end
    
  2. 從包含 Podfile 的目錄,執行:

    pod install --repo-update`
    
  3. 開啟 BasicExample.xcworkspace 檔案,並確認該檔案包含兩個專案:BasicExamplePods (由 CocoaPods 安裝的依附元件),驗證安裝成功。

使用 Swift Package Manager 安裝 SDK

自 3.18.4 版起,互動式媒體廣告 SDK 支援 Swift 套件管理工具。請按照下列步驟匯入 Swift 套件。

  1. 在 Xcode 中依序前往「File」(檔案) >「Add Packages」(新增套件),安裝 IMA DAI SDK Swift 套件。

  2. 在隨即顯示的提示中,搜尋 IMA DAI SDK Swift 套件 GitHub 存放區:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. 選取您要使用的 IMA DAI SDK Swift 套件版本。如要建立新專案,建議您使用直到下一個主要版本

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

手動下載並安裝 SDK

如果您不想使用 Swift Package Manager 或 CocoaPods,您可以下載 IMA DAI SDK 並手動加到專案中。

建立簡易影片播放器

首先,導入基本影片播放器。這個播放器一開始並未使用 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 互動的虛設常式

在專案中加入 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 範例