使用 IMA SDK,即可輕鬆將多媒體廣告整合至網站和應用程式。IMA SDK 可向任何 符合 VAST 規定的廣告伺服器請求廣告,並在應用程式中管理廣告播放。使用 IMA 用戶端 SDK 時,您可以控管內容影片的播放,SDK 則負責處理廣告播放。廣告會在應用程式內容影片播放器上方的獨立影片播放器中播放。
本指南說明如何將 IMA SDK 整合至影片播放器應用程式。如要查看或跟著操作已完成的整合範例,請從 GitHub 下載 BasicExample。
IMA 用戶端總覽
導入 IMA 用戶端時,會用到四個主要的 SDK 元件,本指南將說明這些元件:
- IMAAdDisplayContainer: 容器物件,用於指定 IMA 算繪廣告 UI 元素的位置,以及評估可視度 (包括 Active View 和 Open Measurement)。
- IMAAdsLoader: 這個物件會請求廣告,並處理廣告請求回應中的事件。您應該只例項化一個廣告載入器,這個載入器可在應用程式的整個生命週期中重複使用。
- IMAAdsRequest: 定義廣告請求的物件。廣告請求會指定 VAST 廣告代碼的網址,以及廣告尺寸等其他參數。
- IMAAdsManager: 這個物件包含廣告請求的回應、控管廣告播放,並監聽 SDK 觸發的廣告事件。
必要條件
開始之前,請先備妥下列項目:
- Xcode 13 以上版本
- CocoaPods (建議使用)、Swift Package Manager,或iOS 專用 IMA SDK 的下載副本
1. 建立新的 Xcode 專案
在 Xcode 中,使用 Objective-C 或 Swift 建立新的 iOS 專案。使用「BasicExample」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.27.4' end- Swift- source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.27.4' 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 Package」。 
- 在提示中,搜尋 IMA iOS SDK Swift Package GitHub 存放區: - swift-package-manager-google-interactive-media-ads-ios。
- 選取要使用的 IMA SDK Swift Package 版本。 新專案建議使用「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 內容播放完畢的時間,以便顯示片尾廣告。方法是在 IMAAdsLoader 上呼叫 contentComplete 方法,並使用 AVPlayerItemDidPlayToEndTimeNotification。
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 平台上盡量提高廣告收益,請要求應用程式追蹤透明度權限,以便使用廣告識別碼。
 
    