Como usar uma sessão de mídia

Uma sessão de mídia convive com o player que a gerencia. Crie e inicialize uma sessão de mídia no método onCreate() da atividade ou serviço que possui a sessão de mídia e o player associado.

Inicializar a sessão de mídia

Uma sessão de mídia recém-criada não tem recursos. Inicialize a sessão executando estas etapas:

  • Defina sinalizações para que a sessão de mídia receba callbacks de controladores de mídia e botões de mídia.
  • Crie e inicialize uma instância de PlaybackStateCompat e a atribua à sessão. O estado de reprodução muda durante a sessão, por isso recomendamos o cache de PlaybackStateCompat.Builder para reutilização.
  • Crie uma instância de MediaSessionCompat.Callback e a atribua à sessão. Veja abaixo mais informações sobre callbacks.

Crie e inicialize uma sessão de mídia no método onCreate() da atividade ou serviço que detém a sessão.

Para que botões de mídia funcionem quando o app for recém inicializado (ou interrompido), o PlaybackState precisa conter uma ação de reprodução correspondente ao intent que o botão de mídia envia. É por isso que ACTION_PLAY é atribuído ao estado da sessão durante a inicialização. Para saber mais, consulte a seção Como responder aos botões de mídia.

Manter o estado de reprodução e os metadados

Há duas classes que representam o estado de uma sessão de mídia.

A classe PlaybackStateCompat descreve o estado operacional atual do player. Isso inclui:

  • O estado de transporte, isto é, se o player está em reprodução/pausado/em buffer etc. Veja getState().
  • Um código de erro e uma mensagem de erro opcional, quando aplicável. Veja getErrorCode() e leia Estados e erros, abaixo.
  • A posição do player
  • As ações válidas do controlador que podem ser processadas no estado atual

A classe MediaMetadataCompat descreve o material que está sendo reproduzido:

  • O nome do artista, álbum e faixa
  • A duração da faixa
  • Arte do álbum para exibição na tela de bloqueio. A imagem é um bitmap com tamanho máximo de 320 x 320 dp. Se for maior, ela será reduzida.
  • Uma instância de ContentUris que aponta para uma versão maior da obra de arte

O estado do player e os metadados podem mudar durante a vida útil de uma sessão de mídia. Toda vez que o estado ou os metadados mudarem, você precisará usar o builder correspondente para cada classe, PlaybackStateCompat.Builder() ou MediaMetadataCompat.Builder() e, em seguida, transmitir a nova instância para a sessão de mídia chamando setPlaybackState() ou setMetaData(). Para reduzir o consumo geral de memória em função dessas operações frequentes, uma boa sugestão é criar os builders uma vez e reutilizá-los ao longo da vida da sessão.

Estados e erros

Observe que PlaybackState é um objeto que contém valores separados para o estado de reprodução da sessão (getState()) e, quando necessário, um código de erro associado (getErrorCode()). Os erros podem ser fatais ou não fatais:

Sempre que a reprodução for interrompida, você precisará gerar um erro fatal: defina o estado de transporte como STATE_ERROR e especifique um erro associado a setErrorMessage(int, CharSequence). Enquanto a reprodução estiver bloqueada pelo erro, o PlaybackState precisará continuar a informar STATE_ERROR e o erro.

Um erro não fatal ocorre quando o app não consegue processar uma solicitação, mas pode continuar a reprodução: o transporte permanece em um estado “normal” (como STATE_PLAYING ), mas o PlaybackState contém um código de erro. Por exemplo, se a última música estiver sendo reproduzida, e o usuário solicitar um pulo para a próxima música, a reprodução poderá continuar, mas você precisará criar um novo PlaybackState com o código de erro ERROR_CODE_END_OF_QUEUE e, em seguida, chamar setPlaybackState(). Os controladores de mídia anexados à sessão receberão o callback onPlaybackStateChanged() e explicarão ao usuário o que aconteceu. Um erro não fatal precisar ser informado apenas uma vez, no momento em que ocorre. Na próxima vez que a sessão atualizar o PlaybackState, não defina o mesmo erro não fatal novamente, a menos que ele tenha ocorrido em resposta a uma nova solicitação.

Telas de bloqueio de sessão de mídia

A partir do Android 4.0 (API de nível 14), o sistema pode acessar o estado de reprodução de uma sessão de mídia e os metadados. É assim que a tela de bloqueio pode exibir controles de mídia e obras de arte. O comportamento varia de acordo com a versão do Android.

Arte do álbum

No Android 4.0 (API de nível 14) e versões posteriores, o plano de fundo da tela de bloqueio exibe a capa do álbum, mas somente se os metadados da sessão de mídia incluem um bitmap em segundo plano.

Controles de transporte

Do Android 4.0 (API de nível 14) até o Android 4.4 (API de nível 19), quando uma sessão de mídia está ativa e os metadados da sessão incluem um bitmap em segundo plano, a tela de bloqueio exibe automaticamente os controles de transporte.

No Android 5.0 (API de nível 21) ou versão superior, o sistema não fornece controles de transporte na tela de bloqueio. Em vez disso, use uma notificação MediaStyle para exibir os controles de transporte.

Adicionar ações personalizadas

Você pode adicionar ações personalizadas com addCustomAction(). Por exemplo, para adicionar um controle para implementar uma ação de aprovação:

Kotlin

    stateBuilder.addCustomAction(
            PlaybackStateCompat.CustomAction.Builder(
                    CUSTOM_ACTION_THUMBS_UP,
                    resources.getString(R.string.thumbs_up),
                    thumbsUpIcon
            ).run {
                setExtras(customActionExtras)
                build()
            }
    )
    

Java

    stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
        CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon)
        .setExtras(customActionExtras)
        .build());
    

Consulte Universal Music Player para ver um exemplo completo.

Você responde à ação com onCustomAction().

Kotlin

    override fun onCustomAction(action: String, extras: Bundle?) {
        when(action) {
            CUSTOM_ACTION_THUMBS_UP -> {
                ...
            }
        }
    }
    

Java

    @Override
    public void onCustomAction(@NonNull String action, Bundle extras) {
        if (CUSTOM_ACTION_THUMBS_UP.equals(action)) {
            ...
        }
    }
    

Consulte também Universal Music Player (link em inglês).

Callbacks de sessão de mídia

Os principais métodos de callback de sessão de mídia são onPlay(), onPause() e onStop(). É aqui que você adiciona o código que controla o player.

Como você instancia e define o callback da sessão no tempo de execução (em onCreate()), o app pode definir callbacks alternativos que usam players diferentes e escolher a combinação apropriada de callback/player de acordo com o dispositivo e/ou nível do sistema. Você pode mudar o player sem mudar o restante do app. Por exemplo, você pode usar ExoPlayer ao executar no Android 4.1 (API de nível 16) ou versões posteriores e usar MediaPlayer em sistemas anteriores.

Além de controlar o player e gerenciar as transições de estado da sessão de mídia, os callbacks também ativam e desativam recursos do app e controlam a interação com outros apps e o hardware do dispositivo. Consulte Como controlar a saída de áudio.

A implementação dos métodos de callback de sessão de mídia depende da estrutura do app. Consulte as páginas separadas que descrevem como usar callbacks em apps de áudio e apps de vídeo, descrevem como implementar os callbacks para cada tipo de app.