Panoramica di MediaPlayer

Il framework multimediale Android include il supporto per la riproduzione di vari tipi di contenuti multimediali comuni, quindi di integrare facilmente audio, video e immagini nelle tue applicazioni. Puoi riprodurre contenuti audio o Video da file multimediali archiviati nelle risorse dell'applicazione (risorse non elaborate), da file autonomi nel file system o da uno stream di dati in arrivo su una connessione di rete, il tutto utilizzando le API di MediaPlayer.

Questo documento illustra come utilizzare MediaPlayer per scrivere una riproduzione multimediale un'applicazione che interagisce con l'utente e il sistema per ottenere buone prestazioni e una piacevole esperienza utente. In alternativa, potresti per utilizzare ExoPlayer, un sistema open source personalizzabile libreria che supporta funzionalità ad alte prestazioni non disponibile in MediaPlayer

Nota:puoi riprodurre i dati audio solo sull'output standard dispositivo. Attualmente, si tratta dell'altoparlante del dispositivo mobile o delle cuffie Bluetooth. Non puoi riprodurre il suono file nell'audio della conversazione durante una chiamata.

Nozioni di base

Le seguenti classi vengono utilizzate per riprodurre audio e video nel framework Android:

MediaPlayer
Questa classe è l'API principale per la riproduzione di audio e video.
AudioManager
Questo corso gestisce le sorgenti e l'uscita audio su un dispositivo.

Dichiarazioni del file manifest

Prima di iniziare lo sviluppo dell'applicazione utilizzando MediaPlayer, assicurati che il file manifest abbia le dichiarazioni appropriate per consentire l'uso delle funzionalità correlate.

  • Autorizzazione Internet: se utilizzi MediaPlayer per lo streaming in base alla rete. contenuti, l'applicazione deve richiedere l'accesso alla rete.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Autorizzazione wakelock: se l'applicazione del player deve mantenere lo schermo l'attenuazione della luminosità o la sospensione del processore, oppure utilizza MediaPlayer.setScreenOnWhilePlaying() o MediaPlayer.setWakeMode() metodi, devi richiedere questa autorizzazione.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

Utilizzo di MediaPlayer

Uno dei componenti più importanti del framework multimediale è il MediaPlayer . Un oggetto di questa classe può recuperare, decodificare e riprodurre sia audio che video con una configurazione minima. Supporta diverse fonti multimediali, tra cui:

  • Risorse locali
  • URI interni, ad esempio quello che potresti ottenere da un resolver di contenuti
  • URL esterni (streaming)

Per un elenco dei formati multimediali supportati da Android, consulta la sezione Contenuti multimediali supportati Formati.

Ecco un esempio di come riprodurre l'audio disponibile come risorsa locale non elaborata (salvato nel directory 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

In questo caso, un file "grezzo" risorsa è un file che il sistema non provare ad analizzare in un modo particolare. Tuttavia, i contenuti di questa risorsa non devono essere audio RAW. Deve essere un file multimediale codificato e formattato correttamente in un dei formati supportati.

Ed ecco come potresti giocare da un URI disponibile localmente nel sistema (ottenuti, ad esempio, tramite un sistema di risoluzione dei contenuti):

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();

La riproduzione da un URL remoto tramite streaming HTTP ha il seguente aspetto:

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();

Nota: Se passi un URL per lo streaming di un file multimediale online, il file deve essere in grado di: un download progressivo.

Attenzione: devi rilevare o superare IllegalArgumentException e IOException quando utilizzi setDataSource(), perché il file a cui fai riferimento potrebbe non esistere.

Preparazione asincrona

