O framework multimídia do Android inclui suporte à reprodução de vários tipos de mídia comuns. Assim, você pode integrar facilmente áudio, vídeo e imagens aos seus apps. É possível reproduzir áudio ou
vídeo de arquivos de mídia armazenados nos recursos do 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 isso usando APIs MediaPlayer
.
Este documento mostra como usar o
MediaPlayer
para criar um aplicativo de reprodução
de mídia que interage com o usuário e o sistema para conseguir um bom desempenho e uma
experiência agradável. Como alternativa, você pode
usar a ExoPlayer, uma biblioteca de código aberto personalizável
com suporte a recursos de alto desempenho não disponíveis em MediaPlayer
Observação:só é possível tocar os dados de áudio para o dispositivo de saída padrão. que atualmente é o alto-falante do dispositivo móvel ou um fone de ouvido Bluetooth. Não é possível reproduzir arquivos de som 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 adequadas para permitir o uso de recursos relacionados.
- Permissão de Internet: se você estiver usando o MediaPlayer para fazer streaming de conteúdo
baseado em rede, seu aplicativo precisará solicitar acesso à rede.
<uses-permission android:name="android.permission.INTERNET" />
- Permissão de wake lock: se o aplicativo do player precisar impedir que a tela
esmaeça ou o processador entre em suspensão ou usar os métodos
MediaPlayer.setScreenOnWhilePlaying()
ouMediaPlayer.setWakeMode()
, será 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 é a
classe
MediaPlayer
. Um objeto dessa classe pode buscar, decodificar e reproduzir áudio e vídeo
com uma 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 ver uma lista de formatos de mídia com suporte no Android, consulte a página Formatos de mídia compatíveis.
Confira um exemplo
de como reproduzir o áudio disponível como um recurso bruto local (salvo no diretório
res/raw/
do aplicativo):
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 recurso "bruto" é um arquivo que o sistema não tenta analisar de nenhuma maneira específica. No entanto, o conteúdo desse recurso não pode ser áudio bruto. Ele precisa ser um arquivo de mídia codificado e formatado corretamente em um dos formatos compatíveis.
Veja como você pode reproduzir a partir de um URI disponível localmente no sistema (recebido por 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ê estiver transmitindo um URL para fazer streaming de um arquivo de mídia on-line, o arquivo precisa ter a capacidade de download progressivo.
Cuidado:é necessário capturar ou transmitir
IllegalArgumentException
e IOException
ao usar
setDataSource()
, porque
o arquivo que você está referenciando pode não existir.
Preparação assíncrona
O uso de MediaPlayer
pode ser simples em
princípio. No entanto, é importante ter em mente que mais algumas coisas são necessárias para integrá-lo corretamente a um app Android típico. Por
exemplo, a chamada para prepare()
pode
levar muito tempo para ser executada, porque
envolve a busca e a decodificação de dados de mídia. Portanto, como acontece com qualquer
método de execução muito demorado, nunca o chame na
linha de execução de IU do app. Isso faz com que a interface trave até que o método seja retornado,
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ê espere que o recurso seja carregado rapidamente, lembre-se de que qualquer ação que leve mais de um décimo
de segundo para responder na interface causa uma pausa perceptível e dá
ao usuário a impressão de que o aplicativo está lento.
Para evitar a suspensão da linha de execução de IU, gere outra linha de execução para
preparar a MediaPlayer
e notifique a linha principal quando terminar. No entanto, embora
você possa criar a lógica de 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
método prepareAsync()
. Esse método
começa a preparar a mídia em segundo plano e é retornado imediatamente. Quando a preparação
da mídia é concluída, o método onPrepared()
da MediaPlayer.OnPreparedListener
, configurado por
setOnPreparedListener()
, é chamado.
Gerenciar estados
Outro aspecto de uma MediaPlayer
que você precisa ter em mente é
que ela é baseada em estado. Ou seja, a MediaPlayer
tem um estado interno
que você precisa sempre conhecer ao escrever o código, porque algumas operações
só são válidas 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 indesejáveis.
A documentação na
classe MediaPlayer
mostra um diagrama de estado completo,
que esclarece quais métodos movem MediaPlayer
de um estado para outro.
Por exemplo, quando você cria um novo MediaPlayer
, ele está no estado
Inativo. Nesse ponto, inicialize-o chamando
setDataSource()
e trazendo-o
para o estado Initialized (inicializado). Depois disso, é necessário prepará-lo usando o método
prepare()
ou
prepareAsync()
. Quando
o MediaPlayer
é concluído, ele entra no estado Prepared (preparado),
o que significa que você pode chamar start()
para que ele reproduza a mídia. Nesse ponto, como ilustra o diagrama, é possível alternar entre os estados Started, Pause e PlaybackConcluído 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 o MediaPlayer
de novo.
Sempre tenha em mente o diagrama de estado
ao escrever um código que interage com um objeto
MediaPlayer
, porque chamar os métodos do estado errado é uma
causa comum de bugs.
Liberar a MediaPlayer
Um MediaPlayer
pode consumir recursos valiosos
do sistema.
Portanto, sempre tome precauções extras para não ficar
atravando uma instância MediaPlayer
por mais tempo que o necessário. Quando terminar, chame sempre release()
para garantir que todos os recursos do sistema alocados para ele sejam liberados corretamente. Por exemplo, se você estiver
usando um MediaPlayer
e sua atividade receber uma chamada para onStop()
, será necessário liberar a MediaPlayer
,
porque faz
pouco sentido mantê-la enquanto a atividade não estiver 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.
Obviamente, quando a atividade for retomada ou reiniciada, será necessário
criar um novo MediaPlayer
e prepará-lo novamente antes de retomar a reprodução.
Veja como liberar e anular sua MediaPlayer
:
Kotlin
mediaPlayer?.release() mediaPlayer = null
Java
mediaPlayer.release(); mediaPlayer = null;
Por exemplo, considere os problemas que podem acontecer se você
se esquecer de liberar a MediaPlayer
quando a atividade for interrompida, mas criar uma
nova quando a atividade for reiniciada. Como você deve saber, quando o usuário muda a
orientação da tela (ou a configuração do dispositivo de outra forma),
o sistema reinicia a atividade (por padrão). Assim, é possível consumir
rapidamente todos os recursos do sistema à medida que o usuário
gira o dispositivo entre retrato e paisagem, porque a cada
mudança de orientação, você cria uma MediaPlayer
que nunca
é liberada. Para saber mais sobre reinicializações durante a execução, consulte Gerenciar alterações de configuração.
Você pode estar se perguntando o que acontecerá se quiser continuar reproduzindo
"mídia em segundo plano" mesmo quando o usuário sair da atividade, da mesma forma
que o aplicativo de música integrado se comporta. Nesse caso, você precisa de
um MediaPlayer
controlado por um serviço, conforme
discutido na próxima seção
Usar o MediaPlayer em um serviço
Se você quiser que sua mídia seja reproduzida em segundo plano mesmo quando o aplicativo
não estiver na tela, ou seja, se quiser que ela continue a ser reproduzida enquanto o usuário interage
com outros aplicativos, inicie um
serviço e controle a
instância MediaPlayer
nele.
Você precisa incorporar o
MediaPlayer a um serviço de MediaBrowserServiceCompat
e fazer
com que ele interaja com um
MediaBrowserCompat
em outra atividade.
Tenha cuidado com essa configuração de cliente/servidor. Há expectativas sobre como um player em execução em um serviço em segundo plano interage com o restante do sistema. Se o aplicativo não atender a essas expectativas, o usuário poderá ter uma experiência ruim. Leia Como criar um app de áudio para ver todos os detalhes.
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 em uma Activity
, todo o trabalho 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ão a mesma linha de execução (a "linha de execução principal") por padrão. Portanto, os serviços precisam
processar intents recebidas rapidamente
e nunca realizar cálculos longos ao responder a elas. Se algum trabalho pesado
ou chamadas de bloqueio for esperado, execute essas tarefas de forma assíncrona: em
outra linha de execução implementada por você ou usando os vários recursos do framework
para processamento assíncrono.
Por exemplo, ao usar um MediaPlayer
da linha de execução principal,
chame prepareAsync()
em vez de
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.
Por 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 seriam sinalizados com uma exceção ou um código de erro, mas sempre que você usar recursos assíncronos, verifique se o aplicativo está notificado sobre erros adequadamente. No caso de um MediaPlayer
,
é possível fazer isso implementando um
MediaPlayer.OnErrorListener
e
configurando-o na sua instância de 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, o MediaPlayer
muda para o estado Erro. Consulte a documentação da
classe MediaPlayer
para ver o diagrama de estado completo.
Você precisa redefini-lo antes de usá-lo 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 economizar bateria enquanto o dispositivo está em suspensão, ele tenta desligar todos os recursos do smartphone que não são necessários, incluindo a CPU e o hardware Wi-Fi. No entanto, se o serviço estiver tocando ou fazendo streaming de música, é recomendado evitar que o sistema interfira na reprodução.
Para garantir que o serviço continue sendo executado nessas condições, você precisa usar "wake locks". Um wake lock é uma maneira de sinalizar ao sistema que o app está usando algum recurso que precisa permanecer disponível, mesmo que o smartphone esteja inativo.
Aviso:sempre use wake locks com moderação e mantenha-os apenas pelo tempo realmente necessário, porque eles reduzem significativamente a duração da bateria do dispositivo.
Para garantir que a CPU continue em execução enquanto o MediaPlayer
é
reproduzido, chame o método setWakeMode()
ao inicializar o MediaPlayer
. Depois disso,
o MediaPlayer
mantém o bloqueio especificado durante a reprodução e o libera 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ê estiver fazendo streaming de mídia pela
rede e usando o Wi-Fi, provavelmente também vai precisar manter um
WifiLock
, que precisa ser adquirido e liberado manualmente. Portanto, ao começar a preparar o
MediaPlayer
com o URL remoto, crie e adquira o bloqueio de Wi-Fi.
Por 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();
Ao pausar ou interromper a mídia ou quando não precisar mais da rede, libere 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, mantenha-o apenas pelo tempo necessário e chame
release()
quando terminar de usá-lo. É importante
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
,
já que ele é sensível apenas às necessidades de memória, e não à escassez de outros recursos relacionados à mídia.
Portanto, no caso de usar um serviço, sempre substitua o método
onDestroy()
para garantir que você esteja liberando
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 liberar a MediaPlayer
, além de fazer a liberação durante o desligamento. Por exemplo, se você acha que não
poderá tocar mídia por um longo período (depois de perder a seleção de áudio, por exemplo),
libere a MediaPlayer
existente e a crie novamente
mais tarde. Por
outro lado, se você pretende interromper a reprodução por um período muito curto, provavelmente
mantenha a MediaPlayer
para evitar a sobrecarga de criar e prepará-la
novamente.
Gerenciamento de direitos digitais (DRM, na sigla em inglês)
No Android 8.0 (nível 26 da API) e versões mais recentes, a MediaPlayer
inclui APIs que
oferecem suporte para a reprodução de material protegido por DRM. Elas são semelhantes à API de baixo nível fornecida por
MediaDrm
, mas operam em um nível superior e não
expõem o extrator, o drm e os objetos criptográficos subjacentes.
Embora a API MediaPlayer DRM não forneça a funcionalidade completa de
MediaDrm
, ela oferece suporte aos casos de uso mais comuns. A
implementação atual pode processar 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 abaixo demonstra como usar os novos métodos DRM MediaPlayer 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 do 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 definindo
a origem usando setDataSource()
,
como de costume. Em seguida, siga estas etapas para usar o DRM:
- Se você quiser que seu app faça uma configuração personalizada, defina uma
interface
OnDrmConfigHelper
e a anexe ao jogador usandosetOnDrmConfigHelper()
. - Chame o método
prepare()
. - Chame o método
getDrmInfo()
. Se a origem tiver conteúdo DRM, o método retornará um valorMediaPlayer.DrmInfo
não nulo.
Se MediaPlayer.DrmInfo
existir:
- analise o mapa dos UUIDs disponíveis e escolha um;
- prepare a configuração de DRM para a origem atual chamando
prepareDrm()
. - Se você criou e registrou um callback
OnDrmConfigHelper
, ele será chamado enquantoprepareDrm()
estiver em execução. Isso permite que você execute a configuração personalizada das propriedades de DRM antes de abrir a sessão correspondente. O callback é chamado de forma síncrona na linha de execução que chamouprepareDrm()
. Para acessar as propriedades de DRM, chamegetDrmPropertyString()
esetDrmPropertyString()
. Evite realizar operações demoradas. - Se o dispositivo ainda não tiver sido provisionado, o
prepareDrm()
também acessará o servidor de provisionamento para provisionar o dispositivo. Isso pode levar um tempo variável, dependendo da conectividade da rede. - Para receber uma matriz de bytes de solicitação de chave opaca a ser enviada a um servidor de licença, chame
getKeyRequest()
. - Para informar o mecanismo de DRM sobre a resposta de 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. É possível usar
esse identificador de conjunto de chaves com
restoreKeys()
para restaurar as chaves a uma nova sessão. - Se a resposta for para uma solicitação de streaming ou liberação, o resultado será nulo.
- Se a resposta for para uma solicitação de chave off-line, o resultado será um identificador de conjunto de chaves. É possível usar
esse identificador de conjunto de chaves com
Executar prepareDrm()
de forma assíncrona
Por padrão, prepareDrm()
é executado de maneira síncrona, bloqueando até que a preparação seja concluída. No entanto, a primeira
preparação de DRM em um novo dispositivo também pode exigir provisionamento, que é
processado internamente pelo
prepareDrm()
e
pode levar algum tempo para ser concluído devido à operação de rede envolvida. Para
evitar o bloqueio em
prepareDrm()
,
defina e configure um MediaPlayer.OnDrmPreparedListener
.
Quando você define um OnDrmPreparedListener
,
o prepareDrm()
realiza o provisionamento (se necessário) e a preparação em segundo plano. Quando o provisionamento e a preparação forem concluídos, o listener será chamado. Não
faça nenhuma suposição sobre a sequência de chamada ou a linha de execução em que o
listener é executado, a menos que o listener esteja registrado com uma linha de execução de gerenciador.
O listener pode ser chamado antes ou depois do retorno de
prepareDrm()
.
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 do DRM e o
MediaPlayer.OnDrmPreparedListener
para iniciar o player.
Elas funcionam em conjunto com
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
No Android 8.0 (nível 26 da API) e versões mais recentes, o MediaPlayer
também pode descriptografar
um esquema de criptografia comum (CENC, na sigla em inglês) e
mídia criptografada no nível de amostra de HLS (METHOD=início teste - AES) para os tipos básicos de fluxo
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 app de player de mídia é a capacidade de
extrair 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.