Audio de fond dans Android avec MediaSessionCompat

L'une des utilisations les plus courantes pour les appareils mobiles est la lecture audio via des services de diffusion de musique, des podcasts téléchargés ou tout autre nombre de sources audio. Bien qu’il s’agisse d’une fonctionnalité assez courante, elle est difficile à mettre en œuvre, car elle nécessite de nombreux éléments différents qui doivent être conçus correctement pour offrir à votre utilisateur une expérience Android complète.. 

Dans ce tutoriel, vous en apprendrez davantage sur MediaSessionCompat depuis la bibliothèque de support Android, et comment l'utiliser pour créer un service audio d'arrière-plan approprié pour vos utilisateurs.

Installer

La première chose à faire est d’inclure la bibliothèque de support Android dans votre projet. Cela peut être fait en ajoutant la ligne suivante dans votre module build.gradle fichier sous le noeud des dépendances.

compiler 'com.android.support:support-v13:24.2.1'

Après avoir synchronisé votre projet, créez une nouvelle classe Java. Pour cet exemple, je vais appeler la classe BackgroundAudioService. Cette classe devra être étendue MediaBrowserServiceCompat. Nous allons également implémenter les interfaces suivantes: MediaPlayer.OnCompletionListener et AudioManager.OnAudioFocusChangeListener.

Maintenant que votre MediaBrowserServiceCompat la mise en œuvre est créée, prenons un moment pour mettre à jour AndroidManifest.xml avant de retourner à cette classe. En haut de la classe, vous devrez demander le VERROUILLAGE DE RÉVEIL autorisation.

Ensuite, dans le application noeud, déclarez votre nouveau service avec ce qui suit filtre d'intention articles. Celles-ci permettront à votre service d'intercepter les boutons de commande, les événements liés aux écouteurs et la navigation multimédia pour des périphériques tels qu'Android Auto (bien que nous ne fassions rien avec Android Auto pour ce didacticiel, une assistance de base est toujours requise pour cela. MediaBrowserServiceCompat).

      

Enfin, vous devrez déclarer l’utilisation de la MediaButtonReceiver de la bibliothèque de support Android. Cela vous permettra d'intercepter les interactions des boutons de contrôle des médias et les événements du casque sur les appareils exécutant KitKat et les versions antérieures..

     

Maintenant que votre AndroidManifest.xml le fichier est terminé, vous pouvez le fermer. Nous allons également créer une autre classe nommée MediaStyleHelper, qui a été écrit par Ian Lake, développeur avocat chez Google, pour nettoyer la création de notifications de style multimédia.

Classe publique MediaStyleHelper / ** * Construire une notification en utilisant les informations de la session multimédia donnée. Utilise beaucoup * de @link MediaMetadataCompat # getDescription () pour extraire les informations appropriées. * @param context Contexte utilisé pour construire la notification. * @param mediaSession Session de média pour obtenir des informations. * @return Une notification pré-construite avec les informations de la session multimédia donnée. * / public statique NotificationCompat.Builder de (contexte de contexte, MediaSessionCompat mediaSession) contrôleur MediaControllerCompat = mediaSession.getController (); MediaMetadataCompat mediaMetadata = controller.getMetadata (); MediaDescriptionCompat description = mediaMetadata.getDescription (); Générateur NotificationCompat.Builder = new NotificationCompat.Builder (context); constructeur .setContentTitle (description.getTitle ()) .setContentText (description.getSubtitle ()) .setSubText (description.getDescription ()) .setLargeIcon (description.getIconBitmap ()) .setContentIntent (controller.getSessionActivity) .buildMediaButtonPendingIntent (context, PlaybackStateCompat.ACTION_STOP)) .setVisibility (NotificationCompat.VISIBILITY_PUBLIC); constructeur de retour; 

Une fois que cela est créé, allez-y et fermez le fichier. Nous nous concentrerons sur le service audio en arrière-plan dans la section suivante.

Construire le service audio d'arrière-plan

Il est maintenant temps de creuser le cœur de la création de votre application multimédia. Il y a quelques variables de membre que vous voudrez déclarer en premier pour cet exemple d'application: a Lecteur multimédia pour la lecture réelle, et un MediaSessionCompat objet qui gérera les métadonnées et les contrôles / états de lecture.

MediaPlayer privé mMediaPlayer; privé MediaSessionCompat mMediaSessionCompat;

De plus, vous aurez besoin d’un BroadcastReceiver qui écoute les changements dans l'état du casque. Pour garder les choses simples, ce récepteur mettra en pause le Lecteur multimédia, s'il joue.

broadcastReceiver privé mNoisyReceiver = new BroadcastReceiver () @Override public void onReceive (contexte de contexte, intention d'intention) if (mMediaPlayer! = null && mMediaPlayer.isPlaying ()) mMediaPlayer.pause (); ;

Pour la variable membre finale, vous allez créer un MediaSessionCompat.Callback objet, utilisé pour gérer l'état de lecture lorsque des actions de session multimédia se produisent.

private MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback () @Override public void onPlay () super.onPlay ();  @Override public void onPause () super.onPause ();  @Override public void onPlayFromMediaId (String mediaId, extras d'ensembles) super.onPlayFromMediaId (mediaId, extras); ;

Nous reviendrons sur chacune des méthodes ci-dessus plus tard dans ce didacticiel, car elles seront utilisées pour piloter les opérations dans notre application multimédia..

Il y a deux méthodes que nous devrons également déclarer, bien qu'ils n'aient rien à faire pour les besoins de ce tutoriel: onGetRoot () et onLoadChildren (). Vous pouvez utiliser le code suivant pour vos valeurs par défaut.

@Nullable @Override public BrowserRoot onGetRoot (@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) if (TextUtils.equals (clientPackageName, getPackageName ())) if new BrowserRoot (getString (Rstring.app_name,)) )  return null;  // Pas important pour le service audio général, requis pour la classe @Override public void onLoadChildren (@NonNull String parentId, @NonNull Résultat> result) result.sendResult (null); 

Enfin, vous voudrez remplacer le onStartCommand () méthode, qui est le point d'entrée dans votre Un service. Cette méthode prendra l’intention qui est transmise au Un service et l'envoyer au MediaButtonReceiver classe.

@Override public int onStartCommand (Intentity, Int flags, int startId) MediaButtonReceiver.handleIntent (mMediaSessionCompat, intent); return super.onStartCommand (intent, flags, startId); 

Initialiser toutes les choses

Maintenant que vos variables de membre de base sont créées, il est temps de tout initialiser. Nous ferons cela en appelant diverses méthodes d'assistance dans onCreate ().

@Override public void onCreate () super.onCreate (); initMediaPlayer (); initMediaSession (); initNoisyReceiver (); 

La première méthode, initMediaPlayer (), va initialiser le Lecteur multimédia objet que nous avons créé en haut de la classe, demande le verrouillage partiel du réveil (raison pour laquelle nous avons demandé cette autorisation dans AndroidManifest.xml) et régler le volume du lecteur.

void privé initMediaPlayer () mMediaPlayer = new MediaPlayer (); mMediaPlayer.setWakeMode (getApplicationContext (), PowerManager.PARTIAL_WAKE_LOCK); mMediaPlayer.setAudioStreamType (AudioManager.STREAM_MUSIC); mMediaPlayer.setVolume (1.0f, 1.0f); 

La prochaine méthode, initMediaSession (), est où nous initialisons le MediaSessionCompat objet et connectez-le aux boutons multimédias et aux méthodes de contrôle qui nous permettent de gérer la lecture et la saisie de l'utilisateur. Cette méthode commence par créer un Nom du composant objet qui pointe vers la bibliothèque de support Android MediaButtonReceiver classe, et utilise cela pour créer un nouveau MediaSessionCompat. Nous passons ensuite le MediaSession.Callback l’objet que nous avons créé précédemment et définissez les indicateurs nécessaires pour recevoir les entrées de boutons multimédias et les signaux de commande. Ensuite, nous créons un nouveau Intention pour gérer les entrées de bouton multimédia sur les appareils pré-Lollipop et définir le jeton de session multimédia pour notre service.

private void initMediaSession () ComponentName mediaButtonReceiver = new ComponentName (getApplicationContext (), MediaButtonReceiver.class); mMediaSessionCompat = new MediaSessionCompat (getApplicationContext (), "Tag", mediaButtonReceiver, null); mMediaSessionCompat.setCallback (mMediaSessionCallback); mMediaSessionCompat.setFlags (MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); Intention mediaButtonIntent = new Intent (Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setClass (this, MediaButtonReceiver.class); PendingIntent waitingIntent = PendingIntent.getBroadcast (this, 0, mediaButtonIntent, 0); mMediaSessionCompat.setMediaButtonReceiver (waitingIntent); setSessionToken (mMediaSessionCompat.getSessionToken ()); 

Enfin, nous allons enregistrer le BroadcastReceiver que nous avons créé au sommet de la classe afin que nous puissions écouter les événements de changement de casque.

private void initNoisyReceiver () // Gère les écouteurs débranchés. ne peut pas être effectué via un récepteur de manifeste IntentFilter filter = new IntentFilter (AudioManager.ACTION_AUDIO_BECOMING_NOISY); registerReceiver (mNoisyReceiver, filter); 

Gestion du focus audio

Maintenant que vous avez fini d'initialiser BroadcastReceiver, MediaSessionCompat et Lecteur multimédia objets, il est temps de se pencher sur la gestion du focus audio. 

Bien que nous puissions penser que nos propres applications audio sont les plus importantes pour le moment, d'autres applications de l'appareil rivaliseront pour créer leurs propres sons, telles qu'une notification par courrier électronique ou un jeu pour mobile. Afin de travailler avec ces différentes situations, le système Android utilise le focus audio pour déterminer comment l’audio doit être traité.. 

Le premier cas que nous voudrons gérer est le démarrage de la lecture et la tentative de réception du focus du périphérique. Dans ton MediaSessionCompat.Callback objet, aller dans le onPlay () méthode et ajouter la vérification de condition suivante.

@Override public void onPlay () super.onPlay (); if (! successRetrievedAudioFocus ()) return; 

Le code ci-dessus appellera une méthode d'assistance qui tente de récupérer le focus et, si elle ne le peut pas, elle retournera simplement. Dans une application réelle, vous souhaitez gérer les lectures audio ayant échoué de manière plus élégante.. successRetrievedAudioFocus () obtiendra une référence au système AudioManager, et essayez de demander le focus audio pour diffuser de la musique. Il retournera alors un booléen représentant si la demande a réussi ou non.

private boolean avec succèsRetrievedAudioFocus () AudioManager audioManager = (AudioManager) getSystemService (Context.AUDIO_SERVICE); int result = audioManager.requestAudioFocus (ceci, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); retourne le résultat == AudioManager.AUDIOFOCUS_GAIN; 

Vous remarquerez que nous passons aussi ce dans le requestAudioFocus () méthode, qui associe le OnAudioFocusChangeListener avec notre service. Il y a quelques états différents que vous voudrez écouter pour être un «bon citoyen» dans l'écosystème d'applications du périphérique..

  • AudioManager.AUDIOFOCUS_LOSS: Cela se produit lorsqu'une autre application a demandé le focus audio. Lorsque cela se produit, vous devez arrêter la lecture audio dans votre application..
  • AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: Cet état est activé lorsqu'une autre application souhaite lire de l'audio, mais il ne prévoit que la nécessité de la mise au point pour une courte période. Vous pouvez utiliser cet état pour mettre en pause votre lecture audio.
  • AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: Lorsque le focus audio est demandé, mais que l'état «canard» est activé, cela signifie que vous pouvez continuer la lecture, mais que vous devez baisser un peu le volume. Cela peut se produire lorsqu'un son de notification est joué par l'appareil.
  • AudioManager.AUDIOFOCUS_GAIN: Le dernier état dont nous allons discuter est AUDIOFOCUS_GAIN. C'est l'état à la fin d'une lecture audio pouvant être canalisée, et votre application peut reprendre son niveau précédent..

Un simplifié onAudioFocusChange () callback peut ressembler à ceci:

@Override public void onAudioFocusChange (int focusChange) commutateur (focusChange) case AudioManager.AUDIOFOCUS_LOSS: if (mMediaPlayer.isPlaying ()) mMediaPlayer.stop ();  Pause;  case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: mMediaPlayer.pause (); Pause;  case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: if (mMediaPlayer! = null) mMediaPlayer.setVolume (0.3f, 0.3f);  Pause;  case AudioManager.AUDIOFOCUS_GAIN: if (mMediaPlayer! = null) if (! mMediaPlayer.isPlaying ()) mMediaPlayer.start ();  mMediaPlayer.setVolume (1.0f, 1.0f);  Pause; 

Comprendre le MediaSessionCompat.Callback

Maintenant que vous avez une structure générale pour votre Un service, il est temps de plonger dans le MediaSessionCompat.Callback. Dans la dernière section, vous avez ajouté un petit peu à onPlay () pour vérifier si le focus audio a été accordé. Au-dessous de la déclaration conditionnelle, vous voudrez définir le MediaSessionCompat objet à actif, lui donner un état de STATE_PLAYING, et assignez les actions appropriées nécessaires pour créer des boutons de pause sur les contrôles de l'écran de verrouillage pré-Lollipop, les notifications téléphoniques et Android Wear.

@Override public void onPlay () super.onPlay (); if (! successRetrievedAudioFocus ()) return;  mMediaSessionCompat.setActive (true); setMediaPlaybackState (PlaybackStateCompat.STATE_PLAYING);…

le setMediaPlaybackState () méthode ci-dessus est une méthode d'assistance qui crée un PlaybackStateCompat.Builder objet et lui donne les actions et l'état appropriés, puis construit et associe un PlaybackStateCompat avec votre MediaSessionCompat objet.

void privé setMediaPlaybackState (état int) PlaybackStateCompat.Builder playbackstateBuilder = new PlaybackStateCompat.Builder (); if (state == PlaybackStateCompat.STATE_PLAYING) playbackstateBuilder.setActions (PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PAUSE);  else playbackstateBuilder.setActions (PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PLAY);  playbackstateBuilder.setState (état, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 0); mMediaSessionCompat.setPlaybackState (playbackstateBuilder.build ()); 

Il est important de noter que vous aurez besoin à la fois du ACTION_PLAY_PAUSE et soit ACTION_PAUSE ou ACTION_PLAY drapeaux dans vos actions afin d’obtenir les contrôles appropriés sur Android Wear.

Retour dans onPlay (), vous souhaitez afficher une notification de jeu associée à votre MediaSessionCompat objet en utilisant le MediaStyleHelper classe que nous avons définie précédemment, puis montrer que la notification.

showPlayingNotification () privé constructeur de NotificationCompat.Builder = MediaStyleHelper.from (BackgroundAudioService.this, mMediaSessionCompat); if (constructeur == null) return;  builder.addAction (nouvelle NotificationCompat.Action (android.R.drawable.ic_media_pause, "Pause", MediaButtonReceiver.buildMediaButtonPendingIntent (this, PlaybackStateCompat.ACTION_PLAY_PAUSE))); builder.setStyle (nouvelle NotificationCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificationManagerCompat.from (BackgroundAudioService.this) .notify (1, builder.build ()); 

Enfin, vous commencerez la Lecteur multimédia au bout du onPlay ().

@Override public void onPlay () super.onPlay ();… showPlayingNotification (); mMediaPlayer.start (); 

Lorsque le rappel reçoit une commande de pause, onPause () sera appelé. Ici, vous ferez une pause Lecteur multimédia, définir l'état à STATE_PAUSED, et montrer une notification en pause.

@Override public void onPause () super.onPause (); if (mMediaPlayer.isPlaying ()) mMediaPlayer.pause (); setMediaPlaybackState (PlaybackStateCompat.STATE_PAUSED); showPausedNotification (); 

Notre showPausedNotification () méthode d'assistance ressemblera à la showPlayNotification () méthode.

showPausedNotification () privé constructeur de NotificationCompat.Builder = MediaStyleHelper.from (this, mMediaSessionCompat); if (constructeur == null) return;  builder.addAction (nouvelle NotificationCompat.Action (android.R.drawable.ic_media_play, "Lecture", MediaButtonReceiver.buildMediaButtonPendingIntent (ceci, PlaybackStateCompat.ACTION_PLAY_PAUSE))); builder.setStyle (nouvelle NotificationCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificationManagerCompat.from (this) .notify (1, builder.build ()); 

La prochaine méthode dans le rappel que nous allons discuter, onPlayFromMediaId (), prend un Chaîne et un Paquet comme paramètres. C'est la méthode de rappel que vous pouvez utiliser pour modifier les pistes audio / le contenu de votre application.. 

Pour ce didacticiel, nous allons simplement accepter un ID de ressource brute et tenter de le lire, puis réinitialiser les métadonnées de la session. Comme vous êtes autorisé à passer un Paquet Dans cette méthode, vous pouvez l’utiliser pour personnaliser d’autres aspects de votre lecture multimédia, tels que la configuration d’un son de fond personnalisé pour une piste..

@Override public void onPlayFromMediaId (String mediaId, extras Bundle) super.onPlayFromMediaId (mediaId, extras); try AssetFileDescriptor afd = getResources (). openRawResourceFd (Integer.valueOf (mediaId)); if (afd == null) return;  try mMediaPlayer.setDataSource (afd.getFileDescriptor (), afd.getStartOffset (), afd.getLength ());  catch (IllegalStateException e) mMediaPlayer.release (); initMediaPlayer (); mMediaPlayer.setDataSource (afd.getFileDescriptor (), afd.getStartOffset (), afd.getLength ());  afd.close (); initMediaSessionMetadata ();  catch (IOException e) return;  essayez mMediaPlayer.prepare ();  catch (IOException e)  // Utilisez des extras ici si vous le souhaitez

Maintenant que nous avons discuté des deux méthodes principales de ce rappel que vous utiliserez dans vos applications, il est important de savoir qu'il existe d'autres méthodes facultatives que vous pouvez utiliser pour personnaliser votre service. Certaines méthodes incluent onSeekTo (), qui vous permet de changer la position de lecture de votre contenu, et sur commande(), qui acceptera un Chaîne désignant le type de commande, un Paquet pour des informations supplémentaires sur la commande, et un Résultat Récepteur callback, qui vous permettra d’envoyer des commandes personnalisées à votre Un service.

@Override public void onCommand (Commande String, Extras Bundle, ResultReceiver cb) super.onCommand (commande, extras, cb); if (COMMAND_EXAMPLE.equalsIgnoreCase (commande)) // Commande personnalisée ici @Override public void onSeekTo (pos long) super.onSeekTo (pos); 

Abattre

Lorsque notre fichier audio sera terminé, nous voudrons décider de notre prochaine action. Bien que vous souhaitiez peut-être lire la piste suivante dans votre application, nous allons garder les choses simples et publier le Lecteur multimédia.

@Override public void onCompletion (MediaPlayer mediaPlayer) if (mMediaPlayer! = Null) mMediaPlayer.release (); 

Enfin, nous voudrons faire quelques choses dans le onDestroy () méthode de notre Un service. Commencez par obtenir une référence au service système. AudioManager, et appeler abandonAudioFocus () avec notre AudioFocusChangeListener en tant que paramètre, qui avertira les autres applications de l'appareil que vous abandonnez le focus audio. Ensuite, annulez l'enregistrement du BroadcastReceiver qui a été configuré pour écouter les changements de casque et relâchez le MediaSessionCompat objet. Enfin, vous voudrez annuler la notification de contrôle de lecture.

@Override public void onDestroy () super.onDestroy (); AudioManager audioManager = (AudioManager) getSystemService (Context.AUDIO_SERVICE); audioManager.abandonAudioFocus (this); unregisterReceiver (mNoisyReceiver); mMediaSessionCompat.release (); NotificationManagerCompat.from (this) .cancel (1); 

À ce stade, vous devriez avoir une base audio de travail de base Un service en utilisant MediaSessionCompat pour le contrôle de la lecture sur les appareils. Bien que la création du service ait déjà été très complexe, vous devriez pouvoir contrôler la lecture à partir de votre application, une notification, des contrôles de verrouillage de l'écran sur les appareils antérieurs à Lollipop (Lollipop et les versions supérieures utiliseront la notification sur l'écran de verrouillage), et à partir de périphériques, tels que Android Wear, une fois le Un service a été commencé.

Démarrer et contrôler le contenu d'une activité

Bien que la plupart des contrôles soient automatiques, vous aurez encore un peu de travail pour démarrer et contrôler une session multimédia à partir de vos contrôles in-app. À tout le moins, vous voudrez un MediaBrowserCompat.ConnectionCallback, MediaControllerCompat.CallbackMediaBrowserCompat, et MediaControllerCompat objets créés dans votre application.

MediaControllerCompat.Callback aura une méthode appelée onPlaybackStateChanged () qui reçoit les changements dans l'état de lecture et peut être utilisé pour garder votre interface utilisateur synchronisée.

private MediaControllerCompat.Callback mMediaControllerCompatCallback = new MediaControllerCompat.Callback () @Override public void onPlaybackStateChanged (état PlaybackStateCompat) super.onPlaybackStateChanged (état); if (state == null) return;  switch (state.getState ()) case PlaybackStateCompat.STATE_PLAYING: mCurrentState = STATE_PLAYING; Pause;  case PlaybackStateCompat.STATE_PAUSED: mCurrentState = STATE_PAUSED; Pause; ;

MediaBrowserCompat.ConnectionCallback a un onConnected () méthode qui sera appelée quand un nouveau MediaBrowserCompat l'objet est créé et connecté. Vous pouvez l'utiliser pour initialiser votre MediaControllerCompat objet, liez-le à votre MediaControllerCompat.Callback, et l'associer à MediaSessionCompat de ton Un service. Une fois que cela est terminé, vous pouvez démarrer la lecture audio à partir de cette méthode.

private MediaBrowserCompat.ConnectionCallback mMediaBrowserCompatConnectionCallback = new MediaBrowserCompat.ConnectionCallback () ) @Override public void onConnected () super.onConnected (); try mMediaControllerCompat = new MediaControllerCompat (MainActivity.this, mMediaBrowserCompat.getSessionToken ()); mMediaControllerCompat.registerCallback (mMediaControllerCompatCallback); setSupportMediaController (mMediaControllerCompat); getSupportMediaController (). getTransportControls (). playFromMediaId (String.valueOf (R.raw.warner_tautz_off_broadway), null);  catch (RemoteException e) ;

Vous remarquerez que l'extrait de code ci-dessus utilise getSupportMediaController (). getTransportControls () communiquer avec la session média. En utilisant la même technique, vous pouvez appeler onPlay () et onPause () dans votre service audio MediaSessionCompat.Callback objet.

if (mCurrentState == STATE_PAUSED) getSupportMediaController (). getTransportControls (). play (); mCurrentState = STATE_PLAYING;  else if (getSupportMediaController (). getPlaybackState (). getState () == PlaybackStateCompat.STATE_PLAYING) getSupportMediaController (). getTransportControls (). pause ();  mCurrentState = STATE_PAUSED; 

Lorsque vous avez terminé votre lecture audio, vous pouvez suspendre le service audio et déconnecter votre MediaBrowserCompat objet, ce que nous ferons dans ce tutoriel lorsque cela Activité est détruit.

@Override protected void onDestroy () super.onDestroy (); if (getSupportMediaController (). getPlaybackState (). getState () == PlaybackStateCompat.STATE_PLAYING) getSupportMediaController (). getTransportControls (). pause ();  mMediaBrowserCompat.disconnect (); 

Emballer

Ouf! Comme vous pouvez le constater, la création et l'utilisation correcte d'un service audio en arrière-plan comportent de nombreux éléments en mouvement.. 

Dans ce didacticiel, vous avez créé un service qui lit un fichier audio simple, écoute les modifications du focus audio et crée des liens vers MediaSessionCompat pour fournir un contrôle de lecture universel sur les appareils Android, y compris les combinés et Android Wear. Si vous rencontrez des obstacles tout au long de ce didacticiel, je vous recommande vivement de consulter le code de projet Android associé sur le GitHub d’Envato Tuts +..

Et découvrez certains de nos autres cours et tutoriels Android ici sur Envato Tuts+!