L'utilizzo di MediaPlayer può essere semplice dell'IA. Tuttavia, è importante tenere presente che vengono necessario per integrarlo correttamente in una tipica applicazione Android. Per Ad esempio, la chiamata a prepare() può richiedono tempi di esecuzione lunghi, potrebbe comportare il recupero e la decodifica dei dati multimediali. Quindi, come avviene per qualsiasi la cui esecuzione può richiedere molto tempo, non dovresti mai chiamarlo dai tuoi thread interfaccia utente dell'applicazione. In questo modo, la UI si blocca finché non viene restituito il metodo. che causa un'esperienza utente molto scadente e può causare un errore ANR (L'applicazione non risponde). Anche se ti aspetti che la risorsa venga caricata rapidamente, ricorda che tutto ciò che richiede più di un decimo di secondo per rispondere nell'UI comporta una notevole pausa e all'utente l'impressione che l'applicazione sia lenta.

Per evitare il blocco del thread della UI, genera un altro thread in prepara MediaPlayer e invia una notifica al thread principale al termine dell'operazione. Tuttavia, anche se potresti scrivere la logica del thread di persona, questo pattern è talmente comune quando si utilizza MediaPlayer che il framework un modo conveniente per svolgere questa attività utilizzando Metodo prepareAsync(). Questo metodo inizia a preparare i contenuti multimediali in background e ritorna immediatamente. Quando i contenuti multimediali ha terminato la preparazione, onPrepared() di MediaPlayer.OnPreparedListener, configurato tramite Chiamata setOnPreparedListener().

Gestione dello stato

Un altro aspetto di MediaPlayer che dovresti tenere a mente è che sia basato sullo stato. Questo significa che MediaPlayer ha uno stato interno di cui devi sempre essere a conoscenza quando scrivi il codice, poiché alcune operazioni sono valide solo quando il player si trova in stati specifici. Se esegui un'operazione stato errato, il sistema potrebbe generare un'eccezione o causare altri comportamenti indesiderati.

La documentazione nel MediaPlayer classe mostra un diagramma di stato completo, che chiarisce quali metodi consentono di spostare MediaPlayer da uno stato all'altro. Ad esempio, quando crei un nuovo MediaPlayer, questo è in Inattivo stato. A quel punto, dovresti inizializzarlo chiamando setDataSource(), ora lo metto allo stato Inizializzato. Dopodiché, devi prepararlo utilizzando prepare() o Metodo prepareAsync(). Quando MediaPlayer ha terminato la preparazione, entra nello stato Preparato stato, il che significa che puoi chiamare start() per riprodurre i contenuti multimediali. A quel punto, come illustrato nel diagramma, puoi spostarti tra gli stati Iniziato, In pausa e Riproduzione completata chiamare questi metodi start(), pause() e seekTo(), tra gli altri. Quando chiama stop(), tuttavia, noterai che non puoi chiamare di nuovo start() finché non prepara di nuovo MediaPlayer.

Mantieni sempre il diagramma di stato quando si scrive un codice che interagisce MediaPlayer, perché chiamare i suoi metodi dallo stato errato è una causa comune di insetti.

Rilascio di MediaPlayer

Un MediaPlayer può consumare preziose risorse di sistema. Pertanto, prendi sempre precauzioni aggiuntive per assicurarti di non restando in attesa a un'istanza MediaPlayer più a lungo del necessario. Quando hai finito, dovresti sempre chiamare release() per assicurarti e le risorse di sistema assegnate al suo sistema siano rilasciate correttamente. Ad esempio, se utilizzando MediaPlayer e la tua attività riceve una chiamata al numero onStop(), devi rilasciare MediaPlayer, perché ha poco senso tenerla mentre non interagisci con la tua attività all'utente (a meno che tu non stia riproducendo i contenuti multimediali in background, come descritto nella prossima sezione). Quando l'attività viene ripresa o riavviata, naturalmente, è necessario crea un nuovo MediaPlayer e preparalo di nuovo prima di riprendere la riproduzione.

Ecco come devi rilasciare e annullare MediaPlayer:

Kotlin

mediaPlayer?.release()
mediaPlayer = null

Java

mediaPlayer.release();
mediaPlayer = null;

Considera ad esempio i problemi che potrebbero verificarsi se hai dimenticato di rilasciare MediaPlayer quando la tua attività viene interrotta, ma crea un una nuova sveglia quando l'attività ricomincia. Come forse saprai, quando l'utente modifica orientamento dello schermo (o modifica la configurazione del dispositivo in altro modo), il sistema lo gestisce riavviando l'attività (per impostazione predefinita), quindi potresti e consuma tutte le risorse di sistema mentre ruota il dispositivo avanti e indietro in orizzontale e in verticale, cambia l'orientamento, crei un nuovo MediaPlayer . Per ulteriori informazioni sui riavvii del runtime, consulta Gestione delle modifiche del runtime.

Forse ti starai chiedendo cosa succede se vuoi continuare a giocare "contenuti multimediali in background" anche quando l'utente abbandona la tua attività, quasi il comportamento dell'applicazione Music integrata. In questo caso, ti serve un MediaPlayer controllato da un servizio, come di cui parleremo nella prossima sezione.

Utilizzo di MediaPlayer in un servizio

Se vuoi riprodurre i contenuti multimediali in background anche quando l'applicazione non viene mostrato sullo schermo, vale a dire che vuoi che continui la riproduzione mentre l'utente interagire con altre applicazioni, allora devi avviare Fornire e controllare MediaPlayer istanza da lì. Devi incorporare MediaPlayer in un servizio MediaBrowserServiceCompat e ha interagisce con MediaBrowserCompat in un'altra attività.

Devi prestare attenzione alla configurazione client/server. Ci sono aspettative su come un player eseguito in un servizio in background interagisce con il resto dei di un sistema operativo completo. Se la tua applicazione non soddisfa queste aspettative, l'utente può hanno una brutta esperienza. Letto Creazione di un'app audio per tutti i dettagli.

In questa sezione vengono descritte le istruzioni speciali per la gestione di un MediaPlayer quando è implementato all'interno di un servizio.

Esecuzione asincrona

Innanzitutto, come in un Activity, tutti lavorano in un Service viene svolto in un singolo thread da predefinita: se esegui un'attività e un servizio dalla stessa applicazione, usa lo stesso thread (il "thread principale") per impostazione predefinita. Pertanto, i servizi devono elaborare rapidamente gli intent in arrivo e non eseguire mai calcoli lunghi quando si risponde. Se intensa di lavoro o di blocco delle chiamate, devi eseguire queste attività in modo asincrono: un altro thread che implementi personalmente o utilizzando le numerose strutture del framework per l'elaborazione asincrona.

Ad esempio, se usi MediaPlayer dal thread principale, dovresti chiamare prepareAsync() anziché prepare() e implementa un MediaPlayer.OnPreparedListener per ricevere una notifica quando la preparazione è terminata e potrai iniziare a giocare. Ad esempio:

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();
    }
}

