Comenzar con el SDK de IMA de DAI

Los SDK de IMA facilitan la integración de anuncios multimedia en sus sitios web y aplicaciones. Los SDK de IMA pueden solicitar anuncios de cualquier servidor de anuncios compatible con VAST y administrar la reproducción de anuncios en sus aplicaciones. Con los SDK de DAI de IMA, las aplicaciones realizan una solicitud de transmisión para anuncios y video de contenido, ya sea VOD o contenido en vivo. Luego, el SDK muestra una transmisión de video combinada, de modo que no tienes que administrar el cambio entre el anuncio y el video de contenido dentro de tu app.

En esta guía, se muestra cómo integrar el SDK de IMA en una app simple de reproductor de video. Si quieres ver o seguir una integración de ejemplo completa, descarga el BasicExample de GitHub.

Descripción general de la DAI de IMA

La implementación de la DAI de IMA implica cuatro componentes principales del SDK, que se demuestran en esta guía:

  • StreamDisplayContainer: Es un objeto contenedor que se ubica sobre el elemento de reproducción del video y aloja los elementos de la IU del anuncio.
  • AdsLoader: Es un objeto que solicita transmisiones y controla eventos activados por objetos de respuesta de solicitud de transmisión. Solo debes crear una instancia de un cargador de anuncios, que se puede volver a usar durante la vida útil de la aplicación.
  • StreamRequest: Un objeto que define una solicitud de transmisión. Las solicitudes de transmisión pueden ser para video on demand o transmisiones en vivo. Las solicitudes especifican un ID de contenido, así como una clave de API o un token de autenticación y otros parámetros.
  • StreamManager: Es un objeto que controla las transmisiones de inserción de anuncios dinámicos y las interacciones con el backend de la DAI. El administrador de transmisiones también controla los pings de seguimiento y reenvía eventos de transmisión y anuncios al publicador.

Requisitos previos

  • Android Studio
  • La app de ejemplo para el reproductor de video que usarás a fin de integrar el SDK

Descarga y ejecuta la app de ejemplo del reproductor de video

La app de ejemplo proporciona un reproductor de video que funciona y que reproduce video de HLS. Úselo como punto de partida para integrar la funcionalidad de DAI del SDK de Android de IMA.

  1. Descarga la app de reproductor de video de muestra y descomprime.
  2. Inicia Android Studio y selecciona Open an existing Android Studio project, o si Android Studio ya está en ejecución, selecciona File > New > Import Project. Luego, elige SampleVideoPlayer/build.gradle.
  3. Ejecuta una sincronización de Gradle seleccionando Tools > Android > Sync Project with Gradle Files.
  4. Asegúrate de que la app del reproductor se compile y ejecute en un dispositivo Android físico o en un dispositivo virtual de Android mediante Run > Run 'app'. Es normal que la transmisión de video por Internet tarde unos minutos en cargarse antes de reproducirse.

Examina el reproductor de video de muestra

El reproductor de video de muestra todavía no contiene ningún código de integración del SDK de IMA. La app de muestra consta de dos partes principales:

  • samplevideoplayer/SampleVideoPlayer.java: Un reproductor HLS simple basado en ExoPlayer que sirve de base para la integración de DAI de IMA.
  • videoplayerapp/MyActivity.java: Esta actividad crea el reproductor de video y le pasa un Context y SimpleExoPlayerView.

Agregue el SDK de IMA para Android a la aplicación del reproductor

También debe incluir una referencia al SDK de IMA. En Android Studio, agrega lo siguiente al archivo build.gradle a nivel de la aplicación, ubicado en app/build.gradle:

repositories {
  google()
  jcenter()
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.browser:browser:1.3.0'
    implementation 'com.google.android.exoplayer:exoplayer:2.18.5'
    implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.30.1'
}

Punto de control: Tu aplicación debería compilarse y ejecutarse, pero aún no agregaste elementos de IU ni código para solicitar y mostrar anuncios.

