Visão geral do MediaPlayer

O framework multimídia do Android inclui suporte para reproduzir vários tipos de mídia comuns. Portanto, que você pode integrar facilmente áudio, vídeo e imagens aos seus aplicativos. Você pode reproduzir áudio ou vídeo de arquivos de mídia armazenados nos recursos do seu aplicativo (recursos brutos), de arquivos independentes no sistema de arquivos ou de um fluxo de dados que chega por uma conexão de rede, tudo usando APIs MediaPlayer.

Neste documento, mostramos como usar MediaPlayer para criar um objeto aplicativo que interage com o usuário e o sistema para obter um bom desempenho e uma uma experiência do usuário agradável. Como alternativa, você pode querer usar o ExoPlayer, que é uma ferramenta de código aberto personalizável, biblioteca com suporte a recursos de alto desempenho não disponíveis em MediaPlayer

Observação:só é possível reproduzir os dados de áudio na saída padrão. dispositivo. que atualmente é o alto-falante do dispositivo móvel ou um fone de ouvido Bluetooth. Não é possível tocar o som arquivos no áudio da conversa durante uma chamada.

Noções básicas

As seguintes classes são usadas para reproduzir som e vídeo no framework do Android:

MediaPlayer
Esta classe é a principal API para reprodução de som e vídeo.
AudioManager
Esta classe gerencia fontes e saída de áudio em um dispositivo.

Declarações do manifesto

Antes de iniciar o desenvolvimento no seu aplicativo usando o MediaPlayer, verifique se o manifesto tem as declarações apropriadas para permitir o uso de recursos relacionados.

  • Permissão de Internet: se você estiver usando o MediaPlayer para fazer streaming baseado em rede. conteúdo, seu aplicativo deve solicitar acesso à rede.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Permissão de Wake Lock: se o app do seu player precisar manter a tela. o escurecimento ou a suspensão do processador, ou usa MediaPlayer.setScreenOnWhilePlaying() ou MediaPlayer.setWakeMode(), é necessário solicitar essa permissão.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

Usar a MediaPlayer

Um dos componentes mais importantes do framework de mídia é o MediaPlayer . Um objeto desta classe pode buscar, decodificar e reproduzir áudio e vídeo com configuração mínima. Ela é compatível com várias fontes de mídia diferentes, como:

  • Recursos locais
  • URIs internos, como um que você possa conseguir a partir de um resolvedor de conteúdo
  • URLs externos (streaming)

Para conferir uma lista dos formatos de mídia com suporte no Android, consulte a página Suporte de formatos.

Aqui está um exemplo de como tocar áudio disponível como um recurso bruto local (salvos no arquivo res/raw/):

Kotlin

var mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1)
mediaPlayer.start() // no need to call prepare(); create() does that for you

Java

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

Nesse caso, um valor "bruto" recurso é um arquivo que o sistema não tente analisar de uma maneira específica. No entanto, o conteúdo desse recurso não deve áudio bruto. Deve ser um arquivo de mídia devidamente codificado e formatado dos formatos compatíveis.

Veja como você pode reproduzir a partir de um URI disponível localmente no sistema (recebidos por meio de um resolvedor de conteúdo, por exemplo):

Kotlin

val myUri: Uri = .... // initialize Uri here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, myUri)
    prepare()
    start()
}

Java

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

A reprodução a partir de um URL remoto por streaming HTTP é assim:

Kotlin

val url = "http://........" // your URL here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(url)
    prepare() // might take long! (for buffering, etc)
    start()
}

Java

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

Observação: Se você passar um URL para transmitir um arquivo de mídia on-line, o arquivo deverá ter a capacidade download progressivo.

Atenção:você precisa pegar ou passar IllegalArgumentException e IOException ao usar setDataSource(), porque o arquivo mencionado talvez não exista.

Preparação assíncrona

