Achtergrondaudio in Android met MediaSessionCompat

Een van de populairste toepassingen voor mobiele apparaten is het afspelen van audio via services voor muziekstreaming, gedownloade podcasts of een ander aantal audiobronnen. Hoewel dit een vrij algemene functie is, is het moeilijk te implementeren, met veel verschillende onderdelen die correct moeten worden gebouwd om uw gebruiker de volledige Android-ervaring te geven. 

In deze tutorial leert u meer over MediaSessionCompat van de Android-ondersteuningsbibliotheek en hoe deze kan worden gebruikt om een ​​juiste achtergrondaudiodienst voor uw gebruikers te creëren.

Opstelling

Het eerste dat u moet doen, is de Android-ondersteuningsbibliotheek opnemen in uw project. Dit kan gedaan worden door de volgende regel toe te voegen aan uw modules build.gradle bestand onder het knooppunt afhankelijkheden.

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

Nadat u uw project hebt gesynchroniseerd, maakt u een nieuwe Java-klasse. Voor dit voorbeeld zal ik de klas bellen BackgroundAudioService. Deze klasse moet worden uitgebreid MediaBrowserServiceCompat. We zullen ook de volgende interfaces implementeren: MediaPlayer.OnCompletionListener en AudioManager.OnAudioFocusChangeListener.

Nu dat van jou MediaBrowserServiceCompat implementatie is gemaakt, laten we even de tijd nemen om bij te werken AndroidManifest.xml voordat je terugkeert naar deze les. In de top van de klas moet je de WAKE_LOCK toestemming.

Vervolgens, binnen de toepassing knooppunt, verklaar uw nieuwe service met het volgende intent-filter items. Hiermee kunt u uw service gebruiken om bedieningsknoppen, hoofdtelefoongebeurtenissen en mediabrowsing voor apparaten te onderscheppen, zoals Android Auto (hoewel we in deze zelfstudie niets met Android Auto zullen doen, is enige basisondersteuning hiervoor nog steeds vereist door Android Auto). MediaBrowserServiceCompat).

      

Ten slotte moet u het gebruik van het MediaButtonReceiver van de Android-ondersteuningsbibliotheek. Hiermee kunt u interacties tussen mediabesturingsknoppen en koptelefoongebeurtenissen op apparaten met KitKat en eerder onderscheppen.

     

Nu dat van jou AndroidManifest.xml bestand is voltooid, kunt u het sluiten. We gaan ook een andere klasse maken met de naam MediaStyleHelper, die werd geschreven door Ian Lake, Developer Advocate bij Google, om het maken van mediastijlmeldingen op te schonen.

public class MediaStyleHelper / ** * Bouw een melding op met behulp van de informatie uit de gegeven mediasessie. Maakt intensief gebruik * van @link MediaMetadataCompat # getDescription () om de juiste informatie te extraheren. * @param-context Context voor het samenstellen van de melding. * @param mediaSession Media-sessie om informatie te krijgen. * @return Een vooraf aangemaakte melding met informatie uit de gegeven mediasessie. * / public static NotificationCompat.Builder from (Context-context, MediaSessionCompat mediaSession) MediaControllerCompat-controller = mediaSession.getController (); MediaMetadataCompat mediaMetadata = controller.getMetadata (); MediaDescriptionCompat description = mediaMetadata.getDescription (); NotificationCompat.Builder builder = new NotificationCompat.Builder (context); builder .setContentTitle (description.getTitle ()) .setContentText (description.getSubtitle ()) .setSubText (description.getDescription ()) .setLargeIcon (description.getIconBitmap ()) .setContentIntent (controller.getSessionActivity ()) .setDeleteIntent (MediaButtonReceiver .buildMediaButtonPendingIntent (context, PlaybackStateCompat.ACTION_STOP)) .setVisibility (NotificationCompat.VISIBILITY_PUBLIC); terugkeer bouwer; 

Als dat eenmaal is aangemaakt, ga je gang en sluit je het bestand. We zullen ons in de volgende sectie concentreren op de achtergrondaudiodienst.

De achtergrondaudiodienst uitbouwen

Nu is het tijd om diep in te gaan op het creëren van je media-app. Er zijn een paar lidvariabelen die u als eerste wilt declareren voor deze voorbeeld-app: Mediaspeler voor het daadwerkelijke afspelen en a MediaSessionCompat object dat metadata en besturingselementen / toestanden voor afspelen beheert.

privé MediaPlayer mMediaPlayer; private MediaSessionCompat mMediaSessionCompat;

Bovendien heeft u een Uitzending ontvanger die luistert naar veranderingen in de hoofdtelefoonstatus. Om de dingen eenvoudig te houden, zal deze ontvanger de Mediaspeler, als het speelt.

private BroadcastReceiver mNoisyReceiver = new BroadcastReceiver () @Override public void onReceive (Context context, Intent intent) if (mMediaPlayer! = null &&MMediaPlayer.isPlaying ()) mMediaPlayer.pause (); ;

Voor de laatste lidvariabele moet je een maken MediaSessionCompat.Callback object, dat wordt gebruikt voor het afhandelen van de afspeelstatus wanneer acties met mediasessies plaatsvinden.

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, bundel extra's) super.onPlayFromMediaId (mediaId, extra's); ;

We zullen later in deze tutorial terugkomen op elk van de bovenstaande methoden, omdat deze worden gebruikt om de bewerkingen in onze media-app te stimuleren.

Er zijn twee methoden die we ook moeten verklaren, hoewel ze niets hoeven te doen voor de doeleinden van deze zelfstudie: onGetRoot () en onLoadChildren (). U kunt de volgende code gebruiken voor uw standaardwaarden.

@Nullable @Override public BrowserRoot onGetRoot (@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) if (textUtils.equals (clientPackageName, getPackageName ())) retourneer nieuwe BrowserRoot (getString (R.string.app_name), null );  return null;  // Niet belangrijk voor algemene audioservice, vereist voor class @Override public void onLoadChildren (@NonNull String parentId, @NonNull Result> resultaat) result.sendResult (null); 

Ten slotte wilt u de onStartCommand () methode, dat is het toegangspunt tot uw Service. Deze methode neemt de intentie die wordt doorgegeven aan de Service en stuur het naar de MediaButtonReceiver klasse.

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

Alle dingen initialiseren

Nu de variabelen van uw basisleden zijn gemaakt, wordt het tijd om alles te initialiseren. We doen dit door verschillende hulpmethoden te gebruiken in onCreate ().

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

De eerste methode, initMediaPlayer (), initialiseert de Mediaspeler object dat we boven in de klas hebben gemaakt, vraag om gedeeltelijke wake lock (daarom hebben we die toestemming nodig in AndroidManifest.xml) en stel het volume van de speler in.

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

De volgende methode, initMediaSession (), is waar we het MediaSessionCompat object en bedraad het met de mediaknoppen en besturingsmethoden waarmee we het afspelen en de gebruikersinvoer kunnen verwerken. Deze methode begint met het maken van een componentnaam object dat naar de ondersteuningsbibliotheek van Android verwijst MediaButtonReceiver klasse, en gebruikt dat om een ​​nieuw te maken MediaSessionCompat. We passeren dan de MediaSession.Callback object dat we eerder hebben gemaakt en stel de vlaggen in die nodig zijn voor het ontvangen van mediaknopsingangen en besturingssignalen. Vervolgens maken we een nieuwe voornemen voor het omgaan met mediaknoopsingangen op pre-Lollipop-apparaten en het mediasessietoken in te stellen voor onze service.

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

Ten slotte registreren we het Uitzending ontvanger die we hebben gemaakt aan de top van de klas, zodat we kunnen luisteren naar gebeurtenissen voor het veranderen van hoofdtelefoon.

private void initNoisyReceiver () // Behandelt hoofdtelefoons zonder stekker. kan niet worden gedaan via een manifeste ontvanger IntentFilter filter = new IntentFilter (AudioManager.ACTION_AUDIO_BECOMING_NOISY); registerReceiver (mNoisyReceiver, filter); 

Omgaan met audiofocus

Nu bent u klaar met het initialiseren Uitzending ontvanger, MediaSessionCompat en Mediaspeler objecten, het is tijd om te kijken naar de omgang met de audiofocus. 

Hoewel we misschien denken dat onze eigen audio-apps op dit moment het belangrijkst zijn, concurreren andere apps op het apparaat om hun eigen geluiden te maken, zoals een e-mailmelding of een mobiel spel. Om met deze verschillende situaties te werken, gebruikt het Android-systeem audiofocus om te bepalen hoe audio moet worden verwerkt. 

Het eerste geval dat we willen behandelen, is het starten van het afspelen en proberen de focus van het apparaat te ontvangen. In uw MediaSessionCompat.Callback object, ga naar de onPlay () methode en voeg de volgende voorwaardecontrole toe.

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

De bovenstaande code roept een hulpmethode aan die probeert de focus op te halen, en als dat niet het geval is, zal het gewoon terugkeren. In een echte app zou je een mislukte audioweergave eenvoudiger willen afhandelen. successfullyRetrievedAudioFocus () krijgt een verwijzing naar het systeem AudioManager, en probeer audiofocus op te vragen voor het streamen van muziek. Het zal dan a terugkeren boolean die aangeeft of het verzoek is gelukt.

private boolean successfulRetrievedAudioFocus () AudioManager audioManager = (AudioManager) getSystemService (Context.AUDIO_SERVICE); int resultaat = audioManager.requestAudioFocus (dit, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); resultaat teruggeven == AudioManager.AUDIOFOCUS_GAIN; 

Je zult merken dat we ook voorbijgaan deze in de requestAudioFocus () methode, die de associeert OnAudioFocusChangeListener met onze service. Er zijn een paar verschillende staten waar je naar wilt luisteren om een ​​"goede burger" te zijn in het app-ecosysteem van het apparaat.

  • AudioManager.AUDIOFOCUS_LOSS: Dit gebeurt wanneer een andere app om audiofocus heeft gevraagd. Wanneer dit gebeurt, moet u het afspelen van audio stoppen in uw app.
  • AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: Deze status wordt ingevoerd wanneer een andere app audio wil afspelen, maar verwacht slechts een korte tijd focus te hebben. U kunt deze status gebruiken om uw audioweergave te pauzeren.
  • AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: Als er om audio-focus wordt gevraagd, maar er een 'kan duck'-status wordt gegenereerd, betekent dit dat u door kunt gaan met afspelen, maar het volume iets lager zou moeten zetten. Dit kan gebeuren wanneer een waarschuwingsgeluid door het apparaat wordt gespeeld.
  • AudioManager.AUDIOFOCUS_GAIN: De laatste staat die we zullen bespreken is AUDIOFOCUS_GAIN. Dit is de toestand wanneer een audio-afspeelfunctie voor duckable is voltooid en uw app kan worden hervat op de voorgaande niveaus.

Een vereenvoudigde onAudioFocusChange () callback kan er als volgt uitzien:

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

De MediaSessionCompat.Callback begrijpen

Nu heb je een algemene structuur voor je samen Service, het is tijd om in de MediaSessionCompat.Callback. In het laatste gedeelte waaraan je een beetje hebt toegevoegd onPlay () om te controleren of de audiofocus is toegekend. Onder de voorwaardelijke verklaring, wil je de MediaSessionCompat object van actief, geef het een staat van STATE_PLAYING, en wijs de juiste acties toe die nodig zijn om pauzeknoppen te maken op pre-Lollipop lock-schermbesturingselementen, telefoon- en Android Wear-meldingen.

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

De setMediaPlaybackState () bovenstaande methode is een hulpmethode die een PlaybackStateCompat.Builder object en geeft het de juiste acties en staat, en vervolgens bouwt en associeert een PlaybackStateCompat met uw MediaSessionCompat voorwerp.

private void setMediaPlaybackState (int state) 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 (state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 0); mMediaSessionCompat.setPlaybackState (playbackstateBuilder.build ()); 

Het is belangrijk om op te merken dat u zowel de ACTION_PLAY_PAUSE en ook ACTION_PAUSE of ACTION_PLAY vlaggen in je acties om de juiste controle over Android Wear te krijgen.

Terug in onPlay (), je wilt een speelbericht weergeven dat is gekoppeld aan je MediaSessionCompat object met behulp van de MediaStyleHelper klasse die we eerder hebben gedefinieerd en vervolgens die melding weergeven.

private void showPlayingNotification () NotificationCompat.Builder builder = MediaStyleHelper.from (BackgroundAudioService.this, mMediaSessionCompat); if (builder == null) ga terug;  builder.addAction (nieuwe NotificationCompat.Action (android.R.drawable.ic_media_pause, "Pause", MediaButtonReceiver.buildMediaButtonPendingIntent (this, PlaybackStateCompat.ACTION_PLAY_PAUSE))); builder.setStyle (nieuwe NotificationCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificationManagerCompat.from (BackgroundAudioService.this) .notify (1, builder.build ()); 

Ten slotte start u de Mediaspeler aan het einde van onPlay ().

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

Wanneer de callback een pauze-opdracht ontvangt, onPause () zal gebeld worden. Hier pauzeert u de Mediaspeler, stel de staat in op STATE_PAUSED, en toon een gepauzeerde melding.

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

Onze showPausedNotification () helper methode zal lijken op de showPlayNotification () methode.

private void showPausedNotification () NotificationCompat.Builder builder = MediaStyleHelper.from (this, mMediaSessionCompat); if (builder == null) ga terug;  builder.addAction (nieuwe NotificationCompat.Action (android.R.drawable.ic_media_play, "Play", MediaButtonReceiver.buildMediaButtonPendingIntent (this, PlaybackStateCompat.ACTION_PLAY_PAUSE))); builder.setStyle (nieuwe NotificationCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificationManagerCompat.from (this) .notify (1, builder.build ()); 

De volgende methode in de callback die we zullen bespreken, onPlayFromMediaId (), duurt een Draad en een Bundel als parameters. Dit is de callback-methode die u kunt gebruiken voor het wijzigen van audiotracks / inhoud in uw app. 

Voor deze zelfstudie accepteren we gewoon een onbewerkte resource-ID en proberen die af te spelen en vervolgens de metadata van de sessie opnieuw te initialiseren. Zoals je mag passeren Bundel bij deze methode kunt u hiermee andere aspecten van het afspelen van media aanpassen, zoals het instellen van een aangepast achtergrondgeluid voor een nummer.

@Override public void onPlayFromMediaId (String mediaId, bundel extra's) super.onPlayFromMediaId (mediaId, extra's); probeer AssetFileDescriptor afd = getResources (). openRawResourceFd (Integer.valueOf (mediaId)); if (afd == null) terug;  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) terug;  probeer mMediaPlayer.prepare ();  catch (IOException e)  // Werk hier met extra's als u wilt

Nu we de twee belangrijkste methoden in deze callback hebben besproken die u in uw apps zult gebruiken, is het belangrijk om te weten dat er andere optionele methoden zijn die u kunt gebruiken om uw service aan te passen. Sommige methoden omvatten onSeekTo (), waarmee u de afspeelpositie van uw inhoud kunt wijzigen, en op commando(), die een a zal accepteren Draad geeft het type commando aan, a Bundel voor extra informatie over de opdracht, en a ResultReceiver callback, waarmee u aangepaste opdrachten naar uw kunt verzenden Service.

@Override public void onCommand (String-commando, Bundel-extra's, ResultReceiver cb) super.onCommand (command, extras, cb); if (COMMAND_EXAMPLE.equalsIgnoreCase (opdracht)) // Aangepaste opdracht hier @Override openbare ongeldig onSeekTo (lange pos) super.onSeekTo (pos); 

Tearing Down

Wanneer ons audiobestand is voltooid, willen we beslissen wat onze volgende actie zal zijn. Hoewel je misschien het volgende nummer in je app wilt spelen, houden we de dingen eenvoudig en geven we het volgende vrij Mediaspeler.

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

Ten slotte willen we een paar dingen doen in de onDestroy () methode van onze Service. Zoek eerst een verwijzing naar de systeemservices AudioManager, en bel abandonAudioFocus () met onze AudioFocusChangeListener als een parameter, die andere apps op het apparaat op de hoogte brengt dat u de audio-focus opgeeft. Maak de registratie vervolgens ongedaan Uitzending ontvanger die was ingesteld om te luisteren naar veranderingen van de hoofdtelefoon, en de MediaSessionCompat voorwerp. Ten slotte wilt u de melding voor het afspelen van het afspelen annuleren.

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

Op dit moment zou je een werkende basis achtergrondaudio moeten hebben Service gebruik makend van MediaSessionCompat voor afspeelcontrole op verschillende apparaten. Hoewel er al veel is gedaan om de service te maken, moet u het afspelen vanuit uw app, een melding of vergrendelingsschermbediening op pre-Lollipop-apparaten kunnen regelen (Lollipop en hoger gebruiken de melding op het vergrendelingsscherm), en van randapparatuur, zoals Android Wear, zodra de Service is begonnen.

Inhoud starten en beheren vanuit een activiteit

Hoewel de meeste bedieningselementen automatisch zijn, hebt u nog steeds een beetje werk nodig om een ​​mediasessie te starten en beheren via uw in-app-besturingselementen. Op zijn minst wil je een MediaBrowserCompat.ConnectionCallback, MediaControllerCompat.CallbackMediaBrowserCompat, en MediaControllerCompat objecten gemaakt in uw app.

MediaControllerCompat.Callback zal een methode hebben genaamd onPlaybackStateChanged () die wijzigingen in de afspeelstatus ontvangt en kan worden gebruikt om uw gebruikersinterface synchroon te houden.

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

MediaBrowserCompat.ConnectionCallback heeft een onConnected () methode die wordt aangeroepen wanneer een nieuw MediaBrowserCompat object is gemaakt en verbonden. U kunt dit gebruiken om uw te initialiseren MediaControllerCompat object, koppel het aan uw MediaControllerCompat.Callback, en associeer het met MediaSessionCompat van jouw Service. Als dat is voltooid, kunt u het afspelen van audio vanaf deze methode starten.

private MediaBrowserCompat.ConnectionCallback mMediaBrowserCompatConnectionCallback = new MediaBrowserCompat.ConnectionCallback () @Override public void onConnected () super.onConnected (); probeer mMediaControllerCompat = nieuwe 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) ;

U zult merken dat het bovenstaande codefragment wordt gebruikt getSupportMediaController (). getTransportControls () om te communiceren met de mediasessie. Met dezelfde techniek kun je bellen onPlay () en onPause () in uw audioservice MediaSessionCompat.Callback voorwerp.

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

Wanneer u klaar bent met uw audioweergave, kunt u de audiodienst pauzeren en uw verbinding verbreken MediaBrowserCompat object, wat we in deze tutorial zullen doen als dit Activiteit is vernietigd.

@Override beschermde leegte onDestroy () super.onDestroy (); if (getSupportMediaController (). getPlaybackState (). getState () == PlayStateCompat.STATE_PLAYING) getSupportMediaController (). getTransportControls (). pause ();  mMediaBrowserCompat.disconnect (); 

Afsluiten

Oef! Zoals je kunt zien, zijn er veel bewegende delen die te maken hebben met het correct maken en gebruiken van een achtergrond-audioservice. 

In deze zelfstudie hebt u een service gemaakt die een eenvoudig audiobestand afspeelt, luistert naar wijzigingen in de audiofocus en koppelingen naar MediaSessionCompat om universele afspeelcontrole te bieden op Android-apparaten, waaronder handsets en Android Wear. Als je tijdens deze tutorial tegen wegversperringen aanloopt, raad ik je ten zeerste aan om de bijbehorende Android-projectcode te bekijken op Enito Tuts + 's GitHub.

Bekijk enkele van onze andere Android-cursussen en tutorials hier op Envato Tuts+!