Gerenciar o estado e os recursos do MediaPlayer

Este documento aborda duas áreas com possíveis problemas.

  • Estado. Com a `MediaPlayer`, algumas operações são válidas apenas em estados específicos. Operações incorretas podem causar exceções ou comportamentos inesperados.

  • Recursos : quando você faz mudanças de configuração, como a rotação da tela, é necessário liberar um objeto MediaPlayer para liberar recursos do sistema e evitar o esgotamento de recursos.

Gerenciar estado

MediaPlayer é baseada em estado. Ou seja, ela tem um estado interno que você precisa levar sempre em consideração ao escrever seu código, já que determinadas operações são válidas apenas quando o player está em estados específicos. Se você executar uma operação no estado errado, o sistema poderá gerar uma exceção ou causar outros comportamentos indesejados.

O diagrama de estado na documentação da classe MediaPlayer esclarece quais métodos movem a MediaPlayer de um estado para outro. Exemplo:

  • Quando você cria uma nova MediaPlayer, ela está no estado Idle (inativo).
  • Você a inicializa chamandosetDataSource(), que a muda para o estado Initialized (inicializado).
  • Você a prepara usando o método prepare() ou prepareAsync().
  • Quando a preparação da MediaPlayer é concluída, a classe entra no estado Prepared (preparado), o que significa que você pode chamar start() para abrir a mídia.

Nesse ponto, como o diagrama ilustra, você pode alternar entre os estados Started, Paused e PlaybackCompleted chamando métodos como start(), pause() e seekTo(), entre outros.

No entanto, ao chamar stop(), observe que não é possível chamar start() novamente até preparar a MediaPlayer mais uma vez.

Lembre-se sempre de o diagrama de estado ao escrever um código que interage com um objeto MediaPlayer, já que chamar os métodos do estado errado é uma causa comum de bugs.

Liberar a MediaPlayer

Uma MediaPlayer pode consumir recursos valiosos do sistema. Portanto, você sempre deve tomar precauções extras para garantir que não esteja retendo uma instância MediaPlayer por mais tempo que o necessário. Ao terminar, chame sempre release() para garantir que os recursos do sistema alocados para ele sejam liberados de forma correta.

Por exemplo, se você estiver usando um MediaPlayer e sua atividade receber uma chamada para onStop(), libere o MediaPlayer, porque não faz sentido mantê-lo enquanto sua atividade não está interagindo com o usuário (a menos que você esteja reproduzindo mídia em segundo plano, o que é discutido na próxima seção).

Evidentemente, quando sua atividade for retomada ou reiniciada, será necessário criar uma nova MediaPlayer e prepará-la novamente antes de retomar a reprodução.

Veja como liberar e anular sua MediaPlayer:

Kotlin

mediaPlayer?.release()
mediaPlayer = null

Java

mediaPlayer.release();
mediaPlayer = null;

Como exemplo, considere os problemas que surgem se você se esquecer de liberar a MediaPlayer quando a atividade for interrompida, mas criar uma nova quando a atividade começar novamente. Quando o usuário muda a orientação da tela (ou a configuração do dispositivo de alguma outra maneira), o sistema reinicia a atividade por padrão. Você pode consumir rapidamente todos os recursos do sistema enquanto o usuário alterna o dispositivo entre retrato e paisagem, uma vez que, a cada mudança de orientação, você cria uma nova MediaPlayer que nunca é liberada.

Para saber mais sobre reinicializações durante a execução, consulte Gerenciar mudanças de configuração.

Você pode estar se perguntando o que acontecerá se quiser continuar reproduzindo "mídia em segundo plano", mesmo depois que o usuário sair da atividade, da mesma forma que o aplicativo integrado de música faz. Nesse caso, você precisa de uma MediaPlayer controlada por um serviço, como discutido na próxima seção.

Saiba mais

O Jetpack Media3 é a solução recomendada para reprodução de mídia no seu app. Saiba mais.

Essas páginas abrangem tópicos relacionados à gravação, ao armazenamento e à reprodução de áudio e vídeo: