Esta seção explica como separar o app de player de mídia em um controlador de mídia (para a IU) e uma sessão de mídia (para o próprio player). Ela descreve duas arquiteturas de app de mídia: um design cliente/servidor que funciona bem para apps de áudio e um design de atividade única para players de vídeo. Mostra também como fazer com que apps de mídia respondam a controles de hardware e cooperem com outros apps que usam o stream de saída de áudio.
O player e a IU
Um app multimídia que reproduz áudio ou vídeo geralmente tem duas partes:
- Um player que usa a mídia digital e a renderiza como vídeo e/ou áudio
- Uma IU com controles de transporte para executar o player e, opcionalmente, exibir o estado do player
No Android, você pode criar seu player a partir do zero ou escolher uma destas opções:
- A classe MediaPlayer fornece a funcionalidade para um player básico, compatível com os formatos de áudio e vídeo e as fontes de dados mais comuns.
- A ExoPlayer é uma biblioteca de código aberto que expõe as APIs de áudio Android mais antigas.
Ela é compatível com recursos de alto desempenho, como o streaming DASH e o HLS, que não estão disponíveis em
MediaPlayer
. Você pode personalizar o código dela para facilitar a adição de novos componentes. A ExoPlayer só pode ser usada com o Android 4.1 ou versões posteriores.
Sessão de mídia e controlador de mídia
Embora as APIs para a IU e o player possam ser arbitrárias, a natureza da interação entre as duas partes é basicamente a mesma para todos os apps do player de mídia. A estrutura do Android define duas classes, uma sessão de mídia e um controlador de mídia, que impõem uma estrutura bem definida para criar um app de player de mídia.
A sessão de mídia e o controlador de mídia se comunicam usando callbacks predefinidos. Eles correspondem às ações padrão do player (reproduzir, pausar, parar etc.), assim como chamadas personalizadas extensíveis que você usa para definir comportamentos especiais exclusivos para o app.
Sessão de mídia
Uma sessão de mídia é responsável por toda a comunicação com o player. Ele oculta a API do player do restante do app. O player só é chamado pela sessão de mídia que o controla.
A sessão mantém uma representação do estado do player (reprodução/pausa) e informações sobre o que está sendo reproduzido. Uma sessão pode receber callbacks de um ou mais controladores de mídia. Isso possibilita que o player seja controlado pela IU do app, bem como por dispositivos complementares que executam o Wear OS e o Android Auto. A lógica que responde aos callbacks precisa ser consistente. A resposta a um callback de MediaSession
precisa ser a mesma, independentemente do app cliente que iniciou o callback.
Controlador de mídia
Um controlador de mídia isola a IU. O código da IU se comunica apenas com o controlador de mídia, não com o player em si. O controlador de mídia converte as ações de controle de transporte em callbacks para a sessão de mídia. Ele também recebe callbacks da sessão de mídia sempre que o estado da sessão muda. Isso fornece um mecanismo para atualizar automaticamente a IU associada. Um controlador de mídia só pode se conectar a uma sessão de mídia por vez.
Quando você usa um controlador de mídia e uma sessão de mídia, é possível implantar diferentes interfaces e/ou players no momento da execução. Você pode alterar a aparência e/ou o desempenho do app de forma independente, dependendo dos recursos do dispositivo em que ele está sendo executado.
Aplicativos de vídeo vs. aplicativos de áudio
Ao reproduzir um vídeo, seus olhos e ouvidos estão ocupados. Ao reproduzir áudio, você está ouvindo, mas também pode trabalhar com um app diferente ao mesmo tempo. Há um design diferente para cada caso de uso.
App de vídeo
Um app de vídeo precisa de uma janela para visualização do conteúdo. Por esse motivo, um app de vídeo geralmente é implementado como uma única atividade do Android. A tela em que o vídeo aparece faz parte da atividade.
App de áudio
Um player de áudio nem sempre precisa ter uma IU visível. Quando ele começa a reproduzir áudio, o player pode ser executado como uma tarefa em segundo plano. O usuário pode alternar para outro app e trabalhar enquanto continua a ouvir.
Para implementar esse design no Android, você pode criar um app de áudio usando dois componentes: uma atividade para a IU e um serviço para o player. Se o usuário mudar para outro app, o serviço poderá ser executado em segundo plano. Ao fatorar as duas partes de um app de áudio em componentes separados, cada um pode ser executado de forma mais eficiente por conta própria. Uma IU geralmente tem curta duração em comparação com um player, que pode ser executado por muito tempo sem uma IU.
A Biblioteca de Suporte fornece duas classes para implementar essa abordagem cliente/servidor: MediaBrowserService
e MediaBrowser
. O componente de serviço é implementado como uma subclasse de MediaBrowserService
que contém a sessão de mídia e o player. A atividade com a IU e o controlador de mídia precisam incluir um MediaBrowser
, que se comunica com o MediaBrowserService
.
O uso de MediaBrowserService
permite que dispositivos complementares (como o Android Auto e Wear) descubram o app, conectem-se a ele, procurem conteúdo e controlem a reprodução com mais facilidade e sem acessar a atividade da IU do app. Na verdade, pode haver vários app conectados simultaneamente ao mesmo MediaBrowserService
; cada app com o próprio MediaController
. Um app que oferece uma MediaBrowserService
precisa ser capaz de lidar com várias conexões simultâneas.
Aplicativos de mídia e a infraestrutura de áudio do Android
Um app de mídia bem elaborado precisa funcionar bem junto com outros apps que reproduzem áudio. Ele precisa estar preparado para compartilhar o smartphone e colaborar com outros apps no dispositivo que usam áudio. Ele também precisa responder aos controles de hardware no dispositivo.
Todo esse comportamento é descrito em Como gerenciar alterações na saída de áudio.
A biblioteca media-compat
A biblioteca media-compat contém classes úteis para criar apps que reproduzem áudio e vídeo. Essas classes são compatíveis com dispositivos que executam o Android 2.3 (API de nível 9) e versões posteriores. Elas também funcionam com outros recursos para criar uma experiência familiar e confortável com o Android.
A implementação recomendada de sessões de mídia e controladores de mídia são as classes MediaSessionCompat
e MediaControllerCompat
, que são definidas na Biblioteca de Suporte media-compat. Elas substituem versões anteriores das classes MediaSession
e MediaController
que foram introduzidas no Android 5.0 (API de nível 21). As classes compat oferecem a mesma funcionalidade, mas facilitam o desenvolvimento do app, porque você só precisa gravar em uma API. A biblioteca cuida da compatibilidade com versões anteriores ao converter métodos de sessão de mídia nos métodos equivalentes em versões de plataforma mais antigas, quando disponíveis.
Se você já tem um app em funcionamento que esteja usando as classes mais antigas, recomendamos a atualização para as classes compat. Ao usar as versões compatíveis, você pode remover todas as chamadas para registerMediaButtonReceiver()
e quaisquer métodos de RemoteControlClient
.
Medir o desempenho
No Android 8.0 (API de nível 26) e em versões posteriores, o método getMetrics()
está disponível para algumas classes de mídia. Ele retorna um objeto PersistableBundle
contendo informações de configuração e desempenho, expressas como um mapa de atributos e valores.
O método getMetrics()
é definido para estas classes de mídia:
MediaPlayer.getMetrics()
MediaRecorder.getMetrics()
MediaCodec.getMetrics()
MediaExtractor.getMetrics()
As métricas são coletadas separadamente para cada instância e permanecem durante a vida útil dela. Se nenhuma métrica estiver disponível, o método retornará nulo. As métricas reais retornadas dependem da classe.