Usar MediaPlayer pode ser simples em do princípio de privilégio mínimo. No entanto, é importante ter em mente que mais algumas coisas necessário para integrá-lo corretamente a um aplicativo Android típico. Para exemplo, a chamada para prepare() pode levar muito tempo para ser executada, porque pode envolver buscar e decodificar dados de mídia. Então, como acontece com qualquer que pode demorar para ser executado, você nunca o chame do seu linha de execução de interface do aplicativo. Isso fará com que a IU trave até que o método retorne. o que é uma experiência muito ruim para o usuário e pode causar um erro "O app não está respondendo" (ANR, na sigla em inglês). Mesmo que você espera que seu recurso carregue rapidamente, lembre-se de que qualquer coisa que leve mais de um décimo de um segundo para responder na IU causa uma pausa perceptível e fornece ao usuário a impressão de que o aplicativo está lento.

Para evitar travar sua linha de execução de IU, gere outra linha de execução para prepare a MediaPlayer e notifique a linha de execução principal quando terminar. No entanto, embora escreva a lógica da linha de execução por conta própria, esse padrão é tão comum ao usar MediaPlayer que o framework fornece uma maneira conveniente de realizar essa tarefa usando o prepareAsync(). Esse método começa a preparar a mídia em segundo plano e retorna imediatamente. Quando a mídia a preparação do onPrepared() for concluída do MediaPlayer.OnPreparedListener, configurado pela setOnPreparedListener() é chamado.

Gerenciar estados

Outro aspecto de um MediaPlayer que você precisa ter em mente é que é baseado em estado. Ou seja, a MediaPlayer tem um estado interno que você precisa sempre conhecer ao escrever seu código, já que certas 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 pode gerar uma exceção ou causar outros comportamentos indesejáveis.

A documentação A classe MediaPlayer mostra um diagrama de estado completo, que esclarece quais métodos movem a MediaPlayer de um estado para outro. Por exemplo, quando você cria uma nova MediaPlayer, ela fica no estado Inativo. estado. Nesse ponto, você deve inicializá-lo chamando setDataSource(), agora para o estado Initialized. Depois disso, você precisa prepará-los usando o prepare() ou prepareAsync(). Quando o MediaPlayer terminar a preparação, ele vai entrar no estado Prepared (em inglês). o que significa que é possível chamar start() para ele tocar a mídia. Nesse ponto, como ilustrado no diagrama, você pode alternar entre os estados Iniciado, Pausado e PlaybackCompleted chamar métodos como start(), pause() e seekTo(), entre outros. Quando você chame stop(). No entanto, observe que não é possível chamar start() novamente até que você preparar a MediaPlayer novamente.

Sempre mantenha o diagrama de estado ao escrever um código que interaja com uma objeto MediaPlayer, porque chamar os métodos do estado errado é uma causa comum de insetos.

Liberar a MediaPlayer

Um MediaPlayer pode consumir valores os recursos do sistema. Portanto, você sempre deve tomar precauções extras para não segurar uma instância de MediaPlayer por mais tempo que o necessário. Quando você terminar de usá-lo, sempre chame release() para garantir os recursos do sistema alocados a ele são liberados adequadamente. Por exemplo, se você estiver usando um MediaPlayer e sua atividade receber uma chamada para onStop(), você precisa liberar o MediaPlayer, porque faz pouco sentido segurá-la enquanto sua atividade não está interagindo com o usuário (a menos que você esteja reproduzindo mídia em segundo plano, o que será discutido na próxima seção). Quando sua atividade for retomada ou reiniciada, obviamente, será necessário crie uma nova MediaPlayer e prepare-a 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 podem acontecer se você você esqueceu de liberar a MediaPlayer quando a atividade for interrompida, mas crie uma um novo quando a atividade começar novamente. Como você deve saber, quando o usuário altera o orientação da tela (ou altera a configuração do dispositivo de outra forma), o sistema cuida disso reiniciando a atividade (por padrão), então você pode consumir todos os recursos do sistema à medida gira o dispositivo entre os modos retrato e paisagem, porque a cada mudança de orientação, você cria uma nova MediaPlayer que nunca lançamento. Para saber mais sobre reinicializações durante a execução, consulte Gerenciar alterações de configuração.

