Le framework multimédia Android prend en charge la lecture de divers types de contenus multimédias courants, ce qui vous permet d'intégrer facilement des contenus audio, vidéo et image à vos applications. Vous pouvez lire du contenu audio ou vidéo à partir de fichiers multimédias stockés dans les ressources de votre application (ressources brutes), à partir de fichiers autonomes du système de fichiers ou 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 application de lecture multimédia qui interagit avec l'utilisateur et le système afin d'obtenir de bonnes performances et une expérience utilisateur agréable. Vous pouvez également utiliser ExoPlayer, une bibliothèque Open Source personnalisable qui prend en charge des fonctionnalités hautes performances non disponibles dans MediaPlayer
.
Remarque:Vous ne pouvez lire les données audio que sur le périphérique de sortie standard. Actuellement, il s'agit du haut-parleur de l'appareil mobile ou d'un casque Bluetooth. Vous ne pouvez pas lire de fichiers audio dans l'audio de la conversation pendant un appel.
Principes de base
Les classes suivantes sont utilisées pour lire du son et de la vidéo dans le framework Android:
MediaPlayer
- Cette classe est l'API principale pour la lecture de contenus audio et vidéo.
AudioManager
- Cette classe gère les sources audio et la sortie audio d'un appareil.
Déclarations du fichier manifeste
Avant de commencer le développement de votre application avec MediaPlayer, assurez-vous que votre fichier manifeste contient les déclarations appropriées pour permettre l'utilisation des fonctionnalités associées.
- Autorisation Internet : si vous utilisez MediaPlayer pour diffuser du contenu basé sur le réseau, votre application doit demander l'accès au réseau.
<uses-permission android:name="android.permission.INTERNET" />
- Autorisation Wake Lock : Si l'application de lecteur doit empêcher l'écran de s'assombrir ou le processeur pour se mettre en veille, ou si elle utilise les méthodes
MediaPlayer.setScreenOnWhilePlaying()
ouMediaPlayer.setWakeMode()
, vous devez demander cette autorisation.<uses-permission android:name="android.permission.WAKE_LOCK" />
Utiliser MediaPlayer
L'un des composants les plus importants du framework multimédia est la classe MediaPlayer
. Un objet de cette classe peut récupérer, décoder et lire des contenus audio et vidéo avec une configuration minimale. Il est compatible avec plusieurs sources multimédias, dont les suivantes:
- Ressources locales
- URI internes, tels que celui que vous pouvez obtenir via un résolveur de contenu.
- URL externes (flux)
Pour obtenir la liste des formats multimédias compatibles avec Android, consultez la page Formats multimédias compatibles.
Voici un exemple de lecture de contenu audio disponible en tant que ressource brute locale (enregistrée dans le répertoire res/raw/
de votre application):
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 ressource "brute" est un fichier que le système n'essaie pas d'analyser d'une manière particulière. Toutefois, le contenu de cette ressource ne doit pas être de l'audio brut. Il doit s'agir d'un fichier multimédia correctement encodé et formaté dans l'un des formats acceptés.
Voici comment effectuer la lecture à partir d'un URI disponible localement dans le système (obtenu via 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();
La lecture à partir d'une URL distante via le streaming HTTP se présente comme suit:
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 un fichier multimédia en ligne, le fichier doit être compatible avec le téléchargement progressif.
Attention:Vous devez intercepter ou transmettre IllegalArgumentException
et IOException
lorsque vous utilisez setDataSource()
, car le fichier auquel vous faites référence n'existe peut-être pas.
Préparation asynchrone
L'utilisation de MediaPlayer
peut être simple en principe. Cependant, il est important de garder à l'esprit que quelques opérations sont nécessaires pour l'intégrer correctement à une application Android standard. Par exemple, l'exécution de l'appel à prepare()
peut prendre beaucoup de temps, car il peut impliquer l'extraction et le décodage des données multimédias. Par conséquent, comme c'est le cas pour toute méthode dont l'exécution peut prendre du temps, vous ne devez jamais l'appeler à partir du thread UI de votre application. Cela entraîne le blocage de l'interface utilisateur jusqu'à ce que la méthode soit renvoyée, ce qui nuit à l'expérience utilisateur et peut entraîner une erreur ANR (l'application ne répond pas). Même si vous pensez que votre ressource se charge rapidement, n'oubliez pas que toute réponse d'un dixième de seconde 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 MediaPlayer
et avertissez le thread principal une fois l'opération terminée. Toutefois, bien que vous puissiez écrire la logique de thread vous-même, ce modèle est si courant lorsque vous utilisez MediaPlayer
que le framework fournit un moyen pratique d'effectuer cette tâche à l'aide de la méthode prepareAsync()
. Cette méthode commence à préparer le contenu multimédia en arrière-plan et s'affiche immédiatement. Une fois la préparation du média terminée, la méthode onPrepared()
du MediaPlayer.OnPreparedListener
, configurée via setOnPreparedListener()
, est appelée.
Gérer l'état
Un autre aspect d'une MediaPlayer
que vous devez garder à l'esprit est qu'elle est basée sur l'état. Autrement dit, MediaPlayer
possède un état interne dont vous devez toujours être conscient lorsque vous écrivez votre code, car certaines opérations ne sont valides que lorsque le lecteur se trouve dans des états spécifiques. 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 de la classe MediaPlayer
présente un diagramme d'état complet, qui explique quelles méthodes déplacent l'MediaPlayer
d'un état à un autre.
Par exemple, lorsque vous créez une nouvelle MediaPlayer
, elle est à l'état Inactif. À ce stade, vous devez l'initialiser en appelant setDataSource()
et en passant à l'état Initialized. Vous devez ensuite le préparer à l'aide de la méthode prepare()
ou prepareAsync()
. Une fois la préparation de MediaPlayer
terminée, il passe à l'état Prepared (préparé), ce qui signifie que vous pouvez appeler start()
pour qu'il lit le contenu multimédia. À ce stade, comme l'illustre le diagramme, vous pouvez passer de l'un des états Started (démarré) à l'état PlaybackCompleted (Lecture terminée) en appelant des méthodes telles que start()
, pause()
et seekTo()
, entre autres. Toutefois, lorsque vous appelez stop()
, notez que vous ne pouvez pas appeler à nouveau start()
tant que vous n'avez pas préparé à nouveau le MediaPlayer
.
Gardez toujours à l'esprit le diagramme d'état lorsque vous écrivez du code qui interagit avec un objet MediaPlayer
, car appeler ses méthodes à partir d'un état incorrect est une cause fréquente de bugs.
Libérer MediaPlayer
Un MediaPlayer
peut consommer de précieuses ressources système.
Par conséquent, vous devez toujours prendre des précautions supplémentaires pour vous assurer de ne pas vous accrocher à une instance MediaPlayer
plus longtemps que nécessaire. Lorsque vous en avez terminé, vous devez toujours appeler release()
pour vous assurer que toutes les ressources système qui lui sont allouées sont correctement libérées. Par exemple, si vous utilisez un MediaPlayer
et que votre activité reçoit un appel à onStop()
, vous devez libérer MediaPlayer
, car il est peu logique de le conserver pendant que votre activité n'interagit pas avec l'utilisateur (sauf si vous lisez du contenu multimédia en arrière-plan, comme expliqué dans la section suivante).
Bien entendu, lorsque votre activité est réactivée ou redémarrée, vous devez créer un MediaPlayer
et le préparer à nouveau avant de reprendre la lecture.
Voici comment libérer votre MediaPlayer
, puis l'annuler:
Kotlin
mediaPlayer?.release() mediaPlayer = null
Java
mediaPlayer.release(); mediaPlayer = null;
Par exemple, prenez en compte les problèmes qui peuvent se produire si vous avez oublié de libérer le MediaPlayer
lorsque votre activité est arrêtée, mais que vous en créez un autre lorsque l'activité redémarre. 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). Vous pouvez donc consommer rapidement toutes les ressources système lorsque l'utilisateur fait pivoter l'appareil entre les modes portrait et paysage. En effet, à chaque changement d'orientation, vous créez un MediaPlayer
que vous ne libérez jamais. 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 souhaitez continuer à lire des "contenus multimédias en arrière-plan" même lorsque l'utilisateur quitte votre activité, à peu près de la même manière que l'application Music intégrée. Dans ce cas, vous avez besoin d'un MediaPlayer
contrôlé par un service, comme indiqué dans la section suivante.
Utiliser MediaPlayer dans un service
Si vous souhaitez que votre contenu multimédia s'exécute en arrière-plan même lorsque votre application n'est pas à l'écran (c'est-à-dire si vous voulez que la lecture se poursuive pendant que l'utilisateur interagit avec d'autres applications), vous devez démarrer un service et contrôler l'instance MediaPlayer
à partir de là.
Vous devez intégrer MediaPlayer à un service MediaBrowserServiceCompat
et le faire interagir avec MediaBrowserCompat
dans une autre activité.
Soyez prudent lors de la configuration client/serveur. Il existe des attentes quant à la manière dont un joueur qui s'exécute dans un service d'arrière-plan interagit avec le reste du système. Si votre application ne répond pas à ces attentes, l'utilisateur risque de subir une mauvaise expérience. Pour en savoir plus, consultez Créer une application audio.
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, à l'instar d'un Activity
, toutes les tâches d'un Service
sont effectuées par défaut dans un seul thread. En fait, si vous exécutez une activité et un service de la même application, ils utilisent le même thread (le "thread principal") par défaut. Par conséquent, les services doivent traiter rapidement les intents entrants et ne jamais effectuer de longs calculs lorsqu'ils y répondent. Si des appels importants ou bloquants sont attendus, vous devez effectuer ces tâches de manière asynchrone: soit à partir d'un autre thread que vous implémentez vous-même, soit en utilisant les nombreuses fonctionnalités du framework pour un traitement asynchrone.
Par exemple, lorsque vous utilisez un MediaPlayer
à partir de votre thread principal, vous devez appeler prepareAsync()
plutôt que prepare()
, et implémenter un MediaPlayer.OnPreparedListener
afin d'être averti lorsque la préparation est terminée et que vous pouvez commencer à jouer.
Par 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 sont normalement signalées par une exception ou un code d'erreur. Toutefois, lorsque vous utilisez des ressources asynchrones, vous devez vous assurer que votre application est informée des erreurs de manière appropriée. Dans le cas d'une MediaPlayer
, vous pouvez y parvenir en implémentant un 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! } }
N'oubliez pas que lorsqu'une erreur se produit, MediaPlayer
passe à l'état Error (erreur) (consultez la documentation de la classe MediaPlayer
pour obtenir le schéma d'état complet). Vous devez alors la réinitialiser avant de pouvoir l'utiliser à nouveau.
Utiliser des wakelocks
Lorsque vous concevez des 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 la batterie pendant que l'appareil est en veille, le système tente de désactiver toutes les fonctionnalités du téléphone qui ne sont pas nécessaires, y compris le processeur et le matériel Wi-Fi. Toutefois, si votre service lit ou diffuse de la musique en streaming, vous devez empêcher le système d'interférer avec la lecture.
Pour vous assurer que votre service continue de fonctionner dans ces conditions, vous devez utiliser des wakelocks. Un wakelock est un moyen de signaler au système que votre application utilise une fonctionnalité qui doit rester disponible même si le téléphone est inactif.
Remarque:Vous devez toujours utiliser les wakelocks avec parcimonie et ne les maintenir enfoncés que le temps vraiment nécessaire, car ils réduisent considérablement l'autonomie de la batterie de l'appareil.
Pour vous assurer que le processeur continue de s'exécuter pendant la lecture de votre MediaPlayer
, appelez la méthode setWakeMode()
lors de l'initialisation de votre MediaPlayer
. Une fois cette opération effectuée, MediaPlayer
conserve le verrou spécifié pendant la lecture et le libère lorsqu'il est mis en pause ou 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);
Toutefois, le wakelock acquis dans cet exemple garantit uniquement que le processeur reste activé. Si vous diffusez du contenu multimédia en streaming sur le réseau et que vous utilisez le Wi-Fi, vous souhaiterez probablement conserver également un WifiLock
, que vous devez acquérir et publier manuellement. Ainsi, lorsque vous commencez à préparer le MediaPlayer
avec l'URL distante, vous devez créer et acquérir le verrou Wi-Fi.
Par 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 votre contenu multimédia, ou lorsque vous n'avez plus besoin du réseau, vous devez débloquer le verrouillage:
Kotlin
wifiLock.release()
Java
wifiLock.release();
Nettoyage en cours
Comme indiqué précédemment, un objet MediaPlayer
peut consommer une quantité importante de ressources système. Vous ne devez donc le conserver que pendant la durée nécessaire et appeler release()
lorsque vous n'en avez plus besoin. Il est important d'appeler explicitement cette méthode de nettoyage plutôt que d'utiliser la récupération de mémoire du système. En effet, le récupérateur de mémoire peut mettre un certain temps à récupérer le MediaPlayer
, car il est uniquement sensible aux besoins de mémoire et non à la pénurie d'autres ressources multimédias.
Ainsi, lorsque vous utilisez un service, vous devez toujours remplacer la méthode onDestroy()
pour vous assurer de publier le 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(); } }
Vous devez toujours rechercher d'autres opportunités pour libérer votre MediaPlayer
, en plus de le libérer lors de son arrêt. Par exemple, si vous vous attendez à ne pas pouvoir lire le contenu multimédia pendant une période prolongée (après avoir perdu la priorité audio, par exemple), vous devez absolument libérer votre MediaPlayer
existant et le recréer plus tard. En revanche, si vous prévoyez d'arrêter la lecture pendant une courte période, vous devez probablement conserver votre MediaPlayer
pour éviter de devoir le créer et le préparer à nouveau.
Gestion des droits numériques (DRM)
À partir d'Android 8.0 (niveau d'API 26), MediaPlayer
inclut des API compatibles avec la lecture de contenus protégés par DRM. Ils sont semblables à l'API de bas niveau fournie par MediaDrm
, mais ils fonctionnent à un niveau plus élevé et n'exposent pas les objets extracteurs, drm et cryptos sous-jacents.
Bien que l'API DRM de MediaPlayer n'offre pas toutes les fonctionnalités de MediaDrm
, elle est compatible avec les cas d'utilisation les plus courants. L'implémentation 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 les nouvelles méthodes DRM MediaPlayer dans une implémentation synchrone simple.
Pour gérer des contenus multimédias contrôlés par DRM, vous devez inclure les nouvelles méthodes en plus du flux habituel d'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éfinir sa source à l'aide de setDataSource()
, comme d'habitude. Ensuite, pour utiliser la DRM, procédez comme suit:
- Si vous souhaitez que votre application effectue une configuration personnalisée, définissez une interface
OnDrmConfigHelper
et associez-la au lecteur à l'aide desetOnDrmConfigHelper()
. - Appelez
prepare()
. - Appelez
getDrmInfo()
. Si la source comporte du contenu DRM, la méthode renvoie une valeurMediaPlayer.DrmInfo
non nulle.
Si MediaPlayer.DrmInfo
existe:
- Examinez le plan des UUID disponibles et choisissez-en un.
- Préparez la configuration DRM pour la source actuelle en appelant
prepareDrm()
. - Si vous avez créé et enregistré un rappel
OnDrmConfigHelper
, il est appelé pendant l'exécution deprepareDrm()
. Cela vous permet d'effectuer une configuration personnalisée des propriétés DRM avant d'ouvrir la session DRM. Le rappel est appelé de manière synchrone dans le thread qui a appeléprepareDrm()
. Pour accéder aux propriétés DRM, appelezgetDrmPropertyString()
etsetDrmPropertyString()
. Évitez d'effectuer des opérations longues. - Si l'appareil n'a pas encore été provisionné,
prepareDrm()
accède également au serveur de provisionnement pour le provisionner. Cette opération peut prendre un certain temps, en fonction de la connectivité réseau. - Pour obtenir un tableau d'octets de requête de clé opaque à envoyer à un serveur de licences, appelez
getKeyRequest()
. - Pour informer le moteur DRM de la réponse de clé reçue du serveur de licences, appelez
provideKeyResponse()
. Le résultat dépend du type de requête de clé :- Si la réponse concerne une requête de clé hors connexion, le résultat est un identifiant de jeu de clés. Vous pouvez utiliser cet identifiant de jeu de clés avec
restoreKeys()
pour restaurer les clés dans une nouvelle session. - Si la réponse concerne une requête de streaming ou de libération, le résultat est nul.
- Si la réponse concerne une requête de clé hors connexion, le résultat est un identifiant de jeu de clés. Vous pouvez utiliser cet identifiant de jeu de clés avec
Exécuter prepareDrm()
de manière asynchrone
Par défaut, prepareDrm()
s'exécute de manière synchrone et bloque jusqu'à la fin de la préparation. Cependant, la toute première préparation DRM sur un nouvel appareil peut également nécessiter un provisionnement, géré en interne par prepareDrm()
, et peut prendre un certain temps en raison de l'opération réseau impliquée. Vous pouvez éviter le blocage sur prepareDrm()
en définissant et en définissant un MediaPlayer.OnDrmPreparedListener
.
Lorsque vous définissez un OnDrmPreparedListener
, prepareDrm()
effectue le provisionnement (si nécessaire) et la préparation en arrière-plan. Une fois le provisionnement et la préparation terminés, l'écouteur est appelé. Vous ne devez faire aucune hypothèse concernant la séquence d'appel ni le thread dans lequel l'écouteur s'exécute (sauf si l'écouteur est enregistré auprès d'un thread de gestionnaire).
L'écouteur peut être appelé avant ou après le renvoi de 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 de la DRM et le MediaPlayer.OnDrmPreparedListener
pour démarrer le lecteur.
Elles fonctionnent 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 le schéma CENC (Common Encryption Scheme) et les contenus multimédias chiffrés au niveau de l'échantillon HLS (Method=Sample-AES) pour les types de flux élémentaires H.264 et AAC. Auparavant, le chiffrement du segment complet (MÉTHODE=AES-128) était pris en charge.
Récupérer des fichiers multimédias à partir d'un ContentResolver
Une autre fonctionnalité qui peut être utile dans une application de lecteur multimédia est la possibilité de récupérer de la musique présente sur l'appareil de l'utilisateur. Pour ce faire, interrogez ContentResolver
pour obtenir des médias 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 couvrent des sujets liés à l'enregistrement, au stockage et à la lecture de contenus audio et vidéo.