Cómo comenzar a usar el SDK de IMA de DAI

Los SDK de IMA facilitan la integración de anuncios multimedia en tus 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 tus apps. Con los SDK de IMA de DAI, las apps realizan una solicitud de transmisión para anuncios y videos de contenido, ya sea VOD o contenido en vivo. Luego, el SDK muestra una transmisión de video por Internet combinada para que no tengas que administrar el cambio entre el anuncio y el video de contenido dentro de tu app.

Seleccione la solución de DAI que le interesa

DAI de servicio completo

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

Descripción general de la DAI de IMA

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

  • StreamDisplayContainer: Es un objeto contenedor que se ubica sobre el elemento de reproducción de video y aloja los elementos de la IU del anuncio.
  • AdsLoader: Es un objeto que solicita transmisiones y controla los eventos activados por los objetos de respuesta a solicitudes 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: Es un objeto que define una solicitud de transmisión. Las solicitudes de transmisión pueden ser para transmisiones de video on demand o 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 interacciones y los flujos de inserción de anuncios dinámicos con el backend de la DAI. El administrador de transmisiones también controla el seguimiento de los pings y reenvía eventos de transmisión y anuncios al publicador.

Requisitos previos

  • Android Studio
  • App de reproductor de video de muestra para la integración del SDK

Descarga y ejecuta la app de muestra de reproductor de video

La app de ejemplo proporciona un reproductor de video en funcionamiento que reproduce video HLS. Úsalo como punto de partida para integrar las capacidades de DAI del SDK de IMA para Android.

  1. Descarga la app de reproductor de video de muestra y extráela.

  2. Inicia Android Studio y selecciona Open an existing Android Studio project o, si Android Studio ya se está ejecutando, 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 se ejecute en un dispositivo Android físico o en un dispositivo virtual de Android con Run > Run 'app'. Es normal que la transmisión de video demore unos minutos en cargarse antes de reproducirse.

Examina el reproductor de video de muestra

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

  1. samplevideoplayer/SampleVideoPlayer.java: Es un reproductor HLS basado en ExoPlayer que funciona como base para la integración de la DAI de IMA.

  2. videoplayerapp/MyActivity.java: Esta actividad crea el reproductor de video y le pasa un Context y un 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 de nivel de aplicación, ubicado en app/build.gradle:

repositories {
  google()
  mavenCentral()
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.media3:media3-exoplayer:1.3.1'
    implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.33.0'
}

Integración del 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 el SampleVideoPlayer existente y agregar lógica que implemente la DAI de IMA. Para ello, primero debes crear un AdsLoader que se use para solicitar anuncios de 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 {
    
        // Livestream 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 = "2548831";
        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 (configurada 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, marca como comentario la solicitud de transmisión en vivo y quita el comentario de la solicitud.

    Para trabajar con DAI, un jugador debe pasar eventos ID3 para las transmisiones en vivo a los SDK de IMA. En el siguiente código de muestra, esto se hace con el método callback.onUserTextReceived().

    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);
                        }
                    }
                });
    
        // Livestream 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 livestream 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 implementa 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.

    Ten en cuenta la implementación de AdErrorListener, ya que llama a una URL de resguardo si no se reproducen los anuncios. Dado que el contenido y los anuncios están en una transmisión, debes 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 el 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/MyActivity.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 activity_my.xml de la actividad 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 solicitas y muestras anuncios de video en tu app para Android. Para optimizar tu implementación, consulta Favoritos, 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 la app.

Si los problemas persisten, visita el foro del SDK de IMA.