O Jetpack Media3 define uma interface Player que descreve a funcionalidade básica para reprodução de arquivos de áudio e vídeo. ExoPlayer é a implementação padrão dessa interface na Media3. Recomendamos o uso do ExoPlayer, porque ele oferece um conjunto abrangente de recursos que abrangem a maioria dos casos de uso de reprodução e é personalizável para processar outros casos de uso que você possa ter. O ExoPlayer também abstrai a fragmentação de dispositivos e SOs para que seu código funcione de maneira consistente em todo o ecossistema Android. O ExoPlayer inclui:
- Suporte a playlists
- Suporte a vários formatos de streaming progressivo e adaptável formats
- Suporte à inserção de anúncios do lado do cliente e do lado do servidor ad insertion
- Suporte à reprodução protegida por DRM
Esta página orienta você pelas principais etapas da criação de um app de reprodução. Para mais detalhes, acesse nossos guias completos sobre o ExoPlayer da Media3.
Primeiros passos
Para começar, adicione uma dependência dos módulos ExoPlayer, UI e Common do Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.10.0" implementation "androidx.media3:media3-ui:1.10.0" implementation "androidx.media3:media3-common:1.10.0"
Dependendo do seu caso de uso, você também pode precisar de outros módulos da Media3, como exoplayer-dash, para reproduzir streams no formato DASH.
Substitua 1.10.0 pela versão preferida da biblioteca. Consulte as notas da versão
para conferir a versão mais recente.
Como criar um player de mídia
Com a Media3, você pode usar a implementação incluída da Player
interface, ExoPlayer, ou criar sua própria implementação personalizada.
Como criar um ExoPlayer
A maneira mais simples de criar uma instância ExoPlayer é a seguinte:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
Você pode criar seu player de mídia no método de ciclo de vida onCreate() da Activity, Fragment ou Service em que ele reside.
O Builder inclui
uma variedade de opções de personalização que podem ser interessantes para você, como:
setAudioAttributes()para configurar o processamento da seleção de áudiosetHandleAudioBecomingNoisy()para configurar o comportamento de reprodução quando um dispositivo de saída de áudio é desconectadosetTrackSelector()para configurar a seleção de faixas
A Media3 fornece um componente de interface PlayerView que pode ser incluído no arquivo de layout do app. Esse componente encapsula um PlayerControlView para controles de reprodução, SubtitleView para mostrar legendas e Surface para renderizar vídeos.
Como preparar o player
Adicione itens de mídia a uma playlist para
reprodução com métodos como
setMediaItem()
e addMediaItem().
Em seguida, chame prepare() para
começar a carregar a mídia e adquirir os recursos necessários.
Não execute essas etapas antes que o app esteja em primeiro plano. Se o player estiver em uma Activity ou Fragment, isso significa preparar o player no método de ciclo de vida onStart() no nível da API 24 e mais recentes ou no método de ciclo de vida onResume() no nível da API 23 e anteriores. Para um player que está em um Service, você pode prepará-lo em onCreate(). Consulte o codelab do Exoplayer para conferir um
exemplo de como implementar métodos de ciclo de vida.
Como controlar o player
Depois que o player for preparado, você poderá controlar a reprodução chamando métodos no player, como:
play()epause()para iniciar e pausar a reproduçãoseekTo()para procurar uma posição no item de mídia atualseekToNextMediaItem()eseekToPreviousMediaItem()para navegar pela playlist
Os componentes da interface, como PlayerView ou PlayerControlView, serão atualizados de acordo com a vinculação a um player.
Como liberar o player
A reprodução pode exigir recursos limitados, como decodificadores de vídeo. Por isso, é importante chamar release()
no player para liberar recursos quando ele não for mais necessário.
Se o player estiver em uma Activity ou Fragment, libere o player no método de ciclo de vida onStop() no nível 24 da API e mais recentes ou no método onPause() no nível 23 da API e anteriores. Para um player que está em um Service, você pode liberá-lo em onDestroy(). Consulte o codelab do Exoplayer para conferir um
exemplo de como implementar métodos de ciclo de vida.
Como gerenciar a reprodução com uma sessão de mídia
No Android, as sessões de mídia oferecem uma maneira padronizada de interagir com um player de mídia em limites de processos. Ao conectar uma sessão de mídia ao player , você pode anunciar a reprodução de mídia externamente e receber comandos de reprodução de fontes externas, por exemplo, para integrar com controles de mídia do sistema em dispositivos móveis e de tela grande.
Para usar sessões de mídia, adicione uma dependência do módulo de sessão da Media3:
implementation "androidx.media3:media3-session:1.10.0"
Como criar uma sessão de mídia
Você pode criar uma MediaSession depois de inicializar um player da seguinte maneira:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
A Media3 sincroniza automaticamente o estado do Player com o estado da MediaSession. Isso funciona com qualquer Player implementação, incluindo
ExoPlayer, CastPlayer ou uma
implementação personalizada.
Como conceder controle a outros clientes
Os apps clientes podem implementar um controlador de mídia
para controlar a reprodução da sessão de mídia. Para receber essas solicitações, defina um
objeto de callback ao
criar sua MediaSession.
Quando um controlador está prestes a se conectar à sessão de mídia, o
onConnect()
método é chamado. Você pode usar o ControllerInfo
para decidir se aceita
ou rejeita
a solicitação. Confira um exemplo disso no app de demonstração da sessão da Media3.
Depois de conectado, um controlador pode enviar comandos de reprodução para a sessão. Em seguida, a sessão delega esses comandos ao player. Os comandos de reprodução e playlist definidos na interface Player são processados automaticamente pela sessão.
Outros métodos de callback permitem processar, por exemplo, solicitações de
comandos de reprodução personalizados
e modificar a playlist. Esses callbacks também incluem um objeto ControllerInfo para que você possa determinar o controle de acesso em uma base de solicitação por solicitação.
Como reproduzir mídia em segundo plano
Para continuar reproduzindo mídia quando o app não estiver em primeiro plano, por exemplo
para reproduzir músicas, audiolivros ou podcasts mesmo quando o usuário não tiver o app
aberto, o Player e a MediaSession precisam ser encapsulados em um
serviço em primeiro plano. A Media3 fornece a interface MediaSessionService para essa finalidade.
Como implementar um MediaSessionService
Crie uma classe que estenda MediaSessionService e instancie seu
MediaSession no método de ciclo de vida onCreate().
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
No manifesto, adicione a classe Service com um filtro de intent MediaSessionService e solicite a permissão FOREGROUND_SERVICE para executar um serviço em primeiro plano:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Por fim, na classe criada, substitua o método onGetSession() para controlar o acesso do cliente à sessão de mídia. Retorne uma MediaSession para aceitar a solicitação de conexão ou retorne null para rejeitar a solicitação.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Como se conectar à interface
Agora que a sessão de mídia está em um Service separado da Activity ou Fragment em que a interface do player reside, você pode usar um MediaController para vinculá-los. No método onStart() da Activity ou Fragment com sua interface, crie um SessionToken para sua MediaSession e use o SessionToken para criar um MediaController. A criação de um MediaController acontece de forma assíncrona.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController implementa a interface Player. Portanto, você pode usar os mesmos métodos, como play() e pause(), para controlar a reprodução. Semelhante a outros
componentes, lembre-se de liberar o MediaController quando ele não for mais
necessário, como o método de ciclo de vida onStop() de uma Activity, chamando
MediaController.releaseFuture().
Como publicar uma notificação
Os serviços em primeiro plano precisam publicar uma notificação enquanto estiverem ativos. Um
MediaSessionService vai criar automaticamente uma
MediaStyle notificação para
você na forma de uma MediaNotification.
Para fornecer uma notificação personalizada, crie um
MediaNotification.Provider
com DefaultMediaNotificationProvider.Builder
ou criando uma implementação personalizada da interface do provedor. Adicione seu
provedor ao seu MediaSession com
setMediaNotificationProvider.
Como anunciar sua biblioteca de conteúdo
Um MediaLibraryService é criado em um MediaSessionService, permitindo que apps clientes naveguem pelo conteúdo de mídia fornecido pelo seu app. Os apps clientes implementam um
MediaBrowser para interagir
com seu MediaLibraryService.
A implementação de um MediaLibraryService é semelhante à implementação de um
MediaSessionService, exceto que, em onGetSession(), você precisa retornar um
MediaLibrarySession em vez de um MediaSession. Em comparação com um MediaSession.Callback, o MediaLibrarySession.Callback inclui outros métodos que permitem que um cliente do navegador navegue pelo conteúdo oferecido pelo serviço de biblioteca.
Semelhante ao MediaSessionService, declare o MediaLibraryService no manifesto e solicite a permissão FOREGROUND_SERVICE para executar um serviço em primeiro plano:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
O exemplo acima inclui um filtro de intent para o MediaLibraryService e, para compatibilidade com versões anteriores, o MediaBrowserService legado. O filtro de intent adicional permite que apps clientes que usam a API MediaBrowserCompat reconheçam seu Service.
Uma MediaLibrarySession permite disponibilizar sua biblioteca de conteúdo em uma estrutura de árvore, com uma única raiz MediaItem. Cada MediaItem na árvore pode ter qualquer número de nós filhos MediaItem. Você pode disponibilizar uma raiz diferente ou uma árvore diferente com base na solicitação do app cliente. Por exemplo, a árvore retornada a um cliente que procura uma lista de itens de mídia recomendados pode conter apenas a raiz MediaItem e um único nível de nós filhos MediaItem, enquanto a árvore retornada a um app cliente diferente pode representar uma biblioteca de conteúdo mais completa.
Como criar uma MediaLibrarySession
Uma MediaLibrarySession
estende a API MediaSession para adicionar APIs de navegação de conteúdo. Em comparação com o
MediaSession callback,
o MediaLibrarySession callback
adiciona métodos como:
onGetLibraryRoot()para quando um cliente solicita a raizMediaItemde uma árvore de conteúdoonGetChildren()para quando um cliente solicita os filhos de umMediaItemna árvore de conteúdoonGetSearchResult()para quando um cliente solicita resultados de pesquisa da árvore de conteúdo para uma determinada consulta
Os métodos de callback relevantes vão incluir um LibraryParams
objeto com outros indicadores sobre o tipo de árvore de conteúdo em que um app cliente
está interessado.