O ExoPlayer é um player de mídia no nível do aplicativo para Android. Este guia mostra como usar a extensão do ExoPlayer IMA, que encapsula o SDK de DAI do IMA, para solicitar e reproduzir um fluxo de mídia com anúncios e conteúdo.
Confira alguns benefícios da extensão:
- Simplifica o código necessário para integrar a IMA com recursos.
- Reduz o tempo de desenvolvimento necessário para atualizar para novas versões da IMA.
A extensão IMA do ExoPlayer é compatível com os protocolos de streaming HLS e DASH. Confira um resumo:
Compatibilidade com streams da extensão ExoPlayer-IMA | ||
---|---|---|
Transmissão ao vivo | Streams de VOD | |
HLS | ![]() |
![]() |
DASH | ![]() |
![]() |
As transmissões ao vivo DASH são compatíveis com o ExoPlayer-IMA versão 1.1.0 e mais recentes.
Este guia é baseado no guia do ExoPlayer e mostra como criar um app completo e integrar a extensão. Consulte o
ExoPlayerExample
do
GitHub para ver um exemplo com
um app de exemplo completo.
Pré-requisitos
- Android Studio
- AndroidX Media3 ExoPlayer versão 1.0.0 ou mais recente para suporte à DAI.
Criar um novo projeto do Android Studio
Para criar seu projeto do Android Studio, siga estas etapas:
- Inicie o Android Studio.
- Selecione Start a new Android Studio project.
- Na página Escolher seu projeto, selecione o modelo Nenhuma atividade.
- Clique em Próxima.
Na página Configure seu projeto, nomeie o projeto e selecione Java como a linguagem.
Clique em Concluir.
Adicionar a extensão IMA do ExoPlayer ao projeto
Adicione importações para a extensão ao arquivo build.gradle no nível do aplicativo
na seção dependencies
.
Configure o app e ative o
multidex. Isso é necessário devido ao tamanho da extensão e é obrigatório para apps com minSdkVersion
definido como Android 4.4W (API de nível 20) ou anterior.
Veja um exemplo:
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' }
Adicione as permissões de usuário necessárias pelo SDK da DAI do IMA para solicitar anúncios:
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>
Adicionar declarações de intent
Se o app for direcionado ao Android 11 (nível 30 da API) ou versões mais recentes, as versões atuais e recentes do SDK DAI do IMA vão exigir uma declaração explícita de intenção de abrir links da Web. Adicione o snippet a seguir ao arquivo de manifesto do app para ativar os cliques em anúncios (usuários clicando no botão Saiba mais).
<?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>
Configurar a interface do ExoPlayer
Crie o objeto PlayerView
a ser usado pelo ExoPlayer.
Mude o androidx.constraintlayout.widget.ConstraintLayout
para um
LinearLayout
, que é recomendado para a extensão IMA do ExoPlayer.
Veja um exemplo:
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>
Adicionar parâmetros de stream
Consulte a página de stream de amostra da IMA para conferir recursos de stream de amostra e testar seu projeto. Consulte também a seção do Ad Manager na DAI para saber como configurar seus próprios streams.
Esta etapa demonstra como configurar uma transmissão ao vivo, mas a extensão IMA do ExoPlayer também é compatível com streams de DAI VOD. Confira a etapa para transmissões de vídeo on demand (VOD) e saiba quais mudanças seu app precisa fazer para lidar com transmissões de VOD.
Importar a extensão IMA do ExoPlayer
Adicione as instruções de importação para a extensão do ExoPlayer.
Adicione as seguintes variáveis particulares a MyActivity.java
:
PlayerView
ExoPlayer
ImaServerSideAdInsertionMediaSource.AdsLoader
ImaServerSideAdInsertionMediaSource.AdsLoader.State
Adicione a chave de recurso da transmissão HLS Big Buck Bunny (Live) para testar com essa transmissão. Mais transmissões estão disponíveis para teste na página de amostra de transmissão da IMA.
Crie uma constante KEY_ADS_LOADER_STATE
para salvar e recuperar o estado AdsLoader
.
Veja um exemplo:
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; }
Criar uma instância adsLoader
Substitua o método onCreate
para encontrar o PlayerView
e verificar se há um AdsLoader.State
salvo, que pode ser usado ao iniciar o objeto adsLoader
.
Além disso, ative o multidex se necessário pela contagem de métodos do app e pela minSdkVersion
(conforme explicado na
etapa 2).
Veja um exemplo:
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; } }
Adicionar métodos para inicializar o player
Adicione um método para inicializar o player e faça o seguinte:
- Crie uma instância
AdsLoader
. - Crie o
ExoPlayer
. - Crie um
MediaItem
com a chave de recurso da transmissão ao vivo. - Defina o
MediaItem
para seu player.
Veja um exemplo:
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); } }
Adicionar um método para liberar o player
Adicione um método para liberar o jogador nesta sequência:
- Defina as referências do player como nulas e libere os recursos dele.
- Libere o estado do
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(); }
Processar eventos do player
Por fim, crie callbacks para os eventos do ciclo de vida da atividade para processar a reprodução de stream.
Para oferecer suporte à versão 24 ou mais recente do SDK do Android:
Para oferecer suporte a versões do SDK do Android anteriores à 24:
onStart()
e onResume()
são mapeados para playerView.onResume()
, e onStop()
e onPause()
são mapeados para playerView.onPause()
.
Esta etapa também usa o evento
onSaveInstanceState()
para tentar salvar o 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()); } } ... }
Configuração do stream de VOD (opcional)
Se o app precisar reproduzir conteúdo VOD com anúncios, faça o seguinte:
- Adicione um
CMS ID
e umVideo ID
para um stream de teste de VOD. - Crie um URI de VOD da SSAI usando
ImaServerSideAdInsertionUriBuilder()
. - Use esse novo URI como o item de mídia do player.
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); }
Pronto! Agora você está solicitando e reproduzindo um stream de mídia com a extensão IMA do ExoPlayer. Confira os exemplos de DAI do Android no GitHub para ver o código completo.