Compartir a través de


Guía de integración del SDK de AppleTV

En esta guía de integración se explica cómo integrar el SDK de AppleTV de Xandr en la aplicación AppleTV, de modo que pueda usar la inserción de anuncios del lado cliente de Xandr para pujar, realizar un seguimiento y medir la publicidad de vídeo del lado cliente dentro de la aplicación. En las instrucciones y ejemplos se da por supuesto lo siguiente:

  • Está desarrollando en Apple tvOS 12.0 o superior.
  • Tiene instancias existentes de AVPlayer y controlador AVPlayerView en el entorno de desarrollo.
  • Está usando las bibliotecas de código de Swift en Swift Core Libraries: Foundation. La versión mínima es SWIFT 4.2.
  • Usa Xcode v10.0 o superior.

Esta aplicación admite los /ptv puntos de conexión y /vmap .

En las secciones siguientes se explican los pasos necesarios para completar la integración, se proporciona una referencia a las opciones de personalización, se sugieren procedimientos recomendados y se realizan recomendaciones para los desarrolladores que prefieren usar Objective-C.

Configuración de la integración

1. Configurar e importar CocoaPods

CocoaPods se usa para distribuir el SDK de Xandr e integrarlo en la aplicación. Use los vínculos siguientes para instalar CocoaPods y agregarlo al proyecto.

Puede usar el código siguiente en el archivo de especificación de pod:

Podfile de ejemplo:

target 'MyApp' do
pod 'AppNexusTVOSSDK', '~> 2.0.0'
end

2. Importar el módulo de AppleTV SDK Xandr en UIViewController

Use los siguientes comandos:

import ANTVSDK
import AVKit //standard Audio Video Kit library

3. Agregar el AdControllerProtocol protocolo a UIViewController

Use los siguientes comandos:

class VMAPViewController: UIViewController, AdControllerProtocol {

4. Hacer que las instancias de AVPlayerViewController y AVPlayer estén disponibles

Use los siguientes comandos:

let appContentVideoPlayer:AVPlayer? = AVPlayer(url: URL(string: "<URL to your content video>")!)
let appContentViewController:AVPlayerViewController? = AVPlayerViewController()

5. Create una instancia de AdController

El objeto adController debe tener como ámbito UIControllerVIew. Use el siguiente comando:

let adController = AdController()

6. (Opcional) Definir el objeto AdSlot

Proporcionamos el objeto AdSlot como parámetro para la comunicación entre la aplicación y el SDK. AdSlot representa un salto de anuncio (o "pod de anuncio") que contiene varios objetos VAST. Como puede ver en el ejemplo, la matriz VastData admite varios anuncios en un solo salto.

El método de "configuración" inicial devolverá Array<AdSlot> que representa los saltos de anuncios de VMAP.

@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. Implementar el método delegado necesario adPlaybackControllerDidSetup

Use este método delegado en UIViewController para tener en cuenta los anuncios de pre-inscripción antes de la reproducción de contenido.

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. Implementar el método delegado necesario adPlaybackControllerShouldStartAd

Este método delegado debe implementarse en UIViewController para notificar al SDK que está listo para la reproducción de anuncios de vídeo. Cuando el SDK determine que es el momento de mostrar un anuncio de vídeo, pausará el vídeo de contenido e invocará este método con un único objeto "AdSlot". A continuación, la aplicación del publicador puede implementar cualquier comportamiento específico del anuncio. Tenga en cuenta que esta función debe devolver true. Si devuelve false, no se mostrará el anuncio.

func adPlaybackControllerShouldStartAd(adSlot: AdSlot?) -> Bool {
    return true // if publisher application allows SDK to play video ad for the "adSlot"
}

9. Implementación del método delegado necesario adPlaybackControllerDidNotifyAdSlotEnded

Este método delegado debe implementarse en UIViewController para que el SDK pueda notificar al programa que la ranura del anuncio de vídeo ha terminado de reproducir todas las creatividades de anuncios. Cuando se llama a este delegado, el SDK reanudará la reproducción del vídeo de contenido.

func adPlaybackControllerDidNotifyAdSlotEnded(adSlot: AdSlot?) {
    //do publisher application's internal work here
}

10. Implementar métodos delegados adicionales

Es necesario implementar estos métodos delegados. Sin embargo, pueden seguir siendo funciones auxiliares.

/// 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
}

Métodos de implementación

Llamar a setup()

Invoque el setup() método para inicializar el SDK y solicitar un anuncio. Cuando el SDK esté listo, invocará el adPlaybackControllerDidSetup método delegado. Tenga en cuenta que pasar contentVideoPlayerViewControllery contentVideoPlayer,contentUIViewController permite al SDK detener la reproducción de vídeo de contenido cuando es el momento de mostrar un salto de anuncios, así como mostrar marcas de interrupción de anuncios en la escala de tiempo del vídeo de contenido.

Nota:

Para inicializar el SDK de Apple TV, contentVideoPlayer debe tener recursos de vídeo en el momento setup() en que se llama a .

En los ejemplos siguientes se muestra cómo invocar la configuración para VMAP, para un conjunto de selección de ubicación Xandr, para una dirección URL VAST y para la ubicación de 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

Pausar o reanudar el anuncio

Invoque pauseAd()/resumeAd() para controlar el anuncio de vídeo. getPauseStatus() devolverá el estado de pausa actual del anuncio.

adController.pauseAd() //pause video ad
adController.resumeAd() //resume video ad
adController.getPauseStatus() //true if video ad paused, false otherwise