Talvez você esteja se perguntando o que acontece se quiser continuar jogando "mídia em segundo plano" mesmo quando o usuário sai da atividade, de maneira semelhante como o aplicativo integrado de música se comporta. Nesse caso, você precisa um MediaPlayer controlado por um serviço, como discutidos na próxima seção

Usar o MediaPlayer em um serviço

Se quiser que sua mídia seja reproduzida em segundo plano mesmo quando seu aplicativo não está na tela, ou seja, você quer que ele continue a ser reproduzido enquanto o usuário interagindo com outros aplicativos, é necessário iniciar uma Disponibilizar e controlar o MediaPlayer a partir daí. Você precisa incorporar o a MediaPlayer em um serviço MediaBrowserServiceCompat e têm ele interage MediaBrowserCompat em outra atividade.

Tenha cuidado com essa configuração de cliente/servidor. Há expectativas sobre como um jogador em execução em um serviço em segundo plano interage com o restante do sistema. Se seu aplicativo não atender a essas expectativas, o usuário poderá ter uma experiência ruim. Lida Como criar um app de áudio para saber mais.

Esta seção descreve instruções especiais para gerenciar uma MediaPlayer quando ela é implementada dentro de um serviço.

Executar de forma assíncrona

Em primeiro lugar, como uma Activity, todos funcionam em uma Service é feito em uma única linha de execução por padrão. Na verdade, se você estiver executando uma atividade e um serviço do mesmo aplicativo, eles usar a mesma linha de execução (a "principal") por padrão. Portanto, os serviços precisam processar rapidamente as intents recebidas e nunca realize cálculos demorados ao responder a eles. Se houver trabalho ou chamadas de bloqueio, é necessário realizar essas tarefas de forma assíncrona: outra linha de execução que você mesmo implementou ou usando os diversos recursos do framework para processamento assíncrono.

Por exemplo, ao usar um MediaPlayer da linha de execução principal, chame prepareAsync() em vez prepare() e implemente um MediaPlayer.OnPreparedListener para receber uma notificação quando a preparação for concluída e você puder começar a jogar. Exemplo:

Kotlin

private const val ACTION_PLAY: String = "com.example.action.PLAY"

class MyService: Service(), MediaPlayer.OnPreparedListener {

    private var mMediaPlayer: MediaPlayer? = null

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        ...
        val action: String = intent.action
        when(action) {
            ACTION_PLAY -> {
                mMediaPlayer = ... // initialize it here
                mMediaPlayer?.apply {
                    setOnPreparedListener(this@MyService)
                    prepareAsync() // prepare async to not block main thread
                }

            }
        }
        ...
    }

    /** Called when MediaPlayer is ready */
    override fun onPrepared(mediaPlayer: MediaPlayer) {
        mediaPlayer.start()
    }
}

Java

public class MyService extends Service implements MediaPlayer.OnPreparedListener {
    private static final String ACTION_PLAY = "com.example.action.PLAY";
    MediaPlayer mediaPlayer = null;

    public int onStartCommand(Intent intent, int flags, int startId) {
        ...
        if (intent.getAction().equals(ACTION_PLAY)) {
            mediaPlayer = ... // initialize it here
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.prepareAsync(); // prepare async to not block main thread
        }
    }

    /** Called when MediaPlayer is ready */
    public void onPrepared(MediaPlayer player) {
        player.start();
    }
}

Processar erros assíncronos

Em operações síncronas, os erros normalmente será sinalizado com uma exceção ou um código de erro, mas sempre que você usar recursos, o aplicativo precisa ser notificado de erros adequadamente. No caso de uma MediaPlayer, você pode fazer isso implementando uma MediaPlayer.OnErrorListener e defini-lo na instância MediaPlayer:

Kotlin

