使用 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 以上版本
- Swift Package Manager、CocoaPods 或 tvOS 適用的 IMA SDK 下載副本
1. 建立新的 Xcode 專案
在 Xcode 中,使用 Objective-C 或 Swift 建立新的 tvOS 專案。使用「BasicExample」BasicExample做為專案名稱。
2. 將 IMA SDK 新增至 Xcode 專案
使用 Swift Package Manager 安裝 IMA SDK
互動式媒體廣告 SDK 從 4.8.2 版開始支援 Swift Package Manager。請按照下列步驟匯入 Swift 套件。
在 Xcode 中,依序前往「File」(檔案) >「Add Packages…」(新增套件…),然後安裝 IMA SDK Swift Package。
使用畫面顯示的提示詞框,搜尋「IMA SDK Swift Package GitHub repository」:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos選取要使用的 IMA SDK Swift Package 版本。如果是新專案,建議選用「Up to Next Major Version」(升級至下一個主要版本)。
完成後,Xcode 會解析套件依附元件,並在背景下載。如要進一步瞭解如何新增套件依附元件,請參閱 Apple 的文章。
使用 CocoaPods 安裝 IMA SDK
如要安裝 IMA SDK,請使用 CocoaPods。如要進一步瞭解如何安裝或使用 CocoaPods,請參閱 CocoaPods 說明文件。安裝 CocoaPods 後,請執行下列操作:
在 BasicExample.xcodeproj 檔案所在的目錄中,建立名為 Podfile 的文字檔案,並新增下列設定:
source 'https://github.com/CocoaPods/Specs.git' platform :tvos, '15' target "BasicExample" do pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.16.0' end從包含 Podfile 的目錄執行
pod install --repo-update開啟 BasicExample.xcworkspace 檔案,確認其中包含兩個專案:BasicExample 和 Pods (CocoaPods 安裝的依附元件),藉此驗證安裝是否成功。
手動下載及安裝 IMA SDK
如果不想使用 CocoaPods,可以下載 IMA SDK,然後手動新增至專案。
3. 匯入 IMA SDK
使用匯入陳述式新增 IMA 架構。
Objective-C
#import "ViewController.h"
#import <AVKit/AVKit.h>
@import GoogleInteractiveMediaAds;
Swift
import AVFoundation
import GoogleInteractiveMediaAds
import UIKit
4. 建立影片播放器並整合 IMA SDK
以下範例會初始化 IMA SDK:
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&cmsid=496&vid=short_onecue&correlator=";
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate>
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) IMAAdDisplayContainer *adDisplayContainer;
@property(nonatomic) IMAAdsManager *adsManager;
@property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead;
@property(nonatomic) AVPlayerViewController *contentPlayerViewController;
@property(nonatomic, getter=isAdBreakActive) BOOL adBreakActive;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
[self setupAdsLoader];
[self setupContentPlayer];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self requestAds];
}
// 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 resume events from the
// remote and play content underneath the ad.
[self.contentPlayerViewController willMoveToParentViewController:nil];
[self.contentPlayerViewController.view removeFromSuperview];
[self.contentPlayerViewController removeFromParentViewController];
}
Swift
class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
static let contentURLString =
"https://devstreaming-cdn.apple.com/videos/streaming/examples/"
+ "img_bipbop_adv_example_fmp4/master.m3u8"
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="
var adsLoader: IMAAdsLoader!
var adDisplayContainer: IMAAdDisplayContainer!
var adsManager: IMAAdsManager!
var contentPlayhead: IMAAVPlayerContentPlayhead?
var playerViewController: AVPlayerViewController!
var adBreakActive = false
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.black
setUpContentPlayer()
setUpAdsLoader()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
requestAds()
}
在這個範例中,viewDidLoad() 會初始化 IMAAdsLoader,且 viewDidAppear() 會在檢視畫面顯示後請求廣告。輔助方法 showContentPlayer() 和 hideContentPlayer() 會在廣告播放期間切換內容顯示設定。
這個範例會使用 adTagURLString 常數變數,為廣告請求定義 VAST 廣告代碼,並使用下列元件管理 IMA SDK:
adsLoader:處理廣告請求和回應。建議您為應用程式的生命週期使用單一例項。adDisplayContainer:指定用於算繪廣告的檢視區塊。adsManager:管理廣告播放並監聽廣告事件。contentPlayhead:追蹤內容進度,觸發片中廣告插播時間點。adBreakActive:指出廣告插播是否正在播放,以防止略過廣告。
5. 實作內容播放頭追蹤器和串流結束觀察器
如要播放影片中廣告,IMA SDK 必須追蹤影片內容的目前位置。如要執行這項操作,請建立實作 IMAContentPlayhead 的類別。如本例所示,如果您使用 AVPlayer,SDK 會提供 IMAAVPlayerContentPlayhead 類別,為您執行這項操作。如果您不使用 AVPlayer,就必須在自己的類別中導入 IMAContentPlayhead。
Objective-C
- (void)setupContentPlayer {
// Create a content video player. Create a playhead to track content progress so the SDK knows
// when to play ads in a VMAP playlist.
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];
}
Swift
func setUpContentPlayer() {
// Load AVPlayer with path to our content.
let contentURL = URL(string: ViewController.contentURLString)!
let player = AVPlayer(url: contentURL)
playerViewController = AVPlayerViewController()
playerViewController.player = player
// Set up our 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()
}
您也必須讓 SDK 知道內容何時播放完畢,以便顯示片尾廣告。方法是使用 AVPlayerItemDidPlayToEndTimeNotification,在 IMAAdsLoader 上呼叫 contentComplete。
Objective-C
- (void)contentDidFinishPlaying:(NSNotification *)notification {
// Notify the SDK that the postrolls should be played.
[self.adsLoader contentComplete];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Swift
@objc func contentDidFinishPlaying(_ notification: Notification) {
adsLoader.contentComplete()
}
6. 初始化廣告載入器並發出廣告請求
如要請求一組廣告,請建立 IMAAdsLoader 例項。這個載入器可用於處理與指定廣告代碼網址相關聯的 IMAAdsRequest 物件。
最佳做法是在整個應用程式生命週期中,只維護一個 IMAAdsLoader 例項。如要提出其他廣告請求,請建立新的 IMAAdsRequest 物件,但重複使用相同的 IMAAdsLoader。詳情請參閱 IMA SDK 常見問題。
Objective-C
- (void)setupAdsLoader {
self.adsLoader = [[IMAAdsLoader alloc] init];
self.adsLoader.delegate = self;
}
- (void)requestAds {
// Pass the main view as the container for ad display.
self.adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.view
viewController:self];
IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kAdTagURLString
adDisplayContainer:self.adDisplayContainer
contentPlayhead:self.contentPlayhead
userContext:nil];
[self.adsLoader requestAdsWithRequest:request];
}
Swift
func setUpAdsLoader() {
adsLoader = IMAAdsLoader(settings: nil)
adsLoader.delegate = self
}
func requestAds() {
// Create ad display container for ad rendering.
adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view, viewController: self)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(
adTagUrl: ViewController.adTagURLString,
adDisplayContainer: adDisplayContainer,
contentPlayhead: contentPlayhead,
userContext: nil)
adsLoader.requestAds(with: request)
}
7. 設定廣告載入器委派
載入事件成功後,IMAAdsLoader 會呼叫指派的委派項目的 adsLoadedWithData 方法,並傳遞 IMAAdsManager 的執行個體。接著,您可以初始化廣告管理工具,載入廣告代碼網址回應中定義的個別廣告。
此外,請務必處理載入程序中可能發生的任何錯誤。如果廣告未載入,請確保媒體播放作業會繼續進行 (不含廣告),以免干擾使用者體驗。
Objective-C
#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.delegate = self;
[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];
}
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
adsManager.initialize(with: nil)
}
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
print("Error loading ads: \(adErrorData.adError.message ?? "No error message available.")")
showContentPlayer()
playerViewController.player?.play()
}
8. 設定廣告管理員委派
最後,為了管理事件和狀態變更,廣告管理工具需要自己的委派項目。IMAAdManagerDelegate 具有處理廣告事件和錯誤的方法,以及觸發影片內容播放和暫停的方法。
開始播放
didReceiveAdEvent 方法可用於處理許多事件。
在這個基本範例中,請監聽 LOADED 事件,告知廣告管理工具開始播放內容和廣告。使用者輕觸圖示後關閉圖示備用對話方塊時,IMA SDK 會觸發 ICON_FALLBACK_IMAGE_CLOSED 事件。廣告結束後,系統會繼續播放影片內容。
Objective-C
#pragma mark - IMAAdsManagerDelegate
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
switch (event.type) {
case kIMAAdEvent_LOADED: {
// Play each ad once it has loaded.
[adsManager start];
break;
}
case kIMAAdEvent_ICON_FALLBACK_IMAGE_CLOSED: {
// Resume ad after user has closed dialog.
[adsManager resume];
break;
}
default:
break;
}
}
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
switch event.type {
case IMAAdEventType.LOADED:
// Play each ad once it has been loaded.
adsManager.start()
case IMAAdEventType.ICON_FALLBACK_IMAGE_CLOSED:
// Resume playback after the user has closed the dialog.
adsManager.resume()
default:
break
}
}
處理錯誤
同時也新增廣告錯誤的處理常式。如果發生錯誤 (如上一個步驟所述),請繼續播放內容。
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];
}
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
// Fall back to playing content
print("AdsManager error: \(error.message ?? "No error message available.")")
showContentPlayer()
playerViewController.player?.play()
}
觸發播放和暫停事件
您需要導入的最後兩個委派方法,是用來在 IMA SDK 要求時,觸發基礎影片內容的播放和暫停事件。在使用者要求時觸發暫停和播放功能,可避免廣告顯示時,使用者錯過部分影片內容。
Objective-C
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
// Pause the content for the SDK to play ads.
[self.contentPlayerViewController.player pause];
[self hideContentPlayer];
// Trigger an update to send focus to the ad display container.
self.adBreakActive = YES;
[self setNeedsFocusUpdate];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
// Resume the content since the SDK is done playing ads (at least for now).
[self showContentPlayer];
[self.contentPlayerViewController.player play];
// Trigger an update to send focus to the content player.
self.adBreakActive = NO;
[self setNeedsFocusUpdate];
}
Swift
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
// Pause the content for the SDK to play ads.
playerViewController.player?.pause()
hideContentPlayer()
// Trigger an update to send focus to the ad display container.
adBreakActive = true
setNeedsFocusUpdate()
}
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
// Resume the content since the SDK is done playing ads (at least for now).
showContentPlayer()
playerViewController.player?.play()
// Trigger an update to send focus to the content player.
adBreakActive = false
setNeedsFocusUpdate()
}
大功告成!您現在可以使用 IMA SDK 請求及顯示廣告。如要瞭解其他 SDK 功能,請參閱其他指南或 GitHub 上的範例。
後續步驟
如要在 tvOS 平台上盡量提高廣告收益,請要求應用程式追蹤透明度和追蹤權限,以便使用廣告識別碼。