ExoPlayer es un reproductor multimedia a nivel de la aplicación para Android. En esta guía, se muestra cómo usar la extensión de IMA de ExoPlayer, que encapsula el SDK de IMA DAI, para solicitar y reproducir una transmisión de medios con anuncios y contenido.
Estos son algunos de los beneficios de la extensión:
- Simplifica el código necesario para integrar IMA con funciones.
- Reduce el tiempo de desarrollo necesario para actualizar a las nuevas versiones del IMA.
La extensión de IMA de ExoPlayer admite los protocolos de transmisión HLS y DASH. A continuación, se incluye un resumen:
Compatibilidad con transmisiones de la extensión IMA de ExoPlayer | ||
---|---|---|
Transmisión en vivo | Transmisiones de VOD | |
HLS | ![]() |
![]() |
DASH | ![]() |
![]() |
Las transmisiones en vivo de DASH son compatibles con la versión 1.1.0 y versiones posteriores de ExoPlayer-IMA.
Esta guía se basa en la guía de ExoPlayer y muestra cómo crear una app completa e integrar la extensión. Consulta ExoPlayerExample
de GitHub para ver un ejemplo con una app de ejemplo completa.
Requisitos previos
- Android Studio
- AndroidX Media3 ExoPlayer versión 1.0.0 o posterior para la compatibilidad con la DAI
Crea un proyecto nuevo de Android Studio
Para crear tu proyecto de Android Studio, completa los siguientes pasos:
- Inicia Android Studio.
- Selecciona Start a new Android Studio project.
- En la página Elige tu proyecto, selecciona la plantilla Sin actividad.
- Haz clic en Siguiente.
En la página Configura tu proyecto, asígnale un nombre y selecciona Java como lenguaje.
Haz clic en Finalizar.
Agrega la extensión de IMA de ExoPlayer a tu proyecto
Agrega importaciones para la extensión al archivo build.gradle a nivel de la aplicación en la sección dependencies
.
Configura tu app para multidex y habilítalo. Esto es necesario debido al tamaño de la extensión y se requiere para las apps con minSdkVersion
establecido en Android 4.4W (nivel de API 20) o versiones anteriores.
Por ejemplo:
app/build.gradle
android { ... defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.videoplayerapp" minSdkVersion 21 targetSdkVersion 34 multiDexEnabled true versionCode 1 versionName "1.0" } ... } dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.media3:media3-ui:1.7.1' implementation 'androidx.media3:media3-exoplayer:1.7.1' implementation 'androidx.media3:media3-exoplayer-hls:1.7.1' implementation 'androidx.media3:media3-exoplayer-dash:1.7.1' // Adding the ExoPlayer IMA extension for ads will also include the IMA // SDK as a dependency. implementation 'androidx.media3:media3-exoplayer-ima:1.7.1' }
Agrega los permisos del usuario que requiere el SDK de DAI de IMA para solicitar anuncios:
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name"> <!-- Required permissions for the IMA DAI SDK --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ... </manifest>
Cómo agregar declaraciones de intención
Si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores, las versiones actuales y recientes del SDK de IMA DAI requieren una declaración explícita de intención para abrir vínculos web. Agrega el siguiente fragmento al archivo de manifiesto de tu app para habilitar los clics en los anuncios (usuarios que hacen clic en el botón Más información).
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name"> ... </application> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> </intent> </queries> </manifest>
Configura la IU de ExoPlayer
Crea el objeto PlayerView
que usará ExoPlayer.
Cambia androidx.constraintlayout.widget.ConstraintLayout
por LinearLayout
, que se recomienda para la extensión de IMA de ExoPlayer.
Por ejemplo:
app/src/main/res/layout/activity_my.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:background="@android:color/black" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity" tools:ignore="MergeRootFrame"> <androidx.media3.ui.PlayerView android:id="@+id/player_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Agrega tus parámetros de transmisión
Consulta la página de muestra de transmisiones de IMA para obtener recursos de muestra de transmisiones y probar tu proyecto. Consulta también la sección de Ad Manager sobre la DAI para obtener información sobre cómo configurar tus propias transmisiones.
En este paso, se muestra cómo configurar una transmisión en vivo, pero la extensión de IMA de ExoPlayer también admite transmisiones de VOD de DAI. Consulta el paso para las transmisiones de video on demand (VOD) para ver qué cambios debe controlar tu app para las transmisiones de VOD.
Importa la extensión de IMA de ExoPlayer
Agrega las instrucciones de importación para la extensión de ExoPlayer.
Agrega las siguientes variables privadas a MyActivity.java
:
PlayerView
ExoPlayer
ImaServerSideAdInsertionMediaSource.AdsLoader
ImaServerSideAdInsertionMediaSource.AdsLoader.State
Agrega la clave del recurso de la transmisión HLS de Big Buck Bunny (en vivo) para probarla con esta transmisión. En la página de muestra de transmisiones de IMA, hay más transmisiones disponibles para probar.
Crea una constante KEY_ADS_LOADER_STATE
para guardar y recuperar el estado AdsLoader
.
Por ejemplo:
app/src/main/java/com/example/project name/MyActivity.java
import static androidx.media3.common.C.CONTENT_TYPE_HLS; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.annotation.OptIn; import androidx.media3.common.MediaItem; import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionUriBuilder; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.util.EventLogger; import androidx.media3.ui.PlayerView; import androidx.multidex.MultiDex; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; ... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaSdkSettings imaSdkSettings; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; }
Crea una instancia de adsLoader
Anula el método onCreate
para encontrar el PlayerView
y verificar si hay un AdsLoader.State
guardado, que se puede usar cuando se inicia el objeto adsLoader
.
Además, habilita multidex si lo requiere el recuento de métodos y minSdkVersion
de tu app (como se explica en el paso 2).
Por ejemplo:
app/src/main/java/com/example/project name/MyActivity.java
... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaSdkSettings imaSdkSettings; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); MultiDex.install(this); // Initialize the IMA SDK as early as possible when the app starts. If your app already // overrides Application.onCreate(), call this method inside the onCreate() method. // https://developer.android.com/topic/performance/vitals/launch-time#app-creation ImaSdkFactory.getInstance().initialize(this, getImaSdkSettings()); playerView = findViewById(R.id.player_view); // Checks if there is a saved AdsLoader state to be used later when // initiating the AdsLoader. if (savedInstanceState != null) { Bundle adsLoaderStateBundle = savedInstanceState.getBundle(KEY_ADS_LOADER_STATE); if (adsLoaderStateBundle != null) { adsLoaderState = ImaServerSideAdInsertionMediaSource.AdsLoader.State.fromBundle( adsLoaderStateBundle); } } } private ImaSdkSettings getImaSdkSettings() { if (imaSdkSettings == null) { imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings(); // Set any IMA SDK settings here. } return imaSdkSettings; } }
Agrega métodos para inicializar el reproductor
Agrega un método para inicializar el reproductor y haz lo siguiente:
- Crea una instancia de
AdsLoader
. - Crea el
ExoPlayer
: - Crea un objeto
MediaItem
con la clave del activo de la transmisión en vivo. - Establece el
MediaItem
en tu reproductor.
Por ejemplo:
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... // Create a server side ad insertion (SSAI) AdsLoader. private ImaServerSideAdInsertionMediaSource.AdsLoader createAdsLoader() { ImaServerSideAdInsertionMediaSource.AdsLoader.Builder adsLoaderBuilder = new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(this, playerView); // Attempt to set the AdsLoader state if available from a previous session. if (adsLoaderState != null) { adsLoaderBuilder.setAdsLoaderState(adsLoaderState); } return adsLoaderBuilder .setImaSdkSettings(getImaSdkSettings()) .build(); } private void initializePlayer() { adsLoader = createAdsLoader(); // Set up the factory for media sources, passing the ads loader. DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this); DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(dataSourceFactory); // MediaSource.Factory to create the ad sources for the current player. ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory = new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, mediaSourceFactory); // 'mediaSourceFactory' is an ExoPlayer component for the DefaultMediaSourceFactory. // 'adsMediaSourceFactory' is an ExoPlayer component for a MediaSource factory for IMA server // side inserted ad streams. mediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory); // Create an ExoPlayer and set it as the player for content and ads. player = new ExoPlayer.Builder(this).setMediaSourceFactory(mediaSourceFactory).build(); playerView.setPlayer(player); adsLoader.setPlayer(player); // Build an IMA SSAI media item to prepare the player with. Uri ssaiLiveUri = new ImaServerSideAdInsertionUriBuilder() .setAssetKey(SAMPLE_ASSET_KEY) .setFormat(CONTENT_TYPE_HLS) // Use CONTENT_TYPE_DASH for dash streams. .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiLiveUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); } }
Agrega un método para liberar al jugador
Agrega un método para liberar al jugador en esta secuencia:
- Establece las referencias del reproductor como nulas y libera los recursos del reproductor.
- Libera el estado del objeto
adsLoader
.
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... private void releasePlayer() { // Set the player references to null and release the player's resources. playerView.setPlayer(null); player.release(); player = null; // Release the adsLoader state so that it can be initiated again. adsLoaderState = adsLoader.release(); }
Cómo controlar eventos del reproductor
Por último, crea devoluciones de llamada para los eventos del ciclo de vida de la actividad para controlar la reproducción de transmisiones.
Para admitir la versión 24 y posteriores del SDK de Android, haz lo siguiente:
Para admitir versiones del SDK de Android anteriores a la 24, haz lo siguiente:
onStart()
y onResume()
se asignan a playerView.onResume()
, y onStop()
y onPause()
se asignan a playerView.onPause()
.
En este paso, también se usa el evento onSaveInstanceState()
para intentar guardar el adsLoaderState
.
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... @Override public void onStart() { super.onStart(); if (Util.SDK_INT > 23) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onResume() { super.onResume(); if (Util.SDK_INT <= 23 || player == null) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onPause() { super.onPause(); if (Util.SDK_INT <= 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onStop() { super.onStop(); if (Util.SDK_INT > 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onSaveInstanceState(Bundle outState) { // Attempts to save the AdsLoader state to handle app backgrounding. if (adsLoaderState != null) { outState.putBundle(KEY_ADS_LOADER_STATE, adsLoaderState.toBundle()); } } ... }
Configuración de la transmisión de VOD (opcional)
Si tu app debe reproducir contenido de VOD con anuncios, deberás hacer lo siguiente:
- Agrega un
CMS ID
y unVideo ID
para una transmisión de prueba de VOD. - Crea un URI de VOD de SSAI con
ImaServerSideAdInsertionUriBuilder()
. - Usa este nuevo URI como elemento multimedia del reproductor.
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private static final String SAMPLE_CMS_ID = "2548831"; private static final String SAMPLE_VIDEO_ID = "tears-of-steel"; ... private void initializePlayer() { ... Uri ssaiVodUri = new ImaServerSideAdInsertionUriBuilder() .setContentSourceId(SAMPLE_CMS_ID) .setVideoId(SAMPLE_VIDEO_ID) .setFormat(CONTENT_TYPE_HLS) .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiVodUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); }
Eso es todo. Ahora solicitas y reproduces una transmisión de contenido multimedia con la extensión de IMA de ExoPlayer. Consulta las muestras de DAI para Android en GitHub para ver el código completo.