class MyService : Service(), MediaPlayer.OnErrorListener {

    private var mediaPlayer: MediaPlayer? = null

    fun initMediaPlayer() {
        // ...initialize the MediaPlayer here...
        mediaPlayer?.setOnErrorListener(this)
    }

    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        // ... react appropriately ...
        // The MediaPlayer has moved to the Error state, must be reset!
    }
}

Java

public class MyService extends Service implements MediaPlayer.OnErrorListener {
    MediaPlayer mediaPlayer;

    public void initMediaPlayer() {
        // ...initialize the MediaPlayer here...
        mediaPlayer.setOnErrorListener(this);
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        // ... react appropriately ...
        // The MediaPlayer has moved to the Error state, must be reset!
    }
}

É importante lembrar que, quando ocorre um erro, a MediaPlayer move para o estado Error (consulte a documentação do classe MediaPlayer para o diagrama de estado completo) Nesse caso, será necessário redefini-la para usá-la novamente.

Usar wake locks

Ao projetar aplicativos que reproduzem mídia em segundo plano, o dispositivo pode entrar no modo de suspensão enquanto o serviço está em execução. Como o sistema Android tenta conservar bateria enquanto o dispositivo está em modo de suspensão, o sistema tenta desligar qualquer dos recursos do celular que são necessário, como a CPU e o hardware Wi-Fi. No entanto, caso seu serviço esteja reproduzindo ou fazendo streaming de música, você deve impedir que o sistema interfira na reprodução.

Para garantir que seu serviço continue a funcionar nessas condições, use "wake locks". Um wake lock é uma maneira de sinalizar sistema de que o aplicativo está usando algum recurso que deveria continuam disponíveis mesmo que o celular esteja ocioso.

Aviso:sempre use os wake locks com moderação e mantenha-os pressionados. somente pelo tempo realmente necessário, pois reduzem significativamente a duração da bateria do dispositivo.

Para garantir que a CPU continue em execução enquanto o MediaPlayer estiver em reprodução, chame o método setWakeMode() ao inicializar o MediaPlayer. Depois disso, o MediaPlayer mantém o bloqueio especificado durante a reprodução e libera o bloqueio quando pausado ou interrompido:

Kotlin

mediaPlayer = MediaPlayer().apply {
    // ... other initialization here ...
    setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK)
}

Java

mediaPlayer = new MediaPlayer();
// ... other initialization here ...
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);

No entanto, o wake lock adquirido nesse exemplo garante apenas que a CPU permaneça ativa. Se você está transmitindo mídia por streaming e estiver usando Wi-Fi, é recomendável manter uma conexão WifiLock como que precisa ser adquirida e liberada manualmente. Então, quando você começar a preparar MediaPlayer pelo URL remoto, crie e adquira o bloqueio de Wi-Fi. Exemplo:

Kotlin

val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiLock: WifiManager.WifiLock =
    wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock")

wifiLock.acquire()

Java

WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
    .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");

wifiLock.acquire();

Quando você pausar ou interromper a mídia ou quando não precisar mais do botão é preciso liberar o bloqueio:

Kotlin

wifiLock.release()

Java

wifiLock.release();

Realizar uma limpeza

Como mencionado anteriormente, um objeto MediaPlayer pode consumir uma quantidade significativa de recursos do sistema, portanto, você deve mantê-lo apenas pelo tempo que precisar e chamar release() quando terminar de usá-lo. É importante para chamar esse método de limpeza explicitamente, em vez de depender da coleta de lixo do sistema, porque pode levar algum tempo até que o coletor de lixo recupere o MediaPlayer. pois é sensível apenas às necessidades de memória e não à falta de outros recursos relacionados à mídia. Portanto, caso esteja usando um serviço, você deve sempre substituir o campo onDestroy() para garantir o lançamento o MediaPlayer:

Kotlin

class MyService : Service() {

    private var mediaPlayer: MediaPlayer? = null
    // ...

