Gerenciar o estado e os recursos do MediaPlayer

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

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

  • Recursos: ao fazer 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 deles.

Gerenciar estado

MediaPlayer é baseado em estado. Ou seja, ele tem um estado interno que você precisa saber sempre ao escrever seu código, porque 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 o MediaPlayer de um estado para outro. Exemplo:

  • Quando você cria uma nova MediaPlayer, ela está no estado inativo.
  • Para inicializar, chame setDataSource(), que muda para o estado Initialized.
  • Ela é preparada usando o método prepare() ou prepareAsync().
  • Quando a preparação da MediaPlayer é concluída, a classe entra no estado Prepared, 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(), não é possível chamar start() novamente até preparar a MediaPlayer novamente.

Sempre considere 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, sempre tome precauções extras para garantir que você não esteja retendo uma instância de MediaPlayer por mais tempo que o necessário. Ao terminar, sempre chame release() para garantir que todos os recursos do sistema alocados a ele sejam liberados corretamente.

Por exemplo, se você estiver usando um MediaPlayer e sua atividade receber uma chamada para onStop(), será necessário liberar o MediaPlayer, porque não faz sentido mantê-lo enquanto a atividade não interage 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 muda a configuração do dispositivo de outra forma), o sistema reinicia a atividade por padrão. Você pode consumir rapidamente todos os recursos do sistema à medida que o usuário gira o dispositivo para frente e para trás entre retrato e paisagem, porque em cada mudança de orientação, você cria um novo MediaPlayer que nunca é liberado.

Para mais informações sobre reinicializações durante a execução, consulte Como lidar com mudanças de execuçã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 a reprodução de mídia no seu app. Saiba mais.

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