Omitir anuncio

Para representar un botón omitir, implemente el adPlaybackControllerDidNotifyAnEvent() método delegado. La lógica del SDK agrega un destino para controlar UIControlEvents.primaryActionTriggered que llamará a una API skip(). Esto VideoEvent.timeToShowSkip confía en el atributo 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()
}

Personalización del comportamiento del SDK

Puedes usar el setOptions() método para especificar cómo quieres que se vea el SDK, qué texto quieres mostrar con anuncios, si el anuncio de vídeo muestra un botón omitir y otras características. Tenga en cuenta que setOptions() debe invocarse antes de setup().

Todas estas opciones son opcionales. En el ejemplo siguiente se muestra cómo establecerlos:

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);
    ...

Referencia del parámetro setOptions()

Parámetro Tipo de datos Description
adText String?=nil Texto del indicador de anuncio (por ejemplo Ad, )
alphaOfAdIndicator Double?=nil Valor del canal alfa (transparencia) del indicador de anuncio.
- 1.0=no transparente
- 0,5=50% transparente
- 0=completamente transparente (y, por lo tanto, invisible)
backgroundColor UIColor?=nil Color de fondo del indicador de anuncio.
bottomMarginOfAdIndicator Int?=nil Alto del margen inferior del indicador de anuncio en píxeles.
disableSelectGestureOverride Bool?=nil Si la aplicación del publicador, no Xandr, debe controlar la acción de gesto del trackpad remoto. Para permitir que Xandr invalide el gesto normal y habilite una acción de omisión, establezca este parámetro en false. Por ejemplo, true.
fontColor UIColor?=nil Color de fuente del indicador de anuncio.
heightOfAdCountdown Int?=nil Alto de la cuenta atrás del anuncio en píxeles.
heightOfAdIndicator Int?=nil Alto del indicador de anuncio en píxeles.
isSkippable Bool?=nil Si se muestra un botón omitir, lo que permite al visor omitir el anuncio. Por ejemplo, true.
leftMarginOfAdIndicator Int?=nil Ancho del margen izquierdo del indicador de anuncio en píxeles.
widthOfAdCountdown Int?=nil Ancho de la cuenta atrás del anuncio en píxeles. La cuenta atrás del anuncio es el área que muestra el número de segundos para los que se reproduce el anuncio. Si el anuncio se puede omitir, muestra el número de segundos hasta que el visor puede hacer clic en el botón omitir.
widthOfAdIndicator Int?=nil Ancho del indicador de anuncio en píxeles. El indicador de anuncio es la sección del anuncio que indica que es publicidad y no contenido solicitado.

Código de ejemplo para UIViewController

En este ejemplo se usa 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()
        }  
    }  
}

Sugerencias y procedimientos recomendados

Use los siguientes procedimientos recomendados al implementar el SDK en la aplicación.

Actualización del correlacionador DFP

Cuando se llama a una etiqueta DFP con ANTVSDK, el correlacionador garantiza que el publicador recibe una respuesta adecuada del servidor DFP. Asegúrese de cambiar el parámetro en la correlator etiqueta cada vez que realice esta llamada, como se muestra en el ejemplo siguiente:

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}

Permitir que el SDK inicie el vídeo de contenido

La aplicación no debe iniciar el vídeo de contenido por sí mismo. Debe esperar hasta que el SDK haya cargado anuncios y, posiblemente, muestre un anuncio previo a la publicación. La implementación adPlaybackControllerDidSetup garantiza que el SDK inicia el vídeo de contenido. Al usar este método, los anuncios de pre-inscripción se mostrarán correctamente antes de que comience el vídeo de contenido de la aplicación.

Administración de memoria

tvOS ARC (Recuento automático de referencias) comprueba y limpia la mayoría de los objetos usados en ANTVSDK que no son necesarios en el momento en que se descarta UIViewController de la aplicación editora. Sin embargo, para admitir y garantizar la validez de ARC, es necesario llamar al adController.dismiss()deinit uiViewController de las aplicaciones del publicador (como se muestra en el ejemplo siguiente).

deinit {
    adController.dismiss() //dismiss all objects created on ANTVSDK
}

Pruebas en modo no seguro

De forma predeterminada, Xcode no admite solicitudes HTTP no seguras. Algunas situaciones de depuración y pruebas en tiempo de desarrollo pueden requerir el uso de etiquetas HTTP no seguras. Para habilitar temporalmente el acceso completo al protocolo HTTP, compruebe la pestaña "Información del proyecto" para asegurarse de que el proyecto permite cargas arbitrarias.

Administración de versiones binarias de x86_64 y ARM64

Un marco "ANTVSDK.framework" incluye x86_64 y arm64 binario para admitir un emulador y un dispositivo Apple TV real. En caso de que no quiera incluir el binario x86_64 en la aplicación debido a las directrices de Apple AppStore, puede quitarlo simplemente mediante lipo, como se muestra en el ejemplo siguiente:

cd ANTVSDK.framework
lipo -remove x86_64 ANTVSDK -o ANTVSDK

A continuación, puede comprobar si la biblioteca solo contiene el archivo binario 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 $

Requisitos del proyecto de Objective C

De forma predeterminada, XCode no tiene una configuración para usar las bibliotecas estándar de Swift para proyectos de Objective-C. En el caso de una aplicación de publicador basada en Objective-C, deberá establecer la opción "Insertar siempre bibliotecas estándar de Swift" en en la configuración de compilación del IDE.