O framework multimídia do Android inclui compatibilidade com diversos tipos de mídia comuns. Assim, você pode integrar facilmente áudio, vídeo e imagens aos seus aplicativos. É 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 meio de uma conexão de rede, tudo isso com APIs MediaPlayer
.
Este documento mostra como criar um aplicativo de mídia que interage com o usuário e o sistema para ter um bom desempenho e uma experiência de usuário agradável.
Observação: só é possível abrir 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 abrir 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 apropriadas para permitir o uso de recursos relacionados.
- Permissão de Internet: se você estiver usando o MediaPlayer para fazer streaming de conteúdo on-line, seu aplicativo precisará solicitar acesso à rede.
<uses-permission android:name="android.permission.INTERNET" />
- Permissão de wake lock: se seu aplicativo precisar impedir que a tela seja escurecida ou que o processador entre em suspensão, ou se ele usar os métodos
MediaPlayer.setScreenOnWhilePlaying()
ouMediaPlayer.setWakeMode()
, será necessário solicitar esta 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 quantidade mínima de configuração. 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 compatíveis com o Android, consulte a página Formatos de mídia compatíveis.
Veja 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? = 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 deve ser áudio bruto. Ele deve ser um arquivo de mídia corretamente codificado e formatado em um dos formatos compatíveis.
Veja como você pode reproduzir a partir de um URI disponível localmente no sistema (acessado por meio de um resolvedor de conteúdo, por exemplo):
Kotlin
val myUri: Uri = .... // initialize Uri here val mediaPlayer: MediaPlayer? = MediaPlayer().apply { setAudioStreamType(AudioManager.STREAM_MUSIC) setDataSource(applicationContext, myUri) prepare() start() }
Java
Uri myUri = ....; // initialize Uri here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 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? = MediaPlayer().apply { setAudioStreamType(AudioManager.STREAM_MUSIC) setDataSource(url) prepare() // might take long! (for buffering, etc) start() }
Java
String url = "http://........"; // your URL here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(url); mediaPlayer.prepare(); // might take long! (for buffering, etc) mediaPlayer.start();
Observação: se você estiver passando um URL para fazer streaming de um arquivo de mídia on-line, o arquivo precisará fazer o download progressivo.
Cuidado: é necessário pegar ou passar 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
é teoricamente simples. No entanto, é importante lembrar que outros fatores são necessários para integrá-lo corretamente a um aplicativo para Android típico. Por exemplo, a execução da chamada para prepare()
pode ser muito demorada, porque envolve a busca e a decodificação de dados de mídia. Portanto, assim como com qualquer método de execução lenta, nunca o chame na linha de execução de IU do aplicativo. Isso fará a IU ser interrompida até que o método retorne, o que é uma experiência muito desagradável para o usuário e pode gerar 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 de mais de um décimo de segundo na IU causa uma pausa perceptível e dá ao usuário a impressão de que o aplicativo está lento.
Para evitar a interrupção da linha de execução de IU, gere outra linha de execução para preparar o MediaPlayer
e notifique a linha principal quando terminar. No entanto, embora você possa escrever a lógica de linha de execução por conta própria, esse padrão é tão comum no uso de MediaPlayer
que o framework oferece uma maneira conveniente de realizar essa tarefa por meio do método prepareAsync()
. Esse método começa preparando a mídia em segundo plano e é retornado imediatamente. Quando a preparação da mídia é concluída, o método onPrepared()
do MediaPlayer.OnPreparedListener
, configurado até setOnPreparedListener()
, é chamado.
Gerenciar estados
Outro aspecto importante de uma MediaPlayer
é que ela é baseada em estado. Ou seja, a MediaPlayer
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.
A documentação na classe MediaPlayer
mostra um diagrama de estado completo, que esclarece quais métodos movem de um estado para outro.
Por exemplo, quando você cria uma nova MediaPlayer
, ela está no estado Idle (inativo). Nesse ponto, inicialize-a chamando setDataSource()
, trazendo-a para o estado Initialized (inicializado). Depois disso, prepare-a com 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 (iniciado), Paused (pausado) e PlaybackCompleted (reprodução concluída) 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 do 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 adote precauções extras para garantir que você 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 uma MediaPlayer
e sua atividade receber uma chamada para onStop()
, libere a MediaPlayer
, porque não faz sentido mantê-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 é 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 poderiam acontecer se você se esquecesse de liberar a MediaPlayer
quando a atividade fosse interrompida, mas criasse uma nova quando a atividade começasse novamente. Como você deve saber, quando o usuário muda a orientação da tela (ou a configuração do dispositivo de alguma outra maneira), o sistema responde reiniciando a atividade (por padrão). Isso significa que 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 alterações 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.
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, que a reprodução continue enquanto o usuário interage com outros aplicativos, será necessário iniciar um serviço e controlar a instância MediaPlayer
a partir dele.
É necessário incorporar a MediaPlayer em um serviço MediaBrowserServiceCompat
e fazê-la interagir 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 seu aplicativo não atender a essas expectativas, o usuário poderá ter uma experiência negativa. Leia Visão geral para um aplicativo 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 uma Activity
, todo o trabalho em um Service
é feito, por padrão, em uma única linha de execuçã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 principal). Portanto, os serviços precisam processar intents de entrada rapidamente e nunca realizar cálculos demorados durante as respostas. Se algum trabalho pesado ou chamadas de bloqueio forem esperados, será preciso realizar essas tarefas de forma assíncrona: de outra linha de execução implementada por você ou por meio das diversas facilidades do framework para processamento assíncrono.
Por exemplo, ao usar uma MediaPlayer
na 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 reprodução.
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 são sinalizados com uma exceção ou um código de erro, mas sempre que você usar recursos assíncronos, verifique se seu aplicativo é corretamente notificado sobre erros. No caso de uma MediaPlayer
, faça isso implementando um MediaPlayer.OnErrorListener
e definindo-o na instância da sua 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 um erro ocorre, a MediaPlayer
entra no estado Error (erro) e você precisa redefini-la para usá-la novamente. Consulte a documentação da classe para ver o diagrama de estado completo.
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 é executado. Como o sistema Android tenta economizar bateria enquanto o dispositivo está inativo, ele tenta desligar os recursos desnecessários para o smartphone, incluindo a CPU e o hardware Wi-Fi. No entanto, se o serviço estiver reproduzindo ou fazendo streaming de música, evite que o sistema interfira na reprodução.
Para que o serviço continue sendo executado nessas condições, é necessário usar "wake locks". Um wake lock é uma maneira de sinalizar para o sistema que seu aplicativo está usando algum recurso que deveria permanecer disponível, mesmo se o telefone estivesse ocioso.
Aviso: sempre use wake locks com moderação e mantenha-os apenas pelo tempo necessário. Eles reduzem significativamente a duração da bateria do dispositivo.
Para que a CPU continue em execução enquanto sua MediaPlayer
é reproduzida, chame o método setWakeMode()
ao inicializar sua . Depois de fazer isso, a MediaPlayer
mantém o wake lock especificado durante a reprodução e o libera quando é pausada ou interrompida:
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 on-line e estiver usando o Wi-Fi, também manterá um WifiLock
, que precisará ser adquirido e liberado manualmente. Então, quando você começar a preparar a MediaPlayer
com o URL remoto, crie e adquira o wake lock 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();
Quando você pausar ou interromper a mídia ou quando não precisar mais da rede, libere o wake lock:
Kotlin
wifiLock.release()
Java
wifiLock.release();
Realizar uma limpeza
Como mencionado anteriormente, um objeto MediaPlayer
pode consumir uma quantidade significativa de recursos do sistema. Por isso, mantenha-o apenas durante o tempo necessário e chame release()
quando terminar de usá-lo. É importante chamar esse método de limpeza explicitamente, em vez de contar com a coleta de lixo do sistema, uma vez que pode demorar até que o coletor de lixo recupere a MediaPlayer
. Isso acontece porque o coletor é sensível apenas às necessidades de memória, não à falta de outros recursos relacionados à mídia.
Sendo assim, caso você esteja usando um serviço, modifique sempre o método onDestroy()
para liberar a 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
, não somente durante o desligamento. Por exemplo, se você acha que não conseguirá reproduzir mídia por um longo período (por exemplo, depois de perder a seleção de áudio), libere a MediaPlayer
existente e crie-a de novo mais tarde. Por outro lado, se você acha que só interromperá a reprodução por um período muito curto, mantenha a MediaPlayer
para evitar a sobrecarga de repetir a criação e a preparação.
Gerenciamento de direitos digitais (DRM, na sigla em inglês)
A partir do Android 8.0 (API nível 26), a MediaPlayer
inclui APIs compatíveis com a reprodução de material protegido por DRM. Elas são semelhantes à API de nível inferior disponibilizada por MediaDrm
, mas operam em um nível superior e não expõem o extrator subjacente, o DRM e os objetos criptografados.
Embora a API MediaPlayer DRM não ofereça a funcionalidade completa de MediaDrm
, ela é compatível com os 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 a seguir demonstra como usar os novos métodos MediaPlayer DRM em uma implementação síncrona simples.
Para gerenciar mídia controlada por DRM, é preciso incluir os novos métodos junto do 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 definindo a origem dele por meio de 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 anexe-a ao player usandosetOnDrmConfigHelper()
. - Chame
prepare()
. - Chame
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 fazer 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,
prepareDrm()
também acessará o servidor de provisionamento para fazer isso. Isso pode levar um tempo variável, dependendo da conexão de rede. - Para conseguir uma matriz de bytes de solicitação de chave opaca para enviar 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. Você pode usar esse identificador de conjunto de chaves com
restoreKeys()
para restaurar as chaves de 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. Você pode usar esse identificador de conjunto de chaves com
Executar prepareDrm()
de forma assíncrona
Por padrão, prepareDrm()
é executado de forma 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 por prepareDrm()
e pode demorar para ser concluído devido à operação de rede envolvida. Você pode evitar o bloqueio em prepareDrm()
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 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 gerenciadora).
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 MediaPlayer.OnDrmInfoListener
para preparação de DRM e MediaPlayer.OnDrmPreparedListener
para iniciar o player.
Eles 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
A partir do Android 8.0 (API nível 26), MediaPlayer
também pode descriptografar mídia criptografada em nível de amostra com Common Encryption Scheme (CENC) e HLS (METHOD=SAMPLE-AES) para os tipos básicos de streaming 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 { setAudioStreamType(AudioManager.STREAM_MUSIC) 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.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(getApplicationContext(), contentUri); // ...prepare and start...
Amostra de código
As amostras BasicMediaDecoder e DeviceOwner (links em inglês) demonstram o uso das APIs abordadas nesta página.
Saiba mais
Essas páginas abrangem tópicos relacionados à gravação, ao armazenamento e à reprodução de áudio e vídeo.