Vamos começar

Os SDKs do IMA facilitam a integração de anúncios multimídia nos seus sites e apps. Os SDKs do IMA podem solicitar anúncios de qualquer servidor compatível com VAST e gerenciar a exibição de anúncios nos seus apps. Com os SDKs do lado do cliente do IMA, você mantém o controle da reprodução de vídeo do conteúdo, enquanto o SDK gerencia a reprodução do anúncio. Os anúncios são reproduzidos em um player de vídeo separado posicionado no player de vídeo do app.

Este guia demonstra como integrar o SDK do IMA a um app de player de vídeo simples. Se você quiser ver ou acompanhar um exemplo de integração concluída, faça o download do BasicExample no GitHub.

Visão geral do lado do cliente do IMA

A implementação do lado do cliente do IMA envolve quatro componentes principais do SDK, que são demonstrados neste guia:

  • IMAAdDisplayContainer: é um objeto contêiner em que os anúncios são renderizados.
  • IMAAdsLoader: um objeto que solicita anúncios e processa eventos de respostas de solicitações de anúncios. Só é possível instanciar um carregador de anúncios, que pode ser reutilizado ao longo da vida útil do aplicativo.
  • IMAAdsRequest: um objeto que define uma solicitação de anúncios. As solicitações de anúncios especificam o URL da tag de anúncio VAST, bem como parâmetros adicionais, como dimensões de anúncio.
  • IMAAdsManager: um objeto que contém a resposta à solicitação de anúncios, controla a reprodução dos anúncios e detecta os eventos de anúncios disparados pelo SDK.

Pré-requisitos

Antes de começar, os seguintes itens são necessários:

1. Criar um novo projeto do Xcode

No Xcode, crie um novo projeto tvOS usando Objective-C ou Swift. Use BasicExample como o nome do projeto.

2. Adicionar o SDK do IMA ao projeto Xcode

Como instalar o SDK usando o CocoaPods (preferencial)

O CocoaPods é um gerenciador de dependências para projetos do Xcode e é o método recomendado para instalar o SDK do IMA. Para mais informações sobre como instalar ou usar o CocoaPods, consulte a documentação do CocoaPods. Depois de instalar o CocoaPods, use as seguintes instruções para instalar o SDK do IMA:

  1. No mesmo diretório do arquivo BasicExample.xcodeproj, crie um arquivo de texto chamado Podfile e adicione a seguinte configuração:

    source 'https://github.com/CocoaPods/Specs.git'
    platform :tvos, '10'
    target "BasicExample" do
      pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.2'
    end
    
  2. No diretório que contém o Podfile, execute pod install --repo-update.

  3. Para verificar se a instalação foi bem-sucedida, abra o arquivo BasicExample.xcworkspace e confirme que ele contém dois projetos: BasicExample e Pods (as dependências instaladas pelo CocoaPods).

Como fazer o download e instalar o SDK manualmente

Se você não quiser usar o CocoaPods, faça o download do SDK do IMA e o adicione manualmente ao seu projeto.

3. Criar um player de vídeo simples

Primeiro, implemente um player de vídeo básico. Inicialmente, esse player não usa o SDK do IMA e ainda não contém nenhum método para acionar a reprodução.

ViewController.m

Objective-C

#import "ViewController.h"

#import <AVKit/AVKit.h>

NSString *const kContentURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/bipbop.m3u8";

@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/bipbop.m3u8"

  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. Importar o SDK do IMA

Em seguida, adicione o framework do IMA usando uma instrução de importação abaixo das importações existentes.

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/bipbop.m3u8";
      

Swift

import AVFoundation
import GoogleInteractiveMediaAds
import UIKit

class ViewController: UIViewController {
  static let ContentURLString = "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8"
      

5. Implementar o tracker de reprodução do conteúdo e o observador no fim da transmissão

Para reproduzir anúncios intermediários, o SDK do IMA precisa rastrear a posição atual do conteúdo em vídeo. Para fazer isso, crie uma classe que implemente IMAContentPlayhead. Se você estiver usando um AVPlayer, como mostrado neste exemplo, o SDK fornecerá a classe IMAAVPlayerContentPlayhead que fará isso por você. Se você não estiver usando AVPlayer, vai precisar implementar IMAContentPlayhead em uma classe própria.

Também é necessário informar o SDK quando o conteúdo for reproduzido para exibir anúncios finais. Para isso, chame contentComplete no IMAAdsLoader usando 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://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8"

  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. Inicializar o carregador de anúncios e fazer uma solicitação de anúncios

Para solicitar um conjunto de anúncios, você precisa criar uma instância de IMAAdsLoader. Esse carregador pode ser usado para processar objetos IMAAdsRequest associados a um URL de tag de anúncio especificado.

Como prática recomendada, mantenha apenas uma instância de IMAAdsLoader durante todo o ciclo de vida do app. Para fazer outras solicitações de anúncios, crie um novo objeto IMAAdsRequest, mas reutilize o mesmo IMAAdsLoader. Para mais informações, consulte as Perguntas frequentes sobre o SDK do IMA.

ViewController.m

Objective-C

...

NSString *const kContentURLString =
    @"https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/"
    @"master.m3u8";
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://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&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. Configurar um delegado do carregador de anúncios

Em um evento de carregamento bem-sucedido, o IMAAdsLoader chama o método adsLoadedWithData do delegado atribuído, transmitindo uma instância de IMAAdsManager. Em seguida, você pode inicializar o gerenciador de anúncios, que carrega os anúncios individuais, conforme definido pela resposta ao URL da tag de anúncio.

Além disso, processe todos os erros que podem ocorrer durante o processo de carregamento. Caso os anúncios não sejam carregados, a reprodução de mídia precisa continuar sem anúncios para não interferir na experiência do usuário.

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. Configurar um delegado do gerenciador de anúncios

Por fim, para gerenciar eventos e mudanças de estado, o gerenciador de anúncios precisa de um delegado. O IMAAdManagerDelegate tem métodos para processar erros e eventos de anúncios, além de métodos para acionar a reprodução e pausar no conteúdo de vídeo.

Iniciando reprodução

Há muitos eventos que o método didReceiveAdEvent pode usar para processar, mas, neste exemplo básico, basta detectar o evento LOADED para dizer ao gerenciador de anúncios para iniciar a reprodução do conteúdo e dos anúncios.

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()
    }
  }

...
      

Como processar os erros

Adicione também um gerenciador para erros de anúncios. Se ocorrer um erro, como na etapa anterior, retome a reprodução do conteúdo.

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()
  }
      

Como acionar eventos de reprodução e pausa

Os dois últimos métodos delegados que você precisa implementar são usados para acionar eventos de reprodução e pausação no conteúdo de vídeo subjacente, quando solicitado pelo SDK do IMA. O acionamento da pausa e da exibição quando solicitado impede que o usuário perca partes do conteúdo de vídeo quando os anúncios são exibidos.

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()
  }
}
      

Pronto! Agora você está solicitando e exibindo anúncios com o SDK do IMA. Para saber mais sobre outros recursos do SDK, consulte os outros guias ou as amostras no GitHub.

Próximas etapas

Para maximizar a receita de publicidade na plataforma tvOS, solicite a permissão de transparência e rastreamento do app para usar o IDFA.