    override fun onDestroy() {
        super.onDestroy()
        mediaPlayer?.release()
    }
}

Java

public class MyService extends Service {
   MediaPlayer mediaPlayer;
   // ...

   @Override
   public void onDestroy() {
       super.onDestroy();
       if (mediaPlayer != null) mediaPlayer.release();
   }
}

Procure sempre outras oportunidades para lançar seu MediaPlayer além de liberá-lo ao ser desligado. Por exemplo, se você espera conseguir tocar mídia por um longo período (depois de perder a seleção de áudio, por exemplo); Libere o MediaPlayer atual e crie-o novamente. mais tarde. No(s) dia(s) Por outro lado, caso espere interromper a reprodução apenas por um período muito curto, Segure seu MediaPlayer para evitar a sobrecarga de criá-lo e prepará-lo. de novo.

Gerenciamento de direitos digitais (DRM, na sigla em inglês)

A partir do Android 8.0 (nível 26 da API), o MediaPlayer inclui APIs que oferecer suporte à reprodução de material protegido por DRM. Elas são semelhantes à API de baixo nível fornecida pelo MediaDrm, mas eles operam em um nível superior expor o extrator, drm e objetos criptográficos subjacentes.

Embora a API DRM do MediaPlayer não forneça a funcionalidade completa do MediaDrm, ele oferece suporte aos casos de uso mais comuns. A A implementação atual pode lidar com os seguintes tipos de conteúdo:

  • Arquivos locais de mídia protegidos pelo Widevine
  • Arquivos de mídia remotos/de streaming protegidos pelo Widevine

O snippet de código a seguir demonstra como usar o novo MediaPlayer DRM em uma implementação síncrona simples.

Para gerenciar mídia controlada por DRM, é preciso incluir os novos métodos junto com o fluxo normal de chamadas da MediaPlayer, conforme mostrado abaixo:

Kotlin

mediaPlayer?.apply {
    setDataSource()
    setOnDrmConfigHelper() // optional, for custom configuration
    prepare()
    drmInfo?.also {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }

    // MediaPlayer is now ready to use
    start()
    // ...play/pause/resume...
    stop()
    releaseDrm()
}

Java

