Présentation de MediaPlayer

Le framework multimédia Android permet de lire divers types de contenus multimédias courants. permettant d'intégrer facilement de l'audio, de la vidéo et des images dans vos applications. Vous pouvez lire du contenu audio ou vidéo provenant de fichiers multimédias stockés dans les ressources de votre application (ressources brutes), à partir de fichiers autonomes dans le système de fichiers ou à partir d'un flux de données arrivant via une connexion réseau, le tout à l'aide des API MediaPlayer.

Ce document explique comment utiliser MediaPlayer pour écrire une lecture multimédia application qui interagit avec l'utilisateur et le système afin d'obtenir de bonnes performances une expérience utilisateur agréable. Vous pouvez également d'utiliser ExoPlayer, une solution Open Source personnalisable Bibliothèque compatible avec les fonctionnalités hautes performances non disponible dans MediaPlayer

Remarque:Vous ne pouvez lire les données audio que sur la sortie standard. appareil. Il s'agit actuellement du haut-parleur de l'appareil mobile ou d'un casque Bluetooth. Vous ne pouvez pas faire sonner fichiers dans l'audio de la conversation lors d'un appel.

Principes de base

Les classes suivantes sont utilisées pour lire des sons et des vidéos dans le framework Android:

MediaPlayer
Cette classe est l'API principale permettant de lire des contenus audio et vidéo.
AudioManager
Cette classe gère les sources et la sortie audio d'un appareil.

Déclarations du fichier manifeste

Avant de commencer le développement de votre application à l'aide de MediaPlayer, assurez-vous que votre fichier manifeste les déclarations appropriées pour permettre l'utilisation des fonctionnalités associées.

  • Autorisation Internet : si vous utilisez MediaPlayer pour lire des contenus en streaming via le réseau. votre application doit demander un accès au réseau.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Autorisation de wakelock, si votre application de lecteur doit garder l'écran. de s'assombrir ou de mettre le processeur en veille, ou utilise le MediaPlayer.setScreenOnWhilePlaying() ou MediaPlayer.setWakeMode(), vous devez demander cette autorisation.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

Utilisation de MediaPlayer

L'un des composants les plus importants du cadre média est la MediaPlayer . Un objet de cette classe peut extraire, décoder et lire des contenus audio et vidéo. avec une configuration minimale. Il est compatible avec plusieurs sources multimédias différentes, par exemple:

  • Ressources locales
  • URI internes, tels que ceux que vous pouvez obtenir auprès d'un résolveur de contenu
  • URL externes (flux)

Pour obtenir la liste des formats multimédias compatibles avec Android, consultez la page Supports compatibles Formats.

Voici un exemple : d'un contenu audio disponible en tant que ressource brute locale (enregistrée dans le fichier répertoire 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

Dans ce cas, une couche « brute » est un fichier que le système n'a pas ou essayer d'analyser d'une manière particulière. Cependant, le contenu de cette ressource ne doit pas au format audio brut. Il doit s'agir d'un fichier multimédia correctement encodé et formaté tous les formats acceptés.

Voici comment effectuer la lecture à partir d'un URI disponible localement dans le système (obtenues par le biais d'un résolveur de contenu, par exemple):

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

Voici à quoi ressemble la lecture à partir d'une URL distante via un streaming HTTP:

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

Remarque: Si vous transmettez une URL pour diffuser en streaming un fichier multimédia en ligne, le fichier doit pouvoir : téléchargement progressif.

Attention:Vous devez soit attraper, soit passer IllegalArgumentException et IOException lors de l'utilisation setDataSource(), car le fichier que vous référencez n'existe peut-être pas.

Préparation asynchrone