Gestione degli errori asincroni

Nelle operazioni sincrone, gli errori normalmente essere segnalata con un'eccezione o un codice di errore, ma ogni volta che utilizzi il devi assicurarti che la tua richiesta venga informata di errori in modo appropriato. Nel caso di un MediaPlayer, puoi farlo implementando un MediaPlayer.OnErrorListener e impostandolo nella tua istanza 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 ricordare che, quando si verifica un errore, MediaPlayer passa allo stato Errore (consulta la documentazione per MediaPlayer per il diagramma dello stato completo) e devi reimpostarlo prima di poterlo riutilizzare.

Utilizzo dei wakelock

Durante la progettazione di applicazioni per la riproduzione di contenuti multimediali in background, il dispositivo potrebbe entrare in modalità di sospensione mentre il servizio è in esecuzione. Poiché il sistema Android cerca di risparmiare batteria mentre il dispositivo è in sospensione, il sistema tenta di spegnere delle funzionalità dello smartphone come la CPU e l'hardware Wi-Fi. Tuttavia, se il servizio riproduce musica o riproduce musica in streaming, vuoi evitare il sistema non interferisca con la riproduzione.

Per assicurarti che il servizio continui a essere eseguito in in queste condizioni, è necessario usare i "wakelock". Un wakelock è un modo per segnalare a al sistema che la tua applicazione stia usando una funzionalità che dovrebbe rimangono disponibili anche quando il telefono è inattivo.