setDataSource();
setOnDrmConfigHelper(); // optional, for custom configuration
prepare();
if (getDrmInfo() != null) {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// MediaPlayer is now ready to use
start();
// ...play/pause/resume...
stop();
releaseDrm();

Comece inicializando o objeto MediaPlayer e configurando a origem usando setDataSource(), como de costume. Em seguida, siga estas etapas para usar o DRM:

  1. Se você quiser que seu app execute uma configuração personalizada, defina um interface OnDrmConfigHelper e anexe-a ao player usando setOnDrmConfigHelper().
  2. Chame o método prepare().
  3. Chame o método getDrmInfo(). Se a origem tiver DRM conteúdo, o método retorna um valor não nulo Valor de MediaPlayer.DrmInfo.

Se MediaPlayer.DrmInfo existir:

  1. analise o mapa dos UUIDs disponíveis e escolha um;
  2. prepare a configuração de DRM para a origem atual chamando prepareDrm().
    • Se você criou e registrou uma OnDrmConfigHelper, ele é chamado enquanto prepareDrm() está em execução. Isso permite que você faça a configuração personalizada do DRM antes de abrir a sessão de DRM. O callback é chamado de forma síncrona na linha de execução que chamou prepareDrm(): Para acessar as propriedades do DRM, chamar getDrmPropertyString() e setDrmPropertyString(). Evite realizar operações demoradas.
    • Se o dispositivo ainda não tiver sido provisionado, prepareDrm() também acessa o servidor de provisionamento para provisionar o dispositivo. Isso pode demorar um pouco por um período de tempo variável, dependendo da conectividade da rede.
  3. Para conseguir uma matriz de bytes de solicitação de chave opaca e enviar a um servidor de licença, chame getKeyRequest():
  4. Para informar o mecanismo de DRM sobre a resposta-chave recebida do servidor de licença, chame provideKeyResponse(): O resultado depende do tipo de solicitação de chave:
    • Se a resposta for para uma solicitação de chave off-line, o resultado será um identificador de conjunto de chaves. Você pode usar esse identificador de conjunto de chaves com restoreKeys() para restaurar as chaves para um novo sessão.
    • Se a resposta for para uma solicitação de streaming ou liberação, o resultado será nulo.

Executar prepareDrm() de forma assíncrona

Por padrão, prepareDrm() é executada de forma síncrona, bloqueando até que a preparação seja concluída. No entanto, a primeira preparação do DRM em um novo dispositivo também pode exigir provisionamento, que é tratados internamente pela prepareDrm() e pode levar algum tempo para ser concluído devido à operação de rede envolvida. Você pode evite o bloqueio em prepareDrm() por definindo e configurando um MediaPlayer.OnDrmPreparedListener.

Quando você define um OnDrmPreparedListener, prepareDrm() realiza o provisionamento (se necessário) e a preparação em segundo plano. Quando quando o provisionamento e a preparação forem concluídos, o listener será chamado. Você deve não faça nenhuma suposição sobre a sequência de chamada ou o thread em que o um listener é executado, a menos que ele esteja registrado em uma linha de execução de gerenciador. O listener pode ser chamado antes ou depois prepareDrm() retorna.

Configurar o DRM de forma assíncrona

Você pode inicializar o DRM de forma assíncrona criando e registrando o MediaPlayer.OnDrmInfoListener para preparação de DRM e o MediaPlayer.OnDrmPreparedListener para iniciar o player. Eles trabalham em conjunto prepareAsync(), conforme mostrado abaixo:

Kotlin

setOnPreparedListener()
setOnDrmInfoListener()
setDataSource()
prepareAsync()
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) {
    mediaPlayer.apply {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
override fun onPrepared(mediaPlayer: MediaPlayer) {
    mediaPlayer.start()
}

Java

setOnPreparedListener();
setOnDrmInfoListener();
setDataSource();
prepareAsync();
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
onDrmInfo() {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
onPrepared() {

start();
}

Processar mídia criptografada

A partir do Android 8.0 (nível 26 da API), o MediaPlayer também pode descriptografar Esquema comum de criptografia (CENC, na sigla em inglês) e Mídia criptografada no nível da amostra HLS (MÉTODO=SAMPLE-AES) para os tipos de stream básicos H.264 e AAC. A mídia criptografada de segmento completo (METHOD=AES-128) era compatível anteriormente.

Recuperar mídia de um ContentResolver

Outro recurso que pode ser útil em um aplicativo de player de mídia é a capacidade de recuperar músicas que o usuário tem no dispositivo. Você pode fazer isso consultando ContentResolver para mídia externa:

Kotlin

val resolver: ContentResolver = contentResolver
val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor? = resolver.query(uri, null, null, null, null)
when {
    cursor == null -> {
        // query failed, handle error.
    }
    !cursor.moveToFirst() -> {
        // no media on the device
    }
    else -> {
        val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE)
        val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID)
        do {
            val thisId = cursor.getLong(idColumn)
            val thisTitle = cursor.getString(titleColumn)
            // ...process entry...
        } while (cursor.moveToNext())
    }
}
cursor?.close()

Java

ContentResolver contentResolver = getContentResolver();
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
    // query failed, handle error.
} else if (!cursor.moveToFirst()) {
    // no media on the device
} else {
    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
    do {
       long thisId = cursor.getLong(idColumn);
       String thisTitle = cursor.getString(titleColumn);
       // ...process entry...
    } while (cursor.moveToNext());
}

Para usar isso com MediaPlayer, faça o seguinte:

Kotlin

val id: Long = /* retrieve it from somewhere */
val contentUri: Uri =
    ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id )

mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, contentUri)
}

// ...prepare and start...

Java

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...

Saiba mais

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