L'utilisation de MediaPlayer peut être simple dans sur ce principe. Cependant, il est important de garder à l’esprit que quelques autres éléments sont pour l'intégrer correctement à une application Android classique. Pour Par exemple, l'appel de prepare() peut son exécution prend beaucoup de temps, car il peut s'agir d'extraire et de décoder des données multimédias. Ainsi, comme c'est le cas pour dont l'exécution peut prendre du temps, vous ne devez jamais l'appeler depuis votre thread UI de l'application. Cela provoque le blocage de l'interface utilisateur jusqu'à ce que la méthode soit renvoyée, ce qui est une très mauvaise expérience utilisateur et peut provoquer une erreur ANR (L'application ne répond pas). Même si vous vous attendez à ce que votre ressource se charge rapidement, n'oubliez pas que tout ce qui prend plus d'un dixième d'une seconde pour répondre dans l'interface utilisateur entraîne une pause notable et donne l'utilisateur l'impression que votre application est lente.

Pour éviter de suspendre votre thread UI, générez un autre thread pour préparer le MediaPlayer et avertir le thread principal une fois l'opération terminée. Cependant, bien que vous pouvez écrire la logique des threads vous-même, ce modèle est si courant lors de l'utilisation de MediaPlayer que le framework fournit un moyen pratique d'accomplir cette tâche en utilisant prepareAsync(). Cette méthode commence à préparer le contenu multimédia en arrière-plan et revient immédiatement. Lorsque le média a fini de préparer, le onPrepared() de MediaPlayer.OnPreparedListener, configurée via setOnPreparedListener() est appelé.

Gérer l'état

Un autre aspect de MediaPlayer que vous devez garder à l'esprit est qu'elle est basée sur l'état. Autrement dit, MediaPlayer a un état interne. dont vous devez toujours être conscient lorsque vous écrivez votre code, car certaines opérations ne sont valides que lorsque le joueur se trouve dans un état spécifique. Si vous effectuez une opération dans le mauvais état, le système peut générer une exception ou provoquer d'autres comportements indésirables.

La documentation disponible dans La classe MediaPlayer montre un diagramme d'état complet. qui précise quelles méthodes déplacent MediaPlayer d'un état à un autre. Par exemple, lorsque vous créez un nouveau MediaPlayer, il se trouve dans l'état Inactif de l'état. À ce stade, vous devez l'initialiser en appelant setDataSource(), c'est parti ! à l'état Initialisé. Vous devez ensuite le préparer en utilisant prepare() ou prepareAsync(). Quand ? MediaPlayer a terminé la préparation, il entre dans la classe Prepared ce qui signifie que vous pouvez appeler start() pour qu'elle lise le contenu multimédia. À ce stade, comme le montre le diagramme, vous pouvez passer d'un état Started (Démarré), Suspendu (Mise en pause) à PlaybackCompleted (Lecture terminée) en procédant comme suit : en appelant des méthodes telles que start(), pause() et seekTo(), entre autres. Lorsque vous appelez stop(). Notez toutefois que Impossible de rappeler start() tant que vous n'aurez pas préparer à nouveau MediaPlayer.

Conservez toujours le diagramme d'état. lorsque vous écrivez du code qui interagit avec MediaPlayer, car appeler ses méthodes à partir du mauvais état constitue est la cause la plus courante de bugs.

Libérer MediaPlayer

Un MediaPlayer peut consommer ressources système. Vous devez donc toujours prendre des précautions supplémentaires pour vous assurer à une instance MediaPlayer plus longtemps que nécessaire. Lorsque vous vous devez toujours appeler release() pour vous assurer les ressources système qui lui sont allouées sont correctement libérées. Par exemple, si vous à l'aide d'un MediaPlayer et que votre activité reçoit un appel à onStop(), vous devez libérer le MediaPlayer, parce qu'il qu'il n'est pas logique de le tenir tant que votre activité n'interagit pas avec l'utilisateur (sauf si vous lisez du contenu multimédia en arrière-plan, ce qui est abordé dans la section suivante). Lorsque votre activité reprend ou reprend, bien sûr, vous devez Créez un MediaPlayer et préparez-le à nouveau avant de reprendre la lecture.

Voici comment libérer et supprimer votre MediaPlayer:

Kotlin

mediaPlayer?.release()
mediaPlayer = null

Java

mediaPlayer.release();
mediaPlayer = null;

