AppleTV SDK 統合ガイド
この統合ガイドでは、Xandr の AppleTV SDK を AppleTV アプリケーションに統合する方法について説明します。これにより、Xandr のクライアント側の広告挿入を使用して、アプリ内でクライアント側のビデオ広告を入札、追跡、測定できます。 手順と例では、次のことを前提としています。
- Apple tvOS 12.0 以降に対して開発しています。
- 開発環境に AVPlayer と AVPlayerView コントローラーの既存のインスタンスがある
- Swift Core ライブラリ: Foundation で Swift コード ライブラリを使用しています。 最小バージョンは SWIFT 4.2 です。
- Xcode v10.0 以降を使用しています。
このアプリケーションでは、 と /vmap
エンドポイントが/ptv
サポートされています。
次のセクションでは、統合を完了し、カスタマイズ オプションのリファレンスを提供し、ベスト プラクティスを提案し、Objective-C を使用する開発者向けに推奨事項を作成するために必要な手順について説明します。
統合の設定
1. CocoaPods を設定してインポートする
CocoaPods は、Xandr の SDK を配布し、アプリに統合するために使用されます。 次のリンクを使用して CocoaPods をインストールし、プロジェクトに追加します。
ポッド スペック ファイルでは、次のコードを使用できます。
サンプル podfile:
target 'MyApp' do
pod 'AppNexusTVOSSDK', '~> 2.0.0'
end
2. Xandr の AppleTV SDK
モジュールを UIViewController にインポートする
次のコマンドを使用します。
import ANTVSDK
import AVKit //standard Audio Video Kit library
3. UIViewController にプロトコルを追加 AdControllerProtocol
する
次のコマンドを使用します。
class VMAPViewController: UIViewController, AdControllerProtocol {
4. のインスタンスをAVPlayerViewController
使用可能にするAVPlayer
次のコマンドを使用します。
let appContentVideoPlayer:AVPlayer? = AVPlayer(url: URL(string: "<URL to your content video>")!)
let appContentViewController:AVPlayerViewController? = AVPlayerViewController()
5. AdController のインスタンスを作成する
adController オブジェクトは、UIControllerVIew 内でスコープを設定する必要があります。 次のコマンドを使用します。
let adController = AdController()
6. (省略可能) AdSlot オブジェクトを定義する
アプリケーションと SDK 間の通信のパラメーターとして AdSlot オブジェクトを提供します。 AdSlot は、複数の VAST オブジェクトを含む広告ブレーク (または "広告ポッド") を表します。 この例でわかるように、VastData 配列は 1 回の中断で複数の広告に対応します。
最初の "セットアップ" メソッドは、VMAP 広告の中断を表すを返します Array<AdSlot>
。
@objc public class AdSlot: NSObject, Codable {
public let breakId: String?;
public var timeOffset: String?;
public let breakType: String?;
public let vastDatas: Array<VastData>;
public let currentAdId: String?;
public let timeToShowAdBreak: Int?;
}
7. 必要な adPlaybackControllerDidSetup
デリゲート メソッドを実装する
UIViewController でこのデリゲート メソッドを使用して、コンテンツの再生前に事前登録広告を考慮します。
func adPlaybackControllerDidSetup(adSlots: Array<AdSlot>?) {
if (adSlots == nil) {
/// fatal SDK error, start playback of your app content video here
} else {AdControllerProtocol
/// SDK called ad URL and got a response from the server and all internal properties are being set and ready to go
adController.play();//send play() signal to SDK
}
}
8. 必要な adPlaybackControllerShouldStartAd
デリゲート メソッドを実装する
このデリゲート メソッドは、ビデオ広告の再生の準備ができている SDK に通知するために UIViewController に実装する必要があります。 SDK は、ビデオ広告を表示する時間であると判断すると、コンテンツ ビデオを一時停止し、1 つの "AdSlot" オブジェクトを使用してこのメソッドを呼び出します。 パブリッシャー アプリケーションは、広告固有の動作を実装できます。 この関数は を返す true
必要があることに注意してください。 が返された false
場合、広告は表示されません。
func adPlaybackControllerShouldStartAd(adSlot: AdSlot?) -> Bool {
return true // if publisher application allows SDK to play video ad for the "adSlot"
}
9. 必要な adPlaybackControllerDidNotifyAdSlotEnded
デリゲート メソッドを実装する
このデリゲート メソッドは UIViewController に実装する必要があります。これにより、SDK は、ビデオ広告スロットがすべての広告クリエイティブの再生を完了したことをプログラムに通知できます。 このデリゲートが呼び出されると、SDK はコンテンツ ビデオの再生を再開します。
func adPlaybackControllerDidNotifyAdSlotEnded(adSlot: AdSlot?) {
//do publisher application's internal work here
}
10. 追加のデリゲート メソッドを実装する
これらのデリゲート メソッドの実装が必要です。 ただし、スタブ関数のままでいることができます。
/// a delegate when sdk raised an error
///
/// - Parameters:
/// - adSlot: AdSlot where error occurred
/// - result: ANTVErrorProrotocol
/// - Returns: void
func adPlaybackControllerDidRaiseAnError(adSlot: AdSlot?, result: ANTVErrorProtocol?) {
//do stuff on publisher application when SDK reports an error
}
/// A delegate SDK triggered a event
///
/// - Parameters:
/// - adSlot: AdSlot where event triggered
/// - result: any object
/// - Returns: void
func adPlaybackControllerDidNotifyAdSlotEnded(adSlot: AdSlot?) {
//do stuff on publisher application when SDK notifies an event
}
実装メソッド
通話 setup()
メソッドを setup()
呼び出して SDK を初期化し、広告を要求します。 SDK の準備ができたら、デリゲート メソッドを adPlaybackControllerDidSetup
呼び出します。 を渡すとcontentVideoPlayerViewController
contentVideoPlayer,
contentUIViewController
、SDK は、広告の中断を表示する時間になるとコンテンツ ビデオの再生を停止したり、コンテンツ ビデオ タイムラインに広告の中断マークを表示したりできます。
注:
Apple TV SDK を初期化するには、 contentVideoPlayer
呼び出された setup()
時点でビデオアセットが必要です。
次の例では、VMAP、Xandr 配置セット、VAST URL、Xandr VAST 配置のセットアップを呼び出す方法を示します。
// VMAP URL
adController.setup(vmapURL:String, contentVideoPlayerViewController: AVPlayerViewController, contentVideoPlayer: AVPlayer, contentUIViewController: UIViewController, delegate: AdControllerProtocol)
// Xandr Placement Set Id
adController.setup(appNexusPsetId: Int, contentVideoPlayerViewController: AVPlayerViewController?, contentVideoPlayer: AVPlayer?, contentUIViewController: UIViewController?, delegate: AdControllerProtocol)
// VAST URL
adController.setup(vastUrl: String, contentVideoPlayerViewController: AVPlayerViewController?, contentVideoPlayer: AVPlayer?, contentUIViewController: UIViewController?,delegate: AdControllerProtocol)
// Xandr VAST Placement ID
adController.setup(appNexusMemberId: Int, appNexusPlacementId: Int, contentVideoPlayerViewController: AVPlayerViewController?, contentVideoPlayer: AVPlayer?, contentUIViewController: UIViewController?,delegate: AdControllerProtocol
広告の一時停止/再開
を呼び出 pauseAd()/resumeAd()
して、動画広告を制御します。 getPauseStatus()
は、広告の現在の一時停止状態を返します。
adController.pauseAd() //pause video ad
adController.resumeAd() //resume video ad
adController.getPauseStatus() //true if video ad paused, false otherwise
広告をスキップする
スキップ ボタンをレンダリングするには、デリゲート メソッドを実装します adPlaybackControllerDidNotifyAnEvent()
。 SDK ロジックは、API skip()
を呼び出す処理UIControlEvents.primaryActionTriggered
対象を追加します。 これは VideoEvent.timeToShowSkip
VAST skipoffset
属性を信頼します。
func adPlaybackControllerDidNotifyAnEvent(adSlot: AdSlot?, event: VideoEvent?, data: String?) {
if (event == VideoEvent.timeToShowSkip) {
//render skip button
button.frame = CGRect(x: 0, y: 0, width: 450, height: 100)
button.setTitle("Click to Skip", for: .normal)
button.addTarget(self, action: #selector(self.skipClicked), for: .primaryActionTriggered)
self.view.addSubview(button)
//update focus engine to let user click a button
self.setNeedsFocusUpdate()
self.updateFocusIfNeeded()
}
}
@objc func skipClicked() {
self.adController.skip() //SDK skip call
//remove target and button
self.button.removeTarget(nil, action: nil, for: .allEvents)
self.button.removeFromSuperview()
}
SDK の動作のカスタマイズ
メソッドを setOptions()
使用して、SDK の外観、広告で表示するテキスト、ビデオ広告にスキップ ボタンを表示するかどうか、その他の機能を指定できます。 の前setup()
にsetOptions()
呼び出す必要があることに注意してください。
これらの設定はすべて省略可能です。 次の例は、それらを設定する方法を示しています。
adController.setOptions(
widthOfAdIndicator: 100,
leftMarginOfAdIndicator: 200,
bottomMarginOfAdIndicator: 300,
backgroundColor: UIColor.black,
heightOfAdIndicator: 400,
fontColor: UIColor.blue,
alphaOfAdIndicator: 0.5,
widthOfAdCountdown: 500,
heightOfAdCountdown: 600,
adText: "advertisement",
isSkippable: true);
...
setOptions() パラメーターリファレンス
パラメーター | データ型 | 説明 |
---|---|---|
adText |
String?=nil |
広告インジケーターのテキスト (例: Ad ) |
alphaOfAdIndicator |
Double?=nil |
広告インジケーターのアルファ チャネル (透明度) の値。 - 1.0=非透過的 - 0.5=50% Transparent - 0=完全に透明 (したがって非表示) |
backgroundColor |
UIColor?=nil |
広告インジケーターの背景色。 |
bottomMarginOfAdIndicator |
Int?=nil |
広告インジケーターの下余白の高さ (ピクセル単位)。 |
disableSelectGestureOverride |
Bool?=nil |
Xandr ではなくパブリッシャー アプリがリモート トラックパッドのジェスチャ アクションを制御する必要があるかどうか。 Xandr が通常のジェスチャをオーバーライドし、スキップ アクションを有効にするには、このパラメーターを に false 設定します。 たとえば、true です。 |
fontColor |
UIColor?=nil |
広告インジケーターのフォントの色。 |
heightOfAdCountdown |
Int?=nil |
広告カウントダウンの高さ (ピクセル単位)。 |
heightOfAdIndicator |
Int?=nil |
広告インジケーターの高さ (ピクセル単位)。 |
isSkippable |
Bool?=nil |
スキップ ボタンが表示されているかどうか。これにより、ビューアーは広告をスキップできます。 たとえば、true です。 |
leftMarginOfAdIndicator |
Int?=nil |
広告インジケーターの左余白の幅 (ピクセル単位)。 |
widthOfAdCountdown |
Int?=nil |
広告カウントダウンの幅 (ピクセル単位)。 広告のカウントダウンは、広告が再生される秒数を表示する領域です。 広告がスキップ可能な場合は、ビューアーがスキップ ボタンをクリックするまでの秒数が表示されます。 |
widthOfAdIndicator |
Int?=nil |
広告インジケーターの幅 (ピクセル単位)。 広告インジケーターは、広告であることを示す広告のセクションであり、要求されたコンテンツではありません。 |
のサンプル コード UIViewController
この例では、Swift を使用します。
import Foundation
import ANTVSDK
import AVKit
import os
class DevViewController: UIViewController, AdControllerProtocol {
static let contentURL: String = "<your content video url>"
let adController = AdController()
let appContentVideoPlayer:AVPlayer? = AVPlayer(url: URL(string: contentURL)!)
let appContentViewController:AVPlayerViewController? = AVPlayerViewController()
let button = UIButton.init(type: .system)
override func viewDidLoad() {
super.viewDidLoad()
self.initANTVSDK()
}
deinit {
adController.dismiss() //dismiss all objects created on ANTVSDK
}
func initANTVSDK() -> Void {
//setup options
adController.setOptions(isSkippable: true, disableSelectGestureOverride: true)
adController.setup(vmapURL: "<your vmap url>", contentVideoPlayerViewController: appContentViewController!, contentVideoPlayer: appContentVideoPlayer!, contentUIViewController: self, delegate: self)
}
func adPlaybackControllerDidSetup(adSlots: Array<AdSlot>?) {
adController.play()
}
func adPlaybackControllerShouldStartAd(adSlot: AdSlot?) -> Bool {
return true;
}
@objc func skipClicked() {
self.adController.skip()
//remove target and button
self.button.removeTarget(nil, action: nil, for: .allEvents)
self.button.removeFromSuperview()
}
func adPlaybackControllerDidNotifyAdSlotEnded(adSlot: AdSlot?) {
Logger.debug("got adPlaybackControllerDidNotifyAdSlotEnded")
exit(0)
}
func adPlaybackControllerDidRaiseAnError(adSlot: AdSlot?, result: ANTVErrorProtocol?) {
Logger.error("got error from SDK: %@", (result?.description)!)
}
func adPlaybackControllerDidNotifyAnEvent(adSlot: AdSlot?, event: VideoEvent?, data: String?) {
if (event == VideoEvent.timeToShowSkip) {
//render skip button
button.frame = CGRect(x: 0, y: 0, width: 450, height: 100)
button.setTitle("Click to Skip", for: .normal)
button.addTarget(self, action: #selector(self.skipClicked), for: .primaryActionTriggered)
self.view.addSubview(button)
//update focus engine to let user click a button
self.setNeedsFocusUpdate()
self.updateFocusIfNeeded()
}
}
}
ヒントとベスト プラクティス
アプリに SDK を実装する場合は、次のベスト プラクティスを使用します。
DFP 相関子の更新
ANTVSDK で DFP タグを呼び出すと、相関子によってパブリッシャーが DFP サーバーから適切な応答を受け取ります。 次の例に示すように、 correlator
この呼び出しを行うたびにタグのパラメーターを変更してください。
https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpreonly&cmsid=496&vid=short_onecue&correlator={unique random number}
SDK にコンテンツ ビデオを開始させる
アプリケーションでコンテンツ ビデオを単独で開始しないでください。 SDK に広告が読み込まれるまで待機し、ロール前の広告が表示される場合があります。 実装 adPlaybackControllerDidSetup
すると、SDK によってコンテンツ ビデオが開始されます。 この方法を使用すると、アプリのコンテンツ ビデオが開始される前に、事前登録広告が正しく表示されます。
メモリ管理
tvOS ARC (自動参照カウント) は、発行元アプリケーションの UIViewController が無視された時点では必要のない、ANTVSDK で使用されるほとんどのオブジェクトをチェックしてクリーンアップします。 ただし、ARC をサポートして確実に有効にするには、パブリッシャー アプリケーションの UIViewController のブロックで (次の例に示すように) を呼び出すadController.dismiss()
deinit
必要があります。
deinit {
adController.dismiss() //dismiss all objects created on ANTVSDK
}
セキュリティで保護されていないモードでのテスト
既定では、Xcode はセキュリティで保護されていない HTTP 要求をサポートしていません。 開発時のテストとデバッグの状況によっては、セキュリティで保護されていない HTTP タグを使用する必要がある場合があります。 HTTP プロトコルへのフル アクセスを一時的に有効にするには、[プロジェクト情報] タブをチェックして、プロジェクトで任意の読み込みが許可されていることを確認します。
x86_64および ARM64 バイナリ バージョンの管理
フレームワーク "ANTVSDK.framework" には、エミュレーターと実際の Apple TV デバイスの両方をサポートするx86_64と ARM64 バイナリが含まれています。 Apple AppStore ガイドラインのためにアプリケーションに x86_64 バイナリを含めない場合は、次の例に示すように、 を使用して lipo
削除するだけです。
cd ANTVSDK.framework
lipo -remove x86_64 ANTVSDK -o ANTVSDK
その後、チェックして、ライブラリに ARM64 バイナリのみが含まれているかどうかを確認できます。
<username>:ANTVSDK.framework $ file ANTVSDK
ANTVSDK: Mach-O universal binary with 1 architecture: [arm64: Mach-O 64-bit dynamically linked shared library arm64]
ANTVSDK (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
<username>:ANTVSDK.framework $
目標 C プロジェクトの要件
既定では、XCode には Objective-C プロジェクトに Swift Standard Libraryes を使用する設定がありません。 Objective-C ベースのパブリッシャー アプリケーションの場合は、IDE のビルド設定で [Always Embed Swift Standard Libraryes]\(常に Swift 標準ライブラリを埋め込む\) 設定を [はい ] に設定する必要があります。