ExoPlayer es un Reproductor multimedia a nivel de la aplicación para Android. En esta guía, se muestra cómo puedes usar la extensión de IMA de ExoPlayer, que une el SDK de IMA de DAI para solicitar y reproducir una transmisión multimedia 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 versiones nuevas de IMA.
La extensión de IMA de ExoPlayer admite los protocolos de transmisión HLS y DASH. Este es un Resumen:
Compatibilidad con la transmisión de extensiones de ExoPlayer-IMA | ||
---|---|---|
Transmisión en vivo | Transmisiones de VOD | |
HLS | ||
DASH |
Las transmisiones en vivo DASH son compatibles con la versión 1.1.0 de ExoPlayer-IMA y versiones posteriores.
Esta guía se basa en el tema ExoPlayer
guía y muestra
cómo crear una app completa y cómo 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 DAI y asistencia.
Cómo crear un nuevo proyecto de Android Studio
Para crear tu proyecto de Android Studio, sigue estos pasos:
- Inicia Android Studio.
- Selecciona Start a new Android Studio project.
- En la página Choose your project, selecciona la plantilla No Activity.
- Haz clic en Siguiente.
En la página Configura tu proyecto, asigna un nombre al proyecto y selecciona Java para el idioma.
Haz clic en Finalizar.
Agrega la extensión IMA de ExoPlayer a tu proyecto
Agrega importaciones para la extensión al archivo build.gradle del nivel de la aplicación.
en la sección dependencies
.
Configura tu app y habilita multidex. Esto es necesario debido al tamaño de la extensión y es obligatorio para las apps con minSdkVersion
configurado 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.1.1' implementation 'androidx.media3:media3-exoplayer:1.1.1' implementation 'androidx.media3:media3-exoplayer-hls:1.1.1' implementation 'androidx.media3:media3-exoplayer-dash:1.1.1' // Adding the ExoPlayer IMA extension for ads will also include the IMA // SDK as a dependency. implementation 'androidx.media3:media3-exoplayer-ima:1.1.1' }
Agregue los permisos de 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 intents
Si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores, la versión actual y del SDK de DAI de IMA requieren una declaración explícita de intent para abrir la Web enlaces. Agrega el siguiente fragmento al archivo de manifiesto de tu app para habilitar los clics en el anuncio (cuando los usuarios 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
a
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 los parámetros de transmisión
Consulta la página de flujo de muestras de IMA para obtener recursos de flujo de muestras para probar tu proyecto. Consulta también la sección de Ad Manager sobre la DAI para obtener información sobre cómo configurar tus propios flujos.
Este paso demuestra la configuración de una transmisión en vivo, pero el IMA de ExoPlayer también admite transmisiones DAI de VOD. Consulta el paso para video on demand (VOD) transmisiones y ver qué cambios necesita tu app para controlar 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 activo de transmisión HLS de Big Buck Bunny (en vivo) para probarla con esto en tiempo real. Hay más transmisiones disponibles para probar en la página de transmisiones de muestra de IMA.
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; ... 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 ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; }
Crea una instancia de adsLoader
Reemplaza el método onCreate
para encontrar el PlayerView
y comprobar si hay un AdsLoader.State
guardado, que se puede usar cuando se inicia el objeto adsLoader
.
Además, habilita multidex si así lo requieren el recuento de métodos de tu app y minSdkVersion
(como se explica en
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 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); 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); } } } }
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
MediaItem
con la clave del activo de la transmisión en vivo. - Configura
MediaItem
para el 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.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 el reproductor
Agrega un método para liberar al jugador en esta secuencia:
- Establece las referencias del reproductor en nulas y libera los recursos del jugador.
- Libera el estado de
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(); }
Controla eventos del jugador
Por último, crea devoluciones de llamada para que los eventos del ciclo de vida de la actividad controlen la transmisión reproducción.
Para admitir la versión 24 o posterior del SDK de Android, haz lo siguiente:
Para admitir versiones del SDK de Android anteriores a la 24, haz lo siguiente:
: onResume()
: onPause()
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
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 se requiere que tu app reproduzca contenido de VOD con anuncios, deberás hacerlo 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 URI nuevo como elemento multimedia de tu 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 estás solicitando y reproduciendo una transmisión de contenido multimedia con ExoPlayer extensión de IMA. Consulta los ejemplos de DAI de Android en GitHub para ver el código completo.