Esta seção explica como separar um app de player de mídia em um controlador de mídia (para a interface) e uma sessão de mídia (para o player real). 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. Ele também mostra como fazer com que os apps de mídia respondam aos 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 mídias digitais e as renderiza como vídeo e/ou áudio
- Uma interface com controles de transporte para executar o player e, opcionalmente, mostrar o estado dele.
No Android, você pode criar seu próprio jogador do zero ou escolher entre estas opções:
- A classe MediaPlayer fornece a funcionalidade básica para um player básico que oferece suporte aos formatos de áudio e vídeo e fontes de dados mais comuns.
- O ExoPlayer
é uma biblioteca de código aberto criada com base em componentes de framework de mídia de nível
inferior, como
MediaCodec
eAudioTrack
. O ExoPlayer oferece suporte a recursos de alto desempenho, como o DASH, que não estão disponíveis emMediaPlayer
. Você pode personalizar o código do ExoPlayer, facilitando a adição de novos componentes. O ExoPlayer só pode ser usado com a versão 4.1 ou mais recente do Android.
Sessão de mídia e controlador de mídia
Embora as APIs para a interface e o player possam ser arbitrárias, a natureza da interação entre as duas partes é basicamente a mesma para todos os apps de player de mídia. O framework 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 que correspondem às ações padrão do player (reproduzir, pausar, interromper etc.), bem como chamadas personalizadas extensíveis que você usa para definir comportamentos especiais exclusivos do seu app.
Sessão de mídia
Uma sessão de mídia é responsável por toda a comunicação com o player. Ela oculta a API do player do restante do app. O player só é chamado na sessão de mídia que o controla.
A sessão mantém uma representação do estado do player (em reprodução/pausado)
e informações sobre o que está sendo reproduzido. Uma sessão pode receber
callbacks de um
ou mais controladores de mídia. Isso permite que o player seja
controlado pela interface do app e 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 MediaSession
precisa ser a mesma, independente do app cliente que iniciou o callback.
Controle 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 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 proporciona um mecanismo para atualizar automaticamente a interface associada. Um controlador de mídia só pode se conectar a uma sessão de mídia por vez.
Ao usar 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 mudar 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 tocar áudio, você está ouvindo, mas também pode trabalhar com outro app 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çar a reproduzir áudio, o player poderá ser executado como uma tarefa em segundo plano. O usuário pode alternar para outro app e trabalhar enquanto continua ouvindo.
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 alternar 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 uma pode ser executada com mais eficiência por conta própria. Uma interface geralmente tem curta duração em comparação com um jogador, que pode ser executado por muito tempo sem uma interface.
A Biblioteca de Suporte oferece duas classes para implementar essa abordagem de 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
reprodutor. A atividade com a interface e o controlador de mídia precisam incluir um
MediaBrowser
, que se comunica com o MediaBrowserService
.
O uso de MediaBrowserService
facilita que dispositivos complementares (como o Android
Auto e o Wear) descubram seu app, se conectem a ele, procurem conteúdo e
controlem a reprodução, sem precisar acessar a atividade da interface do app. Na verdade, pode haver vários apps conectados ao mesmo MediaBrowserService
ao mesmo
tempo, cada um com o próprio MediaController
. Um app que oferece um
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úsica bem projetado precisa funcionar bem com outros apps que reproduzem áudio. Ele precisa estar preparado para compartilhar o smartphone e cooperar com outros apps que usem áudio no dispositivo. 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 mais recentes. Elas também funcionam com outros recursos do Android para criar uma experiência confortável e familiar.
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
introduzidas no Android 5.0 (nível 21 da API). As classes de compatibilidade 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 convertendo métodos de sessão de mídia nos métodos equivalentes em
versões mais antigas da plataforma, quando disponíveis.
Se você já tem um app em funcionamento que usa as classes mais antigas, recomendamos
atualizar para as classes de compatibilidade. Ao usar as versões compatíveis, você pode remover
todas as chamadas para registerMediaButtonReceiver()
e quaisquer métodos de RemoteControlClient
.
Como medir a performance
No Android 8.0 (API de nível 26) e versões mais recentes, o método getMetrics()
está disponível
para algumas classes de mídia. Ela retorna um objeto PersistableBundle
contendo informações de
configuração e desempenho, expressos 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 o ciclo de vida da instância. Se nenhuma métrica estiver disponível, o método retornará nulo. As métricas reais retornadas dependem da classe.