Pakiety IMA SDK ułatwiają integrację reklam multimedialnych z witrynami i aplikacjami. Pakiety IMA SDK mogą wysyłać żądania reklam z dowolnego serwera reklam zgodnego z VAST i zarządzać odtwarzaniem reklam w aplikacjach. Dzięki pakietom SDK IMA po stronie klienta możesz kontrolować odtwarzanie treści wideo, a pakiet SDK obsługuje odtwarzanie reklam. Reklamy wyświetlają się w osobnym odtwarzaczu umieszczonym nad odtwarzaczem wideo w aplikacji.
W tym przewodniku pokazujemy, jak zintegrować pakiet IMA SDK z prostą aplikacją odtwarzacza wideo. Jeśli chcesz obejrzeć ukończoną integrację z taką integracją lub ją kontynuować, pobierz BasicExample z GitHuba.
Przegląd po stronie klienta IMA
Implementacja IMA po stronie klienta obejmuje 4 główne komponenty SDK, które pokazano w tym przewodniku:
IMAAdDisplayContainer
: obiekt kontenera, w którym renderowane są reklamy.IMAAdsLoader
: obiekt, który wysyła żądania reklam i obsługuje zdarzenia z odpowiedzi na żądania reklam. Należy utworzyć tylko jeden program wczytujący reklamy, którego można używać wielokrotnie w całej aplikacji.IMAAdsRequest
: obiekt definiujący żądanie reklamy. Żądania reklam określają adres URL tagu reklamy VAST, a także dodatkowe parametry, np. wymiary reklamy.IMAAdsManager
: obiekt zawierający odpowiedź na żądanie reklamy, steruje odtwarzaniem reklam i nasłuchuje zdarzeń reklamowych wywoływanych przez pakiet SDK.
Wymagania wstępne
Zanim zaczniesz, musisz mieć:
- Xcode 13 lub nowsza wersja
- CocoaPods (preferowane), Menedżer pakietów Swift lub pobrana kopia pakietu IMA SDK dla tvOS
1. Utwórz nowy projekt Xcode
W Xcode utwórz nowy projekt na tvOS przy użyciu Objective-C lub Swift. Jako nazwę projektu użyj BasicExample.
2. Dodawanie pakietu IMA SDK do projektu Xcode
Instalowanie pakietu SDK za pomocą CocoaPods (preferowane)
CocoaPods to menedżer zależności w projektach Xcode i zalecana metoda instalacji pakietu IMA SDK. Więcej informacji o instalowaniu i używaniu CocoaPods znajdziesz w dokumentacji CocoaPods. Po zainstalowaniu CocoaPods postępuj zgodnie z tymi instrukcjami, aby zainstalować pakiet IMA SDK:
W tym samym katalogu co plik BasicExample.xcodeproj utwórz plik tekstowy o nazwie BasicExample.xcodeproj i dodaj tę konfigurację:
source 'https://github.com/CocoaPods/Specs.git' platform :tvos, '14' target "BasicExample" do pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.13.0' end
W katalogu zawierającym plik Podfile uruchom
pod install --repo-update
Sprawdź, czy instalacja się udała. Otwórz plik BasicExample.xcworkspace i potwierdź, że zawiera on 2 projekty: BasicExample i Pods (zależności zainstalowane przez CocoaPods).
Zainstaluj pakiet SDK za pomocą menedżera pakietów Swift
Pakiet Interactive Media Ads SDK obsługuje Swift Package Manager od wersji 4.8.2. Wykonaj poniższe czynności, aby zaimportować pakiet Swift.
W Xcode zainstaluj pakiet IMA SDK Swift, klikając Plik > Dodaj pakiety....
W wyświetlonym oknie wyszukaj repozytorium IMA SDK Swift Package GitHub:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
Wybierz wersję pakietu IMA SDK Swift, którego chcesz użyć. W przypadku nowych projektów zalecamy używanie wersji aż do następnej wersji głównej.
Gdy skończysz, Xcode rozstrzygnie zależności pakietów i pobierze je w tle. Więcej informacji o dodawaniu zależności pakietów znajdziesz w artykule Apple.
Ręczne pobieranie i instalowanie pakietu SDK
Jeśli nie chcesz używać CocoaPods, możesz pobrać pakiet IMA SDK i dodać go ręcznie do swojego projektu.
3. Utwórz prosty odtwarzacz wideo
Najpierw zaimplementuj podstawowy odtwarzacz wideo. Początkowo ten odtwarzacz nie korzysta z pakietu IMA SDK ani nie zawiera jeszcze żadnej metody aktywowania odtwarzania.
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"; @interface ViewController () @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; } - (void)setupContentPlayer { // Create a content video player. 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; // Attach content video player to view hierarchy. [self showContentPlayer]; } // 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 events from the remote. [self.contentPlayerViewController willMoveToParentViewController:nil]; [self.contentPlayerViewController.view removeFromSuperview]; [self.contentPlayerViewController removeFromParentViewController]; } @end
Swift
import AVFoundation import UIKit class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" var playerViewController: AVPlayerViewController! override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() } func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player showContentPlayer() } func showContentPlayer() { self.addChild(playerViewController) playerViewController.view.frame = self.view.bounds self.view.insertSubview(playerViewController.view, at: 0) playerViewController.didMove(toParent:self) } func hideContentPlayer() { // The whole controller needs to be detached so that it doesn't capture events from the remote. playerViewController.willMove(toParent:nil) playerViewController.view.removeFromSuperview() playerViewController.removeFromParent() } }
4. Importowanie pakietu IMA SDK
Następnie dodaj platformę IMA, używając instrukcji importu poniżej dotychczasowych importów.
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> #import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4";
Swift
import AVFoundation import GoogleInteractiveMediaAds import UIKit class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
5. Wdrożenie śledzenia suwaka odtwarzania treści oraz funkcji obserwacji zakończenia transmisji
Aby odtwarzać reklamy w trakcie filmu, pakiet IMA SDK musi śledzić bieżącą pozycję Twoich treści wideo. Aby to zrobić, utwórz klasę, która implementuje funkcję IMAContentPlayhead
. Jeśli używasz klasy AVPlayer
(jak w tym przykładzie), pakiet SDK udostępnia klasę IMAAVPlayerContentPlayhead
, która robi to za Ciebie.
Jeśli nie używasz AVPlayer
, musisz zaimplementować IMAContentPlayhead
w swojej klasie.
Musisz też powiadomić pakiet SDK o zakończeniu odtwarzania treści, aby mógł wyświetlać reklamy po filmie. W tym celu wywołaj contentComplete
na IMAAdsLoader
przy użyciu AVPlayerItemDidPlayToEndTimeNotification
.
ViewController.m
Objective-C
... @interface ViewController () @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end ... - (void)setupContentPlayer { // Create a content video player. 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]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification {} - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } @end
Swift
... class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! deinit { NotificationCenter.default.removeObserver(self) } ... func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player // Set up your 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() } ... @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
6. Zainicjuj program wczytujący reklamy i wyślij żądanie reklamy
Aby zażądać zestawu reklam, musisz utworzyć wystąpienie IMAAdsLoader
.
Za jego pomocą można przetworzyć obiekty IMAAdsRequest
powiązane z określonym adresem URL tagu reklamy.
Zalecaną metodą jest zachowanie tylko jednego wystąpienia IMAAdsLoader
w całym cyklu życia aplikacji. Aby wysyłać dodatkowe żądania reklamy, utwórz nowy obiekt IMAAdsRequest
i ponownie użyj tego samego obiektu IMAAdsLoader
. Więcej informacji znajdziesz w odpowiedziach na najczęstsze pytania dotyczące pakietu IMA SDK.
ViewController.m
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&impl=s&cmsid=496&vid=short_onecue&correlator="; @interface ViewController () @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; [self setupAdsLoader]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self requestAds]; } - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; } - (void)requestAds { // Pass the main view as the container for ad display. IMAAdDisplayContainer *adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.view]; IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kAdTagURLString adDisplayContainer:adDisplayContainer contentPlayhead:self.contentPlayhead userContext:nil]; [self.adsLoader requestAdsWithRequest:request]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification { // Notify the SDK that the postrolls should be played. [self.adsLoader contentComplete]; } ... @end
Swift
... class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4" 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&impl=s&correlator=" var adsLoader: IMAAdsLoader! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() setUpAdsLoader() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated); requestAds() } ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) } func requestAds() { // Create ad display container for ad rendering. let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view) // Create an ad request with your ad tag, display container, and optional user context. let request = IMAAdsRequest( adTagUrl: ViewController.AdTagURLString, adDisplayContainer: adDisplayContainer, contentPlayhead: contentPlayhead, userContext: nil) adsLoader.requestAds(with: request) } @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
7. Konfigurowanie przedstawiciela wczytywania reklam
Po udanym zdarzeniu wczytywania IMAAdsLoader
wywołuje metodę adsLoadedWithData
przypisanego przedstawiciela, przekazując mu instancję IMAAdsManager
. Następnie możesz zainicjować menedżera reklam, który wczytuje poszczególne reklamy zgodnie z odpowiedzią na adres URL tagu reklamy.
Pamiętaj też, by nie zapominać o wszelkich błędach, które mogą wystąpić podczas wczytywania. Jeśli reklamy się nie wczytają, zadbaj o to, aby multimedia były odtwarzane bez reklam, aby nie zakłócać wrażeń użytkownika.
ViewController.m
Objective-C
... @interface ViewController () <IMAAdsLoaderDelegate> @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAdsManager *adsManager; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController ... - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; self.adsLoader.delegate = self; } ... #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 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]; } @end
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate { ... var adsLoader: IMAAdsLoader! var adsManager: IMAAdsManager! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) adsLoader.delegate = self } ... // MARK: - IMAAdsLoaderDelegate func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { adsManager = adsLoadedData.adsManager adsManager.initialize(with: nil) } func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) { print("Error loading ads: " + adErrorData.adError.message) showContentPlayer() playerViewController.player?.play() } }
8. Wyznaczanie przedstawiciela menedżera Google Ads
I wreszcie, aby zarządzać zdarzeniami i zmianami stanu, menedżer reklam potrzebuje przedstawiciela. IMAAdManagerDelegate
udostępnia metody obsługi zdarzeń reklamowych i błędów, a także uruchamianie i wstrzymywanie odtwarzania treści wideo.
Rozpoczynam odtwarzanie
Metoda didReceiveAdEvent
może obsługiwać wiele zdarzeń, ale w tym podstawowym przykładzie wystarczy nasłuchiwać zdarzenia LOADED
, aby nakazać menedżerowi reklam rozpoczęcie odtwarzania treści i reklam.
ViewController.m
Objective-C
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate> ... - (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]; } ... #pragma mark - IMAAdsManagerDelegate - (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event { // Play each ad once it has loaded. if (event.type == kIMAAdEvent_LOADED) { [adsManager start]; } } ...
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate { ... func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { // Grab the instance of the IMAAdsManager and set yourself as the delegate. adsManager = adsLoadedData.adsManager adsManager.delegate = self adsManager.initialize(with: nil) } ... // MARK: - IMAAdsManagerDelegate func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) { // Play each ad once it has been loaded if event.type == IMAAdEventType.LOADED { adsManager.start() } } ...
Obsługa błędów
Dodaj też moduł obsługi błędów w reklamach. Jeśli wystąpi błąd, tak jak w poprzednim kroku, wznów odtwarzanie treści.
ViewController.m
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]; } @end
Swift
... func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) { // Fall back to playing content print("AdsManager error: " + error.message) showContentPlayer() playerViewController.player?.play() }
Aktywowanie zdarzeń odtwarzania i wstrzymywania
Dwie ostatnie metody przekazywania dostępu, które musisz zaimplementować, służą do uruchamiania i wstrzymywania zdarzeń odtwarzania i wstrzymywania odpowiednich treści wideo na żądanie pakietu IMA SDK. Włączenie wstrzymywania i odtwarzania na żądanie zapobiega pomijaniu fragmentów treści wideo podczas wyświetlania reklam.
ViewController.m
Objective-C
... - (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager { // Pause the content for the SDK to play ads. [self.contentPlayerViewController.player pause]; [self hideContentPlayer]; } - (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager { // Resume the content since the SDK is done playing ads (at least for now). [self showContentPlayer]; [self.contentPlayerViewController.player play]; } @end
Swift
... func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) { // Pause the content for the SDK to play ads. playerViewController.player?.pause() hideContentPlayer() } func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) { // Resume the content since the SDK is done playing ads (at least for now). showContentPlayer() playerViewController.player?.play() } }
Znakomicie. Zamawiasz i wyświetlasz reklamy za pomocą pakietu IMA SDK. Informacje o dodatkowych funkcjach pakietu SDK znajdziesz w innych przewodnikach lub w przykładach na GitHubie.
Dalsze kroki
Aby zmaksymalizować przychody z reklam na platformie tvOS, poproś usługę App Transparency i śledzenie o uprawnienia do używania identyfikatora IDFA.