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 tus apps. Con los SDK de DAI de IMA, las apps realizan una solicitud de transmisión de 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 anuncios y videos de contenido dentro de tu app.
Selecciona la solución de DAI que te interesa
DAI de servicio completo
En esta guía, se muestra cómo integrar el SDK de IMA de DAI en una app de reproductor de video simple. Si deseas ver o seguir una integración de muestra completa, descarga el BasicExample desde GitHub.
Descripción general de IMA de DAI
La implementación de la DAI de IMA incluye cuatro componentes principales del SDK, como se muestra en esta guía:
StreamDisplayContainer
: Es un objeto contenedor que se ubica encima del elemento de reproducción de 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 de la aplicación.StreamRequest
: Es un objeto que define una solicitud de transmisión. Las solicitudes de transmisión pueden ser de 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 interacciones y las transmisiones de inserción de anuncios dinámicos con el backend de DAI. El administrador de transmisiones también controla los pings de seguimiento y reenvía los eventos de anuncios y transmisiones 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 ejemplo del reproductor de video
La app de ejemplo proporciona un reproductor de video que funciona y que reproduce video HLS. Úsalo como punto de partida para integrar las funciones de DAI del SDK de IMA.
Descarga la app del reproductor de video de muestra y extráela.
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
.Ejecuta una sincronización de Gradle seleccionando Tools > Android > Sync Project with Gradle Files.
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 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 aún no contiene ningún código de integración del SDK de DAI de IMA. La app de ejemplo consta de dos partes principales:
samplevideoplayer/SampleVideoPlayer.java
: Un reproductor HLS basado en ExoPlayer que funciona como base para la integración de DAI de IMA.videoplayerapp/MyActivity.java
: Esta actividad crea el reproductor de video y le pasa unContext
y unSimpleExoPlayerView
.
Agregue el SDK de IMA de DAI a la aplicación del reproductor
También debe incluir una referencia al SDK de IMA de DAI. En Android Studio, agrega lo siguiente al archivo build.gradle
a nivel de la 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.34.0'
}
Integre el SDK de IMA de DAI
Crea una clase nueva llamada
SampleAdsWrapper
en el paquetevideoplayerapp
(enapp/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/
) para unir elSampleVideoPlayer
existente y agregar lógica que implemente la DAI de IMA. Para ello, primero debes crear unAdsLoader
que se use para 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 { // 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()); } }
Agrega un método
buildStreamRequest()
aAdsLoader
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 pregrabado 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 de transmisión de VOD.Para trabajar con la DAI, un jugador debe pasar eventos ID3 para las transmisiones en vivo a los SDK de IMA de DAI. 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; }
También necesitas un
VideoStreamPlayer
para reproducir la transmisión, así que agrega un métodocreateVideoStreamPlayer()
, que crea una clase anónima que implementaVideoStreamPlayer
.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()); } @Override public int getVolume() { return videoPlayer.getVolume(); } }; return player; }
Implementa los objetos de escucha requeridos y agrega compatibilidad con el manejo de errores.
Observa 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, debe poder 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; }
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); } }
Modifica
MyActivity
envideoplayerapp
para crear una instancia y llamar aSampleAdsWrapper
.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); } }); } ... }
Modifica el archivo de diseño de la actividad
activity_my.xml
para 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, descarga 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.
Si los problemas persisten, visita el foro del SDK de IMA.