Avviso: dovresti sempre usare i wakelock con parsimonia e tenerli in mano solo per il tempo realmente necessario, poiché riducono notevolmente la durata della batteria del dispositivo.

Per assicurarti che la CPU continui a funzionare mentre MediaPlayer è la riproduzione, chiama il metodo setWakeMode() durante l'inizializzazione di MediaPlayer. Dopodiché, MediaPlayer mantiene il blocco specificato durante la riproduzione e rilascia il blocco se messo in pausa o interrotto:

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);

Tuttavia, il wakelock acquisito in questo esempio garantisce solo che la CPU rimanga attiva. Se stai trasmettendo contenuti multimediali in streaming e stai utilizzando il Wi-Fi, probabilmente vorrai mantenere una WifiLock sotto forma di che devi acquisire e rilasciare manualmente. Quindi, quando inizi a preparare MediaPlayer con l'URL remoto, devi creare e acquisire il blocco Wi-Fi. Ad esempio:

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 metti in pausa o interrompi i contenuti multimediali o quando non hai più bisogno del devi rilasciare il blocco:

Kotlin

wifiLock.release()

Java

wifiLock.release();

Pulizia in corso

Come accennato in precedenza, un oggetto MediaPlayer può consumare una quantità una quantità di risorse di sistema, quindi dovresti conservarla solo per il tempo necessario e richiamare release() quando hai finito. È importante di chiamare esplicitamente questo metodo di pulizia anziché fare affidamento sulla garbage collection del sistema potrebbe essere necessario un po' di tempo prima che il garbage collection recuperi l'oggetto MediaPlayer, poiché è sensibile solo alle esigenze di memoria e non alla carenza di altre risorse relative ai media. Quindi, nel caso in cui utilizzi un servizio, dovresti sempre eseguire l'override onDestroy() metodo per assicurarti di rilasciare 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();
   }
}