Integrar el SDK de IMA

  1. Crea una clase nueva llamada SampleAdsWrapper en el paquete videoplayerapp (en app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/) para unir la SampleVideoPlayer existente y agrega lógica mediante la implementación de la inserción de anuncios dinámicos (DAI) de IMA. Para ello, primero debes crear un AdsLoader, que se usa a fin de solicitar anuncios de los servidores de anuncios.

    videoplayerapp/SampleAdsWrapper.java

    package com.google.ads.interactivemedia.v3.samples.videoplayerapp;
    
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.os.Build;
    import android.view.ViewGroup;
    import android.webkit.WebView;
    
    import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
    import com.google.ads.interactivemedia.v3.api.AdEvent;
    import com.google.ads.interactivemedia.v3.api.AdsLoader;
    import com.google.ads.interactivemedia.v3.api.AdsManagerLoadedEvent;
    import com.google.ads.interactivemedia.v3.api.CuePoint;
    import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
    import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
    import com.google.ads.interactivemedia.v3.api.StreamDisplayContainer;
    import com.google.ads.interactivemedia.v3.api.StreamManager;
    import com.google.ads.interactivemedia.v3.api.StreamRequest;
    import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
    import com.google.ads.interactivemedia.v3.api.player.VideoStreamPlayer;
    import com.google.ads.interactivemedia.v3.samples.samplevideoplayer.SampleVideoPlayer;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    public class SampleAdsWrapper implements AdEvent.AdEventListener,
            AdErrorEvent.AdErrorListener, AdsLoader.AdsLoadedListener {
    
        // Live stream asset key.
        private static final String TEST_ASSET_KEY = "sN_IYUG8STe1ZzhIIE_ksA";
    
        // VOD content source and video IDs.
        private static final String TEST_CONTENT_SOURCE_ID = "2528370";
        private static final String TEST_VIDEO_ID = "tears-of-steel";
    
        private static final String PLAYER_TYPE = "DAISamplePlayer";
    
        /**
         * Log interface, so you can output the log commands to the UI or similar.
         */
        public interface Logger {
            void log(String logMessage);
        }
    
        private ImaSdkFactory sdkFactory;
        private AdsLoader adsLoader;
        private StreamDisplayContainer displayContainer;
        private StreamManager streamManager;
        private List<VideoStreamPlayer.VideoStreamPlayerCallback> playerCallbacks;
    
        private SampleVideoPlayer videoPlayer;
        private Context context;
        private ViewGroup adUiContainer;
    
        private String fallbackUrl;
        private Logger logger;
    
        public SampleAdsWrapper(Context context, SampleVideoPlayer videoPlayer,
                                ViewGroup adUiContainer) {
            this.videoPlayer = videoPlayer;
            this.context = context;
            this.adUiContainer = adUiContainer;
            sdkFactory = ImaSdkFactory.getInstance();
            playerCallbacks = new ArrayList<>();
            createAdsLoader();
            displayContainer = sdkFactory.createStreamDisplayContainer(
                this.adUiContainer,
                videoStreamPlayer
            );
        }
    
        private void createAdsLoader() {
            ImaSdkSettings settings = new ImaSdkSettings();
            adsLoader = sdkFactory.createAdsLoader(context);
        }
    
        public void requestAndPlayAds() {
            adsLoader.addAdErrorListener(this);
            adsLoader.addAdsLoadedListener(this);
            adsLoader.requestStream(buildStreamRequest());
        }
    }
              
  2. Agrega un método buildStreamRequest() a AdsLoader para que pueda solicitar una transmisión con anuncios. Esta es una transmisión en vivo con anuncios (que se configura de forma predeterminada) o una transmisión de video on demand(VOD) que reproduce contenido grabado con anuncios. Para habilitar la transmisión de VOD, comenta la solicitud y quita el comentario de la solicitud.

    videoplayerapp/SampleAdsWrapper.java

    private StreamRequest buildStreamRequest() {
        VideoStreamPlayer videoStreamPlayer = createVideoStreamPlayer();
        videoPlayer.setSampleVideoPlayerCallback(
                new SampleVideoPlayer.SampleVideoPlayerCallback() {
                    @Override
                    public void onUserTextReceived(String userText) {
                        for (VideoStreamPlayer.VideoStreamPlayerCallback callback :
                                playerCallbacks) {
                            callback.onUserTextReceived(userText);
                        }
                    }
    
                    @Override
                    public void onSeek(int windowIndex, long positionMs) {
                        // See if you would seek past an ad, and if so, jump back to it.
                        long newSeekPositionMs = positionMs;
                        if (streamManager != null) {
                            CuePoint prevCuePoint  =
                                    streamManager.getPreviousCuePointForStreamTime(positionMs / 1000);
                            if (prevCuePoint != null && !prevCuePoint.isPlayed()) {
                                newSeekPositionMs = (long) (prevCuePoint.getStartTime() * 1000);
                            }
                        }
                        videoPlayer.seekTo(windowIndex, newSeekPositionMs);
                    }
    
                    @Override
                    public void onContentComplete() {
                        for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) {
                            callback.onContentComplete();
                        }
                    }
    
                    @Override
                    public void onPause() {
                        for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) {
                            callback.onPause();
                        }
                    }
    
                    @Override
                    public void onResume() {
                        for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) {
                            callback.onResume();
                        }
                    }
    
                    @Override
                    public void onVolumeChanged(int percentage) {
                        for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) {
                            callback.onVolumeChanged(percentage);
                        }
                    }
                });
    
        // Live stream request.
        StreamRequest request = sdkFactory.createLiveStreamRequest(
                TEST_ASSET_KEY, null, displayContainer);
    
        // VOD request. Comment the createLiveStreamRequest() line above and uncomment this
        // createVodStreamRequest() below to switch from a live stream to a VOD stream.
        // StreamRequest request = sdkFactory.createVodStreamRequest(TEST_CONTENT_SOURCE_ID,
        //        TEST_VIDEO_ID, null, displayContainer);
        return request;
    }
    
  3. También necesitas una VideoStreamPlayer para reproducir la transmisión, así que agrega un método createVideoStreamPlayer(), que crea una clase anónima que implemente VideoStreamPlayer.

    videoplayerapp/SampleAdsWrapper.java

    private VideoStreamPlayer createVideoStreamPlayer() {
        VideoStreamPlayer player = new VideoStreamPlayer() {
            @Override
            public void loadUrl(String url, List<HashMap<String, String>> subtitles) {
                videoPlayer.setStreamUrl(url);
                videoPlayer.play();
            }
    
            @Override
            public void addCallback(
                VideoStreamPlayerCallback videoStreamPlayerCallback) {
                    playerCallbacks.add(videoStreamPlayerCallback);
            }
    
            @Override
            public void removeCallback(
                VideoStreamPlayerCallback videoStreamPlayerCallback) {
                    playerCallbacks.remove(videoStreamPlayerCallback);
            }
    
            @Override
            public void onAdBreakStarted() {
                // Disable player controls.
                videoPlayer.enableControls(false);
                log("Ad Break Started\n");
            }
    
            @Override
            public void onAdBreakEnded() {
                // Re-enable player controls.
                videoPlayer.enableControls(true);
                log("Ad Break Ended\n");
            }
    
            @Override
            public VideoProgressUpdate getContentProgress() {
                return new VideoProgressUpdate(videoPlayer.getCurrentPosition(),
                        videoPlayer.getDuration());
            }
        };
        return player;
    }
    
  4. Implementa los objetos de escucha necesarios y agrega compatibilidad para el manejo de errores.

    Importante: Observa la implementación de AdErrorListener, ya que llama a una URL de resguardo si los anuncios no se pueden reproducir. Como el contenido y los anuncios están en una transmisión continua, debe estar listo para llamar a una transmisión de resguardo si la transmisión de DAI encuentra un error.

    videoplayerapp/SampleAdsWrapper.java

    /** AdErrorListener implementation **/
    @Override
    public void onAdError(AdErrorEvent event) {
        // play fallback URL.
        videoPlayer.setStreamUrl(fallbackUrl);
        videoPlayer.enableControls(true);
        videoPlayer.play();
    }
    
    /** AdEventListener implementation **/
    @Override
    public void onAdEvent(AdEvent event) {
        switch (event.getType()) {
            case AD_PROGRESS:
                // Do nothing or else log are filled by these messages.
                break;
            default:
                log(String.format("Event: %s\n", event.getType()));
                break;
        }
    }
    
    /** AdsLoadedListener implementation **/
    @Override
    public void onAdsManagerLoaded(AdsManagerLoadedEvent event) {
        streamManager = event.getStreamManager();
        streamManager.addAdErrorListener(this);
        streamManager.addAdEventListener(this);
        streamManager.init();
    }
    
    /** Sets fallback URL in case ads stream fails. **/
    void setFallbackUrl(String url) {
        fallbackUrl = url;
    }
    
  5. Agrega código para el registro.

    videoplayerapp/SampleAdsWrapper.java

    /** Sets logger for displaying events to screen. Optional. **/
    void setLogger(Logger logger) {
        this.logger = logger;
    }
    
    private void log(String message) {
        if (logger != null) {
            logger.log(message);
        }
    }
    
  6. Modifica MyActivity en videoplayerapp para crear una instancia y llamar a SampleAdsWrapper.

    videoplayerapp/MiActividad.java

    import android.view.ViewGroup;
    import android.widget.ScrollView;
    …
    public class MyActivity extends AppCompatActivity {
    …
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_my);
            View rootView = findViewById(R.id.videoLayout);
            videoPlayer = new SampleVideoPlayer(rootView.getContext(),
                    (SimpleExoPlayerView) rootView.findViewById(R.id.playerView));
            videoPlayer.enableControls(false);
    
            final SampleAdsWrapper sampleAdsWrapper = new SampleAdsWrapper(this, videoPlayer,
                (ViewGroup) rootView.findViewById(R.id.adUiContainer));
            sampleAdsWrapper.setFallbackUrl(DEFAULT_STREAM_URL);
    
            final ScrollView scrollView = (ScrollView) findViewById(R.id.logScroll);
            final TextView textView = (TextView) findViewById(R.id.logText);
    
            sampleAdsWrapper.setLogger(new SampleAdsWrapper.Logger() {
                @Override
                public void log(String logMessage) {
                    Log.i(APP_LOG_TAG, logMessage);
                    if (textView != null) {
                        textView.append(logMessage);
                    }
                    if (scrollView != null) {
                        scrollView.post(new Runnable() {
                            @Override
                            public void run() {
                                scrollView.fullScroll(View.FOCUS_DOWN);
                            }
                        });
                    }
                }
            });
    
            playButton = (ImageButton) rootView.findViewById(R.id.playButton);
            // Set up play button listener to play video then hide play button.
            playButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    sampleAdsWrapper.requestAndPlayAds();
                    playButton.setVisibility(View.GONE);
                }
            });
        }
    …
    }
  7. Modifica el archivo de diseño de la actividad, activity_my.xml, a fin de agregar elementos de la IU para el registro.

    res/layout/activity_my.xml

    …
        <TextView
            android:id="@+id/playerDescription"
            android:text="@string/video_description"
            android:textAlignment="center"
            android:gravity="center_horizontal"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.1"
            android:textSize="@dimen/font_size" />
        <!-- UI element for viewing SDK event log -->
        <ScrollView
            android:id="@+id/logScroll"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.5"
            android:padding="5dp"
            android:background="#DDDDDD">
    
            <TextView
                android:id="@+id/logText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </TextView>
        </ScrollView>
    

¡Felicitaciones! Ahora solicita y muestra anuncios de video en su aplicación para Android. Para ajustar la implementación, lee las guías Favoritos y Snapback, y la documentación de la API.

Solución de problemas

Si tienes problemas para reproducir un anuncio de video, intenta descargar el BasicExample completo. Si funciona correctamente en BasicExample, es probable que haya un problema con el código de integración de IMA de tu app. Revise esta guía y los documentos de la API para detectar discrepancias.

¿Aún tienes problemas? Escríbenos al foro del SDK de IMA.