Comienza a usar la extensión de IMA de ExoPlayer

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 Marca de verificación Marca de verificación
DASH Marca de verificación Marca de verificación

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

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:

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:

  1. Agrega un CMS ID y un Video ID para una transmisión de prueba de VOD.
  2. Crea un URI de VOD de SSAI con ImaServerSideAdInsertionUriBuilder().
  3. 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.