Dovresti sempre cercare altre opportunità per rilasciare MediaPlayer oltre a rilasciarlo quando viene arrestato. Ad esempio, se non prevedi che poter riprodurre contenuti multimediali per un lungo periodo di tempo (ad esempio, dopo aver perso l'audio attivo), devi sicuramente rilasciare il tuo MediaPlayer esistente e crearlo di nuovo in un secondo momento. Il giorno dall'altra parte, se prevedi di interrompere la riproduzione solo per un breve periodo, probabilmente tieniti stretto MediaPlayer per evitare di sprecare tempo per crearlo e prepararlo di nuovo.

Gestione dei diritti digitali (DRM)

A partire da Android 8.0 (livello API 26), MediaPlayer include API che per la riproduzione di materiale protetto da DRM. Sono simili all'API di basso livello fornita MediaDrm, ma operano a un livello superiore e non esporre gli estrattori, gli oggetti drm e le criptovalute sottostanti.

Sebbene l'API DRM MediaPlayer non fornisca la funzionalità completa MediaDrm, supporta i casi d'uso più comuni. La l'implementazione attuale è in grado di gestire i seguenti tipi di contenuti:

  • File multimediali locali protetti da Widevine
  • File multimediali remoti/in streaming protetti da Widevine

Il seguente snippet di codice mostra come utilizzare il nuovo DRM MediaPlayer in una semplice implementazione sincrona.

Per gestire i contenuti multimediali controllati da DRM, devi includere i nuovi metodi insieme il normale flusso di chiamate a MediaPlayer, come mostrato di seguito:

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();

Inizia inizializzando l'oggetto e l'impostazione MediaPlayer la sua origine utilizzando setDataSource(), come al solito. Quindi, per utilizzare DRM, segui questi passaggi:

  1. Se vuoi che la tua app esegua la configurazione personalizzata, definisci OnDrmConfigHelper e collegala all'interfaccia un lettore con setOnDrmConfigHelper().
  2. Chiama il numero prepare().
  3. Chiama il numero getDrmInfo(). Se l'origine ha DRM content, il metodo restituisce un valore Valore MediaPlayer.DrmInfo.

Se MediaPlayer.DrmInfo esiste:

  1. Esamina la mappa degli UUID disponibili e scegline uno.
  2. Prepara la configurazione DRM per l'origine attuale chiamando prepareDrm().
    • Se hai creato e registrato un callback OnDrmConfigHelper, si chiama mentre prepareDrm() è in esecuzione. Questo ti consente di eseguire la configurazione personalizzata di DRM prima di aprire la sessione DRM. Il callback viene chiamato in modo sincrono nel thread prepareDrm(). A per accedere alle proprietà DRM, richiama getDrmPropertyString() e setDrmPropertyString(). Evita di eseguire operazioni lunghe.
    • Se non è ancora stato eseguito il provisioning del dispositivo, Anche prepareDrm() accede al server di provisioning per eseguire il provisioning del dispositivo. L'operazione può richiedere a seconda della connettività di rete.
  3. Per ottenere un array di byte di richiesta di chiave opaco da inviare a un server licenze, richiama getKeyRequest().
  4. Per informare il motore DRM della risposta chiave ricevuta dal server di licenze, chiama provideKeyResponse(). Il risultato dipende dal tipo di richiesta della chiave:
    • Se la risposta riguarda una richiesta di chiave offline, il risultato è un identificatore del set di chiavi. Puoi utilizzare questo identificatore del set di chiavi con restoreKeys() per ripristinare le chiavi durante la sessione.
    • Se la risposta è per una richiesta di flusso o di rilascio, il risultato è nullo.

Esecuzione di prepareDrm() in modo asincrono

Per impostazione predefinita, prepareDrm() viene eseguito in modo sincrono, bloccando il processo fino al termine della preparazione. Tuttavia, molto la prima preparazione DRM su un nuovo dispositivo può richiedere anche il provisioning, gestiti internamente prepareDrm() e Il completamento dell'operazione potrebbe richiedere del tempo a causa dell'operazione di rete in questione. Puoi evita di bloccare prepareDrm() di la definizione e l'impostazione di un MediaPlayer.OnDrmPreparedListener.

Quando imposti un valore OnDrmPreparedListener, prepareDrm() esegue il provisioning (se necessario) e la preparazione in background. Quando il provisioning e la preparazione sono terminati, viene chiamato il listener. Dovresti non fare ipotesi sulla sequenza di chiamata o sul thread in cui il listener viene eseguito (a meno che il listener sia registrato con un thread gestore). Il listener può essere chiamato prima o dopo prepareDrm() i resi.

Configurazione di DRM in modo asincrono

Puoi inizializzare il DRM in modo asincrono creando e registrando il MediaPlayer.OnDrmInfoListener per la preparazione di DRM e MediaPlayer.OnDrmPreparedListener per avviare il player. Lavorano in combinazione con prepareAsync(), come mostrato di seguito:

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();
}

Gestione dei contenuti multimediali criptati

A partire da Android 8.0 (livello API 26), MediaPlayer può anche decriptare CENC (Common Encryption Scheme) e Contenuti multimediali criptati a livello di campione HLS (METHOD=Sample-AES) per i tipi di stream elementari H.264 e AAC. I contenuti multimediali con crittografia completa (METHOD=AES-128) erano precedentemente supportati.

Recupero di contenuti multimediali da un ContentResolver

Un'altra funzione che può essere utile in un'applicazione di media player è la possibilità di recuperare musica presente sul dispositivo dell'utente. Puoi farlo eseguendo una query su ContentResolver per contenuti multimediali esterni:

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());
}

Per usare questa funzionalità con MediaPlayer, puoi:

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...

Scopri di più

In queste pagine vengono trattati argomenti relativi alla registrazione, all'archiviazione e alla riproduzione di audio e video.