À titre d'exemple, considérez les problèmes qui pourraient survenir si vous oublié de libérer le MediaPlayer lorsque votre activité est arrêtée, mais créez un lorsque l'activité reprendra. Comme vous le savez peut-être, lorsque l'utilisateur modifie l'orientation de l'écran (ou modifie la configuration de l'appareil d'une autre manière) ; le système gère cela en redémarrant l'activité (par défaut). Ainsi, vous pouvez rapidement consomment toutes les ressources système lorsque l'utilisateur fait pivoter l'appareil entre les modes portrait et paysage, car à chaque un changement d'orientation, vous créez un MediaPlayer que vous n'avez jamais de sortie. (Pour en savoir plus sur les redémarrages de l'environnement d'exécution, consultez Gérer les modifications apportées à l'environnement d'exécution.)

Vous vous demandez peut-être ce qui se passe si vous voulez continuer à jouer. "contenu multimédia en arrière-plan" même lorsque l'utilisateur quitte votre activité, à peu près au même du comportement de l'application Music intégrée. Dans ce cas, vous avez besoin un MediaPlayer contrôlé par un Service, comme abordés dans la section suivante

Utiliser MediaPlayer dans un service

Si vous souhaitez lire vos contenus multimédias en arrière-plan même lorsque votre application ne s'affiche pas à l'écran, c'est-à-dire que la lecture doit se poursuivre pendant que l'utilisateur avec d'autres applications, vous devez lancer une Service et contrôle MediaPlayer. Vous devez intégrer le MediaPlayer dans un service MediaBrowserServiceCompat et elle interagit avec MediaBrowserCompat dans une autre activité.

Vous devez faire attention à cette configuration client/serveur. Il y a des attentes sur la façon dont un lecteur exécuté dans un service d'arrière-plan interagit avec le reste du système d'exploitation. Si votre application ne répond pas à ces attentes, l'utilisateur peut ont une mauvaise expérience. Lue Créer une application audio pour en savoir plus.

Cette section décrit des instructions spéciales pour gérer un MediaPlayer lorsqu'il est implémenté dans un service.

Exécuter de manière asynchrone

Tout d'abord, comme une Activity, fonctionnent toutes dans un Service est effectué dans un seul fil de discussion par par défaut. En fait, si vous exécutez une activité et un service à partir de la même application, utilisent le même thread (le "thread principal") par défaut. Par conséquent, les services doivent traiter rapidement les intents entrants ; et de ne jamais effectuer de longs calculs pour y répondre. Si des ou des appels bloquants sont attendus, vous devez effectuer ces tâches de manière asynchrone : un autre fil de discussion que vous mettez en œuvre vous-même, ou en utilisant les nombreuses installations du framework pour le traitement asynchrone.

Par exemple, lorsque vous utilisez un MediaPlayer à partir de votre thread principal, appelez prepareAsync() plutôt que prepare() et implémenter un MediaPlayer.OnPreparedListener pour être averti lorsque la préparation est terminée et que vous pouvez commencer à jouer. Exemple :

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

Gérer les erreurs asynchrones

Pour les opérations synchrones, les erreurs être signalée par une exception ou un code d'erreur, mais chaque fois que vous utilisez des requêtes ressources, vous devez vous assurer que votre application est informée d'erreurs en conséquence. Dans le cas d'une MediaPlayer, vous pouvez y parvenir en implémentant MediaPlayer.OnErrorListener et en le définissant dans votre instance 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!
    }
}

Il est important de se rappeler que lorsqu'une erreur se produit, MediaPlayer passe à l'état Erreur (consultez la documentation pour MediaPlayer pour le diagramme d'état complet) et vous devez le réinitialiser avant de pouvoir l'utiliser à nouveau.

Utiliser des wakelocks

Lors de la conception d'applications qui lisent des contenus multimédias en arrière-plan, l'appareil peut se mettre en veille pendant l'exécution de votre service. Comme le système Android tente de préserver de la batterie lorsque l'appareil est en veille, le système tente d'éteindre fonctionnalités du téléphone qui sont pas nécessaires, y compris le CPU et le matériel WiFi. Toutefois, si votre service lit ou diffuse de la musique en streaming, vous devez empêcher empêcher le système d'interférer avec la lecture.

Afin de garantir que votre service continue de fonctionner en ces conditions, vous devez utiliser des « wakelocks ». Un wakelock est un moyen de signaler le système sur lequel votre application utilise une fonctionnalité restent disponibles même si le téléphone est inactif.

Remarque:Vous devez toujours utiliser les wakelocks avec parcimonie et les maintenir enfoncés. aussi longtemps que nécessaire, car ils réduisent considérablement l'autonomie de la batterie appareil.

Pour garantir que le processeur continue de s'exécuter pendant que votre MediaPlayer est appelez la méthode setWakeMode() lors de l'initialisation de votre MediaPlayer. Une fois que c'est fait, le MediaPlayer maintient le verrouillage spécifié pendant la lecture et libère le verrou en cas de pause ou d'arrêt:

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

Cependant, le wakelock acquis dans cet exemple garantit uniquement que le processeur reste actif. Si vous diffusez du contenu multimédia et que vous utilisez une connexion Wi-Fi, vous voudrez probablement WifiLock en tant que que vous devez acquérir et publier manuellement. Lorsque vous commencerez à préparer MediaPlayer par l'URL distante, vous devez créer et obtenir le verrou Wi-Fi. Exemple :

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

Lorsque vous mettez en pause ou arrêtez la lecture d'un contenu multimédia, ou lorsque vous n'avez plus besoin de la vous devez débloquer le verrou:

Kotlin

wifiLock.release()

Java

wifiLock.release();

Nettoyage...

Comme indiqué précédemment, un objet MediaPlayer peut consommer de ressources système. Vous ne devez donc les conserver que pendant la durée release() lorsque vous n'en avez plus besoin. C'est important d'appeler cette méthode de nettoyage explicitement au lieu d'utiliser la récupération de mémoire du système, car il peut s'écouler un certain temps avant que le récupérateur de mémoire récupère le MediaPlayer, car il n’est sensible qu’aux besoins de mémoire et non à la pénurie d’autres ressources liées aux médias. Ainsi, lorsque vous utilisez un service, vous devez toujours remplacer onDestroy() pour vous assurer de publier votre application 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();
   }
}

Pensez toujours à rechercher d'autres opportunités de publier votre MediaPlayer ainsi que lors de l'arrêt. Par exemple, si vous ne vous attendez pas à de pouvoir lire des contenus multimédias pendant une période prolongée (après avoir perdu la priorité sur le son, par exemple) ; vous devez absolument libérer votre MediaPlayer existante et la recréer plus tard. Le En revanche, si vous prévoyez d'arrêter la lecture pendant un court laps de temps, vous devriez conserver votre MediaPlayer pour éviter les frais de création et de préparation à nouveau.

Gestion des droits numériques (DRM)

À partir d'Android 8.0 (niveau d'API 26), MediaPlayer inclut des API qui : permettre la lecture de contenus protégés par DRM ; Elles sont semblables à l'API de bas niveau fournie par MediaDrm, mais elles fonctionnent à un niveau plus élevé et ne fonctionnent pas expose les objets extracteurs, drm et crypto sous-jacents.

Bien que l'API MediaPlayer DRM ne fournisse pas toutes les fonctionnalités MediaDrm, il est compatible avec les cas d'utilisation les plus courants. La la mise en œuvre actuelle peut gérer les types de contenu suivants:

  • Fichiers multimédias locaux protégés par Widevine
  • Fichiers multimédias distants/en streaming protégés par Widevine

L'extrait de code suivant montre comment utiliser le nouveau MediaPlayer DRM. dans une implémentation synchrone simple.

Pour gérer les contenus multimédias contrôlés par DRM, vous devez inclure les nouvelles méthodes en plus de le flux habituel des appels MediaPlayer, comme indiqué ci-dessous:

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

Commencez par initialiser l'objet MediaPlayer et définissez sa source à l'aide de setDataSource(), comme d'habitude. Ensuite, pour utiliser DRM, procédez comme suit:

  1. Si vous souhaitez que votre application effectue une configuration personnalisée, définissez OnDrmConfigHelper, puis associez-la au joueur utilisant setOnDrmConfigHelper()
  2. Appelez prepare().
  3. Appelez getDrmInfo(). Si la source est protégée par DRM contenu, la méthode renvoie une valeur non nulle Valeur MediaPlayer.DrmInfo.

Si MediaPlayer.DrmInfo existe:

  1. Examinez la carte des UUID disponibles et choisissez-en un.
  2. Préparez la configuration DRM pour la source actuelle en appelant prepareDrm().
    • Si vous avez créé et enregistré un OnDrmConfigHelper, il s'appelle alors que prepareDrm() est en cours d'exécution. Cela vous permet d'effectuer une configuration personnalisée de la DRM. avant d'ouvrir la session DRM. Le rappel est appelé de manière synchrone dans le thread qui a appelé prepareDrm() À accéder aux propriétés DRM, getDrmPropertyString() et setDrmPropertyString() Évitez les opérations interminables.
    • Si l'appareil n'a pas encore été provisionné, prepareDrm() également accède au serveur de provisionnement pour provisionner l'appareil. Cela peut prendre de temps variable, en fonction de la connectivité réseau.
  3. Pour obtenir un tableau d'octets de requête de clé opaque à envoyer à un serveur de licences, appelez getKeyRequest()
  4. Pour informer le moteur DRM de la réponse clé reçue du serveur de licences, appelez provideKeyResponse() Le résultat dépend du type de requête de clé: <ph type="x-smartling-placeholder">
      </ph>
    • Si la réponse concerne une requête de clé hors connexion, le résultat est un identifiant de collection de clés. Vous pouvez utiliser cet identifiant d'ensemble de clés avec restoreKeys() pour restaurer les clés session.
    • Si la réponse concerne une requête de streaming ou de publication, le résultat est nul.

Exécuter prepareDrm() de manière asynchrone

Par défaut, prepareDrm() s'exécute de manière synchrone, en bloquant l'opération jusqu'à la fin de la préparation. Cependant, la première préparation de la DRM sur un nouvel appareil peut également nécessiter un provisionnement, ce qui gérées en interne par prepareDrm() et peut prendre un certain temps en raison de l'opération réseau impliquée. Vous pouvez évitez de bloquer prepareDrm() par définir et définir un MediaPlayer.OnDrmPreparedListener.

Lorsque vous définissez un OnDrmPreparedListener, prepareDrm() effectue le provisionnement (si nécessaire) et la préparation en arrière-plan. Quand ? le provisionnement et la préparation sont terminés, l'écouteur est appelé. Vous devez ne faites aucune hypothèse concernant la séquence d'appel ou le thread dans lequel s'exécute (sauf si l'écouteur est enregistré avec un thread de gestionnaire). L'écouteur peut être appelé avant ou après prepareDrm() .

Configurer la DRM de manière asynchrone

Vous pouvez initialiser la DRM de manière asynchrone en créant et en enregistrant le MediaPlayer.OnDrmInfoListener pour la préparation DRM et les MediaPlayer.OnDrmPreparedListener pour démarrer le lecteur. Elles fonctionnent conjointement avec prepareAsync(), comme indiqué ci-dessous:

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

Gérer les contenus multimédias chiffrés

À partir d'Android 8.0 (niveau d'API 26), MediaPlayer peut également déchiffrer Schéma CENC (Common Encryption Scheme) et Contenu multimédia chiffré au niveau de l'échantillon HLS (Méthodes=EXEMPLE-AES) pour les types de flux élémentaires H.264 et AAC. Auparavant, le contenu multimédia chiffré en segment complet (méthode method=AES-128) était accepté.

Récupérer des contenus multimédias à partir d'un ContentResolver

Une autre fonctionnalité qui peut être utile dans une application de lecteur multimédia est la possibilité récupérer la musique dont l'utilisateur dispose sur l'appareil. Pour ce faire, interrogez ContentResolver pour rechercher des supports externes:

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

Pour l'utiliser avec MediaPlayer, procédez comme suit:

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

En savoir plus

Ces pages traitent de sujets liés à l'enregistrement, au stockage et à la lecture de contenus audio et vidéo.