Una dintre cele mai populare utilizări pentru dispozitive mobile este redarea audio prin servicii de streaming muzical, podcasturi descărcate sau orice alt număr de surse audio. În timp ce aceasta este o caracteristică destul de comună, este greu de implementat, cu o mulțime de piese diferite care trebuie construite corect, pentru a oferi utilizatorilor dvs. experiența Android completă.
În acest tutorial veți afla despre MediaSessionCompat
din biblioteca de asistență Android și cum poate fi utilizată pentru a crea un serviciu audio de fundal adecvat pentru utilizatorii dvs..
Primul lucru pe care trebuie să-l faceți este să includeți biblioteca de asistență Android în proiectul dvs. Acest lucru se poate face adăugând următoarea linie în modulul dvs. build.gradle fișier în cadrul nodului dependențelor.
compile 'com.android.support:support-v13:24.2.1'
După ce ați sincronizat proiectul, creați o nouă clasă Java. Pentru acest exemplu voi numi clasa BackgroundAudioService
. Această clasă va trebui să se extindă MediaBrowserServiceCompat
. Vom implementa, de asemenea, următoarele interfețe: MediaPlayer.OnCompletionListener
și AudioManager.OnAudioFocusChangeListener
.
Acum, că dvs. MediaBrowserServiceCompat
implementarea este creată, să facem un moment de actualizare AndroidManifest.xml înainte de a reveni la această clasă. În partea de sus a clasei, va trebui să solicitați WAKE_LOCK
permisiune.
Apoi, în cadrul cerere
nod, declarați noul dvs. serviciu cu următoarele intenție-filtru
articole. Acestea vor permite serviciului dvs. să intercepteze butoanele de control, evenimentele căștilor și navigarea în mass-media pentru dispozitive, cum ar fi Android Auto (deși nu vom face nimic cu Android Auto pentru acest tutorial, MediaBrowserServiceCompat
).
În cele din urmă, va trebui să declarați utilizarea MediaButtonReceiver
din biblioteca de asistență Android. Acest lucru vă va permite să interceptați interacțiunile butoanelor de control media și evenimentele pentru căști pe dispozitivele care rulează KitKat și mai devreme.
Acum, că dvs. AndroidManifest.xml fișierul este terminat, îl puteți închide. De asemenea, vom crea o altă clasă numită MediaStyleHelper
, care a fost scris de Ian Lake, Avocat dezvoltator la Google, pentru a curăța crearea de notificări de stil media.
public class MediaStyleHelper / ** * Creați o notificare utilizând informațiile din sesiunea media dată. Utilizează grele * din @link MediaMetadataCompat # getDescription () pentru a extrage informațiile corespunzătoare. * @ context param Contextul folosit pentru a construi notificarea. * @param mediaSession Media sesiune pentru a obține informații. * @ return O notificare pre-construită cu informații din sesiunea media dată. * / public Static NotificareCompat.Builder din (Context context, MediaSessionCompat mediaSession) MediaControllerCompact controller = mediaSession.getController (); MediaMetadataCompat mediaMetadata = controller.getMetadata (); MediaDescriptionCompat descriere = mediaMetadata.getDescription (); NotificareCompat.Builder builder = Notificare nouăCompat.Builder (context); constructor .setContentTitle (description.getTitle ()) .setContentText (description.getSubtitle ()) .setSubText (descriere.getDescription ()) .setLargeIcon (descriere.getIconBitmap ()) .setContentIntent (controller.getSessionActivity ()) .setDeleteIntent (MediaButtonReceiver .buildMediaButtonPendingIntent (context, PlaybackStateCompat.ACTION_STOP)) .setVisibility (NotificareCompat.VISIBILITY_PUBLIC); constructor de returnari;
După ce a fost creat, continuați și închideți fișierul. Ne vom concentra pe serviciul audio de fundal în secțiunea următoare.
Acum este timpul să vă grăbiți să creați aplicația media. Există câteva variabile membre pe care doriți să le declarați mai întâi pentru această aplicație probă: a Media Player
pentru redarea reală și a MediaSessionCompat
obiect care va gestiona metadatele și controalele / stările de redare.
private MediaPlayer mMediaPlayer; private MediaSessionCompat mMediaSessionCompat;
În plus, veți avea nevoie de a BroadcastReceiver
care ascultă schimbările în starea căștilor. Pentru a menține lucrurile simple, acest receptor va întrerupe Media Player
, dacă se joacă.
privat BroadcastReceiver mNoisyReceiver = nou BroadcastReceiver () @Override public void onReceive (Context context, Intent intent) if (mMediaPlayer! = null && mMediaPlayer.isPlaying ()) mMediaPlayer.pause (); ;
Pentru variabila finală membru, veți crea o MediaSessionCompat.Callback
obiect, care este utilizat pentru a gestiona starea redării când apar acțiuni de sesiune media.
privat MediaSessionCompat.Callback mMediaSessionCallback = nou MediaSessionCompat.Callback () @Override public void onPlay () super.onPlay (); @Override public void pePause () super.onPause (); @Override public void pePlayFromMediaId (String mediaId, Extras pachet) super.onPlayFromMediaId (mediaId, extras); ;
Vom revizui fiecare dintre metodele de mai sus mai târziu în acest tutorial, deoarece acestea vor fi folosite pentru a conduce operațiile în aplicația noastră media.
Există două metode pe care va trebui să le declarăm, deși nu vor trebui să facă nimic în scopul acestui tutorial: onGetRoot ()
și onLoadChildren ()
. Puteți utiliza codul următor pentru setările prestabilite.
@Nullable @Override public BrowserRoot onGetRoot (@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) if (TextUtils.equals (clientPackageName, getPackageName ())) returnează noul BrowserRoot (getString (R.string.app_name), null ); return null; // Nu este important pentru serviciul audio general, necesar pentru clasa @Override public void onLoadChildren (@NonNull String parentId, @NonNull Result> rezultat) result.sendResult (null);
În cele din urmă, veți dori să suprascrieți onStartCommand ()
metoda, care este punctul de intrare în dvs. Serviciu
. Această metodă va lua intenția care va fi trecută la Serviciu
și trimiteți-l la MediaButtonReceiver
clasă.
@Override public int peStartCommand (Intent intent, int flags, int startId) MediaButtonReceiver.handleIntent (mMediaSessionCompat, intent); returnează super.onStartCommand (intenție, steaguri, startId);
Acum, când variabilele dvs. de bază sunt create, este timpul să inițializați totul. Vom face asta prin apelarea diferitelor metode de ajutor onCreate ()
.
@Override publice void onCreate () super.onCreate (); initMediaPlayer (); initMediaSession (); initNoisyReceiver ();
Prima metodă, initMediaPlayer ()
, va inițializa Media Player
obiect pe care l-am creat la vârful clasei, cereți blocarea parțială a treptelor (motiv pentru care am solicitat permisiunea AndroidManifest.xml) și setați volumul playerului.
void privat initMediaPlayer () mMediaPlayer = nou MediaPlayer (); mMediaPlayer.setWakeMode (getApplicationContext (), PowerManager.PARTIAL_WAKE_LOCK); mMediaPlayer.setAudioStreamType (AudioManager.STREAM_MUSIC); mMediaPlayer.setVolume (1.0f, 1.0f);
Următoarea metodă, initMediaSession ()
, este locul unde inițializăm MediaSessionCompat
obiecte și conectați-le la butoanele media și metodele de control care ne permit să gestionăm redarea și intrarea utilizatorilor. Această metodă începe prin crearea unui ComponentName
obiect care indică biblioteca de suport Android MediaButtonReceiver
clasă și utilizează pentru a crea un nou MediaSessionCompat
. Apoi vom trece MediaSession.Callback
obiect pe care l-am creat mai devreme și setând steagurile necesare pentru recepționarea intrărilor de butoane media și a semnalelor de control. Apoi, vom crea un nou scop
pentru a manipula intrările butoanelor media pe dispozitivele pre-Lollipop și pentru a seta jetonul sesiunii media pentru serviciul nostru.
void privat initMediaSession () ComponentName mediaButtonReceiver = nume Component nou (getApplicationContext (), MediaButtonReceiver.class); mMediaSessionCompat = nou MediaSessionCompat (getApplicationContext (), "Tag", mediaButtonReceiver, null); mMediaSessionCompat.setCallback (mMediaSessionCallback); mMediaSessionCompat.setFlags (MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); Intenția mediaButtonIntent = intenția nouă (Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setClass (aceasta, MediaButtonReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast (aceasta, 0, mediaButtonIntent, 0); mMediaSessionCompat.setMediaButtonReceiver (pendingIntent); setSessionToken (mMediaSessionCompat.getSessionToken ());
În cele din urmă, vom înregistra BroadcastReceiver
pe care am creat-o la vârful clasei, astfel încât să putem asculta evenimentele de schimbare a căștilor.
private void initNoisyReceiver () // Mânerele căștilor care au fost deconectate. nu se poate face printr-un receptor manifest IntentFilter filter = new IntentFilter (AudioManager.ACTION_AUDIO_BECOMING_NOISY); registerReceiver (mNoisyReceiver, filtru);
Acum că ați terminat inițializarea BroadcastReceiver
, MediaSessionCompat
și Media Player
obiecte, este timpul să te uiți în manevrarea focalizării audio.
În timp ce ne putem gândi că aplicațiile audio proprii sunt cele mai importante momentan, alte aplicații de pe dispozitiv vor concura pentru a-și face propriile sunete, cum ar fi o notificare prin e-mail sau un joc mobil. Pentru a lucra cu aceste situații diferite, sistemul Android folosește focalizarea audio pentru a determina modul în care ar trebui să fie tratată audio.
Primul caz pe care vom dori să-l rezolvăm este începerea redării și încercarea de a primi focalizarea dispozitivului. În tine MediaSessionCompat.Callback
obiect, intră în onPlay ()
și adăugați următoarea verificare a condițiilor.
@Override public void pePlay () super.onPlay (); dacă (! successfullyRetrievedAudioFocus ()) return;
Codul de mai sus va apela o metodă de ajutor care încearcă să recupereze focalizarea și dacă nu poate, va reveni pur și simplu. Într-o aplicație reală, ați dori să vă ocupați de redarea eșuată a sunetului mai grațios. successfullyRetrievedAudioFocus ()
va primi o referință la sistem AudioManager
, și încercați să solicitați focalizarea audio pentru streaming muzică. Acesta va reveni apoi a boolean
reprezentând dacă cererea a fost sau nu reușită.
boolean privat cu succesRetrievedAudioFocus () AudioManager audioManager = (AudioManager) getSystemService (Context.AUDIO_SERVICE); int rezultat = audioManager.requestAudioFocus (aceasta, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); return rezultat == AudioManager.AUDIOFOCUS_GAIN;
Veți observa că și noi trecem acest
în requestAudioFocus ()
, care asociază OnAudioFocusChangeListener
cu serviciul nostru. Există câteva stări diferite pe care le veți dori să le ascultați pentru a fi un "bun cetățean" în ecosistemul de aplicații al dispozitivului.
AudioManager.AUDIOFOCUS_LOSS
: Apare atunci când o altă aplicație a solicitat focalizare audio. Când se întâmplă acest lucru, ar trebui să opriți redarea audio în aplicația dvs..AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
: Această stare este introdusă atunci când o altă aplicație dorește să redea audio, dar doar anticipează necesitatea focalizării pentru o perioadă scurtă de timp. Puteți utiliza această stare pentru a întrerupe redarea audio.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
: Când se solicită focalizarea audio, dar aruncă o stare "poate rață", înseamnă că puteți continua redarea, dar ar trebui să aducem puțin volumul. Acest lucru poate apărea atunci când dispozitivul emite un sunet de notificare.AudioManager.AUDIOFOCUS_GAIN
: Starea finală pe care o vom discuta este AUDIOFOCUS_GAIN
. Aceasta este starea în care a fost finalizată o redare audio duckable, iar aplicația dvs. poate relua la nivelurile anterioare.O simplificată onAudioFocusChange ()
inversarea apelului poate să arate astfel:
@Override public void peAudioFocusChange (int focusChange) comutare (focusChange) caz AudioManager.AUDIOFOCUS_LOSS: if (mMediaPlayer.isPlaying ()) mMediaPlayer.stop (); pauză; caz AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: mMediaPlayer.pause (); pauză; caz AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: if (mMediaPlayer! = null) mMediaPlayer.setVolume (0.3f, 0.3f); pauză; caz AudioManager.AUDIOFOCUS_GAIN: if (mMediaPlayer! = null) if (! mMediaPlayer.isPlaying ()) mMediaPlayer.start (); mMediaPlayer.setVolume (1.0f, 1.0f); pauză;
Acum că aveți o structură generală împreună pentru dvs. Serviciu
, este timpul să se scufunde în MediaSessionCompat.Callback
. În ultima secțiune ați adăugat un pic la onPlay ()
pentru a verifica dacă sa acordat focalizarea audio. Sub instrucțiunea condiționată, veți dori să setați MediaSessionCompat
obiect la activ, da-i o stare de STATE_PLAYING
, și să atribuiți acțiunile potrivite necesare pentru a crea butoane de pauză în comenzile de pe ecranul de blocare pre-Lollipop, în notificările telefonului și în Android Wear.
@Override public void pePlay () super.onPlay (); dacă (! successfullyRetrievedAudioFocus ()) return; mMediaSessionCompat.setActive (adevărat); setMediaPlaybackState (PlaybackStateCompat.STATE_PLAYING); ...
setMediaPlaybackState ()
Metoda de mai sus este o metodă de ajutor care creează o PlaybackStateCompat.Builder
obiect și îi dă acțiunile și starea adecvată, apoi construiește și asociază a PlaybackStateCompat
cu tine MediaSessionCompat
obiect.
void privat setMediaPlaybackState (stare int) PlaybackStateCompat.Builder playbackstateBuilder = nou PlaybackStateCompat.Builder (); dacă (state == PlaybackStateCompat.STATE_PLAYING) playbackstateBuilder.setActions (PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PAUSE); altceva playbackstateBuilder.setActions (PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PLAY); playstateBuilder.setState (starea, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 0); mMediaSessionCompat.setPlaybackState (playbackstateBuilder.build ());
Este important să rețineți că veți avea nevoie de ambele ACTION_PLAY_PAUSE
si nici ACTION_PAUSE
sau ACTION_PLAY
steaguri în acțiunile dvs. pentru a obține controale adecvate pentru Android Wear.
Înapoi în onPlay ()
, veți dori să afișați o notificare de joc asociată cu dvs. MediaSessionCompat
obiect folosind MediaStyleHelper
clasa pe care am definit-o mai devreme, și apoi să afișăm această notificare.
private void showPlayingNotificare () NotificareCompat.Builder builder = MediaStyleHelper.from (BackgroundAudioService.this, mMediaSessionCompat); dacă (constructor == null) return; builder.addAction (noua NotificareCompat.Action (android.R.drawable.ic_media_pause, "Pause", MediaButtonReceiver.buildMediaButtonPendingIntent (aceasta, PlaybackStateCompat.ACTION_PLAY_PAUSE)); builder.setStyle (noua NotificareCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificareaManagerCompat.from (BackgroundAudioService.this) .notify (1, builder.build ());
În cele din urmă, veți începe Media Player
la sfârșitul onPlay ()
.
@Override public void onPlay () super.onPlay (); ... showPlayingNotification (); mMediaPlayer.start ();
Când apelul de apel primește o comandă de pauză, onPause ()
va fi numit. Aici veți întrerupe Media Player
, setați starea la STATE_PAUSED
, și să afișați o notificare în pauză.
@Override publice void onPause () super.onPause (); dacă (mMediaPlayer.isPlaying ()) mMediaPlayer.pause (); setMediaPlaybackState (PlaybackStateCompat.STATE_PAUSED); showPausedNotification ();
Al nostru showPausedNotification ()
metoda de ajutor va arata similar cu showPlayNotification ()
metodă.
private void showPausedNotification () NotificareCompat.Builder builder = MediaStyleHelper.from (aceasta, mMediaSessionCompat); dacă (constructor == null) return; builder.addAction (noua NotificareCompat.Action (android.R.drawable.ic_media_play, "Play", MediaButtonReceiver.buildMediaButtonPendingIntent (aceasta, PlaybackStateCompat.ACTION_PLAY_PAUSE)); builder.setStyle (noua NotificareCompat.MediaStyle (). setShowActionsInCompactView (0) .setMediaSession (mMediaSessionCompat.getSessionToken ())); builder.setSmallIcon (R.mipmap.ic_launcher); NotificationManagerCompat.from (acest) .notify (1, builder.build ());
Următoarea metodă din callback pe care o vom discuta, onPlayFromMediaId ()
, ia a Şir
și a Pachet
ca parametri. Aceasta este metoda de apel inversă pe care o puteți utiliza pentru a schimba piste audio / conținut din aplicația dvs..
Pentru acest tutorial, vom accepta pur și simplu un ID de resursă brut și vom încerca să jucăm acest lucru și apoi vom reinitializa metadatele sesiunii. După cum vi se permite să treci a Pachet
în această metodă, o puteți folosi pentru a personaliza alte aspecte ale redării media, cum ar fi configurarea unui sunet de fundal personalizat pentru o piesă.
@Override publice void pePlayFromMediaId (String mediaId, Extras pachet) super.onPlayFromMediaId (mediaId, extras); încercați AssetFileDescriptor afd = getResources () openRawResourceFd (Integer.valueOf (mediaId)); dacă (afd == null) return; încercați mMediaPlayer.setDataSource (afd.getFileDescriptor (), afd.getStartOffset (), afd.getLength ()); captură (IllegalStateException e) mMediaPlayer.release (); initMediaPlayer (); mMediaPlayer.setDataSource (afd.getFileDescriptor (), afd.getStartOffset (), afd.getLength ()); afd.close (); initMediaSessionMetadata (); captură (IOException e) retur; încercați mMediaPlayer.prepare (); catch (IOException e) // Lucrează cu extras aici dacă vrei
Acum, când am discutat cele două metode principale din acest apel invers pe care îl veți folosi în aplicațiile dvs., este important să știți că există și alte metode opționale pe care le puteți utiliza pentru a vă personaliza serviciul. Unele metode includ onSeekTo ()
, care vă permite să modificați poziția de redare a conținutului dvs. și la comandă()
, care va accepta a Şir
indicând tipul de comandă, a Pachet
pentru informații suplimentare despre comandă și a ResultReceiver
apel invers, care vă va permite să trimiteți comenzi personalizate către dvs. Serviciu
.
@Override publice void onCommand (comanda String, extras Bundle, ResultReceiver cb) super.onCommand (comanda, extras, cb); dacă (COMMAND_EXAMPLE.equalsIgnoreCase (comanda)) // Comanda personalizată aici @Override public void onSeekTo (long pos) super.onSeekTo (pos);
Când fișierul nostru audio va fi finalizat, vom dori să decidem ce va fi următoarea noastră acțiune. În timp ce poate doriți să redați piesa următoare în aplicația dvs., vom păstra lucrurile simple și vom elibera Media Player
.
@Override publice void onCompletion (MediaPlayer mediaPlayer) dacă (mMediaPlayer! = Null) mMediaPlayer.release ();
În cele din urmă, vom dori să facem câteva lucruri în onDestroy ()
metoda noastră Serviciu
. Mai întâi, obțineți o referință la serviciul de sistem AudioManager
, și sunați abandonAudioFocus ()
cu a noastră AudioFocusChangeListener
ca parametru, care va notifica alte aplicații de pe dispozitiv că renunțați la focalizarea audio. Apoi, anulați înregistrarea BroadcastReceiver
care a fost configurat pentru a asculta schimbările căștilor și eliberați-l MediaSessionCompat
obiect. În cele din urmă, veți dori să anulați notificarea privind controlul redării.
@Override public void peDestroy () super.onDestroy (); AudioManager audioManager = (AudioManager) getSystemService (Context.AUDIO_SERVICE); audioManager.abandonAudioFocus (aceasta); unregisterReceiver (mNoisyReceiver); mMediaSessionCompat.release (); NotificationManagerCompat.from (aceasta) .cancel (1);
În acest moment, ar trebui să aveți un sunet de fundal de lucru Serviciu
utilizând MediaSessionCompat
pentru controlul redării pe toate dispozitivele. Deși a fost deja mult implicat doar în crearea serviciului, ar trebui să puteți controla redarea din aplicație, o notificare, comenzile de blocare a ecranului pe dispozitivele pre-Lollipop (Lollipop și mai sus vor folosi notificarea pe ecranul de blocare), și de la dispozitivele periferice, cum ar fi Android Wear, o dată Serviciu
a început.
În timp ce cele mai multe controale vor fi automate, veți avea încă un pic de lucru pentru a începe și controla o sesiune media din controalele în aplicație. Cel puțin, veți dori a MediaBrowserCompat.ConnectionCallback
, MediaControllerCompat.Callback
, MediaBrowserCompat
, și MediaControllerCompat
obiecte create în aplicația dvs..
MediaControllerCompat.Callback
va avea o metodă numită onPlaybackStateChanged ()
care primește modificări în starea de redare și poate fi utilizat pentru a păstra sincronizarea interfeței utile.
private MediaControllerCompat.Callback mMediaControllerCompatCallback = nou MediaControllerCompat.Callback () @Override public void pePlaybackStateChanged (starea PlaybackStateCompat) super.onPlaybackStateChanged (state); dacă (state == null) return; comutare (state.getState ()) case PlaybackStateCompat.STATE_PLAYING: mCurrentState = STATE_PLAYING; pauză; caz PlaybackStateCompat.STATE_PAUSED: mCurrentState = STATE_PAUSED; pauză; ;
MediaBrowserCompat.ConnectionCallback
are un onConnected ()
care va fi numită atunci când este nouă MediaBrowserCompat
obiect este creat și conectat. Puteți folosi acest lucru pentru a vă inițializa MediaControllerCompat
obiect, conectați-l la dvs. MediaControllerCompat.Callback
, și asociați-o cu MediaSessionCompat
de la tine Serviciu
. Odată terminată, puteți porni redarea audio de la această metodă.
private MediaBrowserCompat.ConnectionCallback mMediaBrowserCompatConnectionCallback = nou MediaBrowserCompat.ConnectionCallback () @Override public void onConnected () super.onConnected (); încercați mMediaControllerCompat = nou MediaControllerCompat (MainActivity.this, mMediaBrowserCompat.getSessionToken ()); mMediaControllerCompat.registerCallback (mMediaControllerCompatCallback); setSupportMediaController (mMediaControllerCompat); getFormMediaId (String.valueOf (R.raw.warner_tautz_off_broadway), null); captură (RemoteException e) ;
Veți observa că fragmentul de cod de mai sus utilizează getSupportMediaController (). getTransportControls ()
pentru a comunica cu sesiunea media. Folosind aceeași tehnică, puteți apela onPlay ()
și onPause ()
în serviciile dvs. audio MediaSessionCompat.Callback
obiect.
dacă (mCurrentState == STATE_PAUSED) getSupportMediaController (). getTransportControls () play (); mCurrentState = STATE_PLAYING; altceva if (getSupportMediaController () getPlaybackState () getState () == PlaybackStateCompat.STATE_PLAYING) getSupportMediaController () getTransportControls () pauză (); mCurrentState = STATE_PAUSED;
Când ați terminat redarea audio, puteți întrerupe serviciul audio și vă puteți deconecta MediaBrowserCompat
obiect, pe care îl vom face în acest tutorial atunci când aceasta Activitate
este distrusă.
@Override protejate void onDestroy () super.onDestroy (); dacă getStateMediaController () getPlaybackState () getState () == PlaybackStateCompat.STATE_PLAYING) getSupportMediaController () getTransportControls () pauză (); mMediaBrowserCompat.disconnect ();
Uau! După cum puteți vedea, există o mulțime de piese în mișcare implicate în crearea și utilizarea unui serviciu audio de fundal corect.
În acest tutorial, ați creat un serviciu care redă un fișier audio simplu, ascultă schimbările în focalizarea audio și link-urile MediaSessionCompat
pentru a oferi control universal al redării pe dispozitive Android, inclusiv pe telefoane mobile și Android Wear. Dacă vă confruntați cu blocaje în timp ce lucrați prin acest tutorial, vă recomandăm insistent să verificați codul de proiect Android asociat pe GitHub al Envato Tuts +.
Și verificați câteva dintre celelalte cursuri și tutoriale Android de aici, pe Envato Tuts+!