În această serie, construim o aplicație simplă pentru aplicația de muzică pentru Android. Până în prezent, am prezentat o listă de melodii de pe dispozitiv și am permis utilizatorului să facă selecții de la acesta, pornind de la redarea folosind Media Player
clasă într-un Serviciu
clasă. În această parte finală a seriei, vom lăsa utilizatorul să controleze redarea, inclusiv sărind peste melodiile următoare și anterioare, redirecționarea rapidă, reluarea, redarea, întreruperea și căutarea anumitor puncte din piesă. De asemenea, vom afișa o notificare în timpul redării, astfel încât utilizatorul să poată sări înapoi la playerul muzical după ce a folosit alte aplicații.
Această serie de tutoriale vă conduce prin procesul de a construi o aplicație pentru music player de la zero. Dacă doriți o soluție gata, încercați Android Music Player, un player muzical avansat pentru dispozitive Android. Vă permite să răsfoiți și să redați muzică după albume, artiști, melodii, playlisturi, dosare și artiști de album și dispune de o serie de alte caracteristici.
Android Music PlayerSau dacă doriți ceva complet personalizat conform specificațiilor dvs., puteți angaja un dezvoltator Android de pe Envato Studio pentru a face ceva de la tweaks și bug-uri la crearea unei aplicații întregi de la zero.
Funcția de control al playerului muzical va fi implementată cu ajutorul funcției MediaController
clasă, în care a SeekBar
instanța afișează progresul redării, precum și permițând utilizatorului sări la anumite locații dintr-o pistă. Vom folosi Notificare
și PendingIntent
pentru a afișa titlul piesei care se joacă în prezent și permite utilizatorului să navigheze înapoi la aplicație.
Acesta este modul în care ar trebui să apară aplicația când finalizați acest tutorial:
După această serie, vom explora, de asemenea, funcționalitățile asemănătoare pe care doriți să le utilizați pentru a îmbunătăți aplicația pentru music player. Aceasta va include redarea video, streaming media, gestionarea focusului audio și prezentarea datelor media în moduri diferite.
Deschide-ți principalul Activitate
și adăugați următoarea declarație de import:
import șiroid.widget.MediaController.MediaPlayerControl;
Extindeți linia de deschidere a declarației de clasă după cum urmează, pentru a putea folosi Activitate
pentru a oferi controlul redării:
public class MainActivity se extinde Activitatea implementează MediaPlayerControl
Treceți cursorul peste numele clasei și selectați Adăugați metode neimplementate. Eclipse va adăuga diverse metode de control al redării, pe care le vom adapta în timp ce mergem.
MediaController
clasa prezintă un widget standard cu funcții de redare / pauză, derulare înapoi, derulare rapidă înainte și săriți (butoanele anterioare / următoare) în el. Widgetul conține, de asemenea, o bară de căutare, care se actualizează pe măsură ce piesa se redă și conține text care indică durata cântecului și poziția actuală a jucătorului. Pentru a putea configura detaliile controlului, vom implementa o clasă pentru ao extinde. Adăugați o nouă clasă la proiectul dvs., numind-o MusicController. În Eclipse, alegeți android.widget.MediaController ca superclasa la crearea ei.
Oferiți clasei următorul conținut:
clasa publica MusicController extinde MediaController public MusicController (Context c) super (c); public void ascunde ()
Puteți să vă adaptați MediaController
clasa în diferite moduri. Tot ce vrem să facem este să-l oprim de la ascunderea automată după trei secunde prin suprimarea lui ascunde
metodă.
Înapoi în principal Activitate
class, adăugați o variabilă nouă instanță:
controlerul MusicController privat;
Vom seta controlerul de mai multe ori în ciclul de viață al aplicației, așa că haideți să o facem într-o metodă de ajutor. Adăugați următorul fragment de cod la dvs. Activitate
clasă:
private void setController () // setați controlerul în sus
În interiorul metodei, instanțiați controlerul:
controler = nou MusicController (acest);
Puteți configura diferite aspecte ale MediaController
instanță. De exemplu, va trebui să determinăm ce se va întâmpla când utilizatorul apasă butoanele anterioare / următoare. După instanțierea controlerului setați aceste ascultători de clic:
controler.setPrevNextListeners (new View.OnClickListener () @Override public void onClick (Vizualizare v) playNext ();, new View.OnClickListener () @Override public void onClick (Vizualizare v) playPrev (); );
Vom implementa playNext
și playPrev
un pic mai târziu, așa că ignorați erorile pentru moment. Încă înăuntru setController
, setați controlerul pentru a lucra la redarea media în aplicație, cu vizualizarea ancorei care se referă la lista pe care am inclus-o în aspect:
controller.setMediaPlayer (aceasta); controller.setAnchorView (findViewById (R.id.song_list)); controller.setEnabled (true);
Înapoi în onCreate
, apelați metoda:
setController ();
O vom numi și în altă parte în clasă mai târziu.
Amintiți-vă că redarea media se produce în Serviciu
clasa, dar că interfața de utilizator vine de la Activitate
clasă. În tutorialul anterior, am legat Activitate
exemplu la Serviciu
astfel încât să putem controla redarea din interfața cu utilizatorul. Metodele din Activitate
clasa pe care am adăugat-o pentru a implementa MediaPlayerControl
interfața va fi apelată atunci când utilizatorul încearcă să controleze redarea. Vom avea nevoie de Serviciu
clasa de a acționa în acest control, deschideți-vă astfel Serviciu
clasa acum pentru a adăuga mai multe metode pentru a:
public int getPosn () retur player.getCurrentPosition (); public int int getDur () retur player.getDuration (); boolean public isPng () return player.isPlaying (); public void pauzăPlayer () player.pause (); public void caută (int posn) player.seekTo (posn); void go public () player.start ();
Aceste metode se aplică tuturor funcțiilor standard de control al redării pe care utilizatorul le va aștepta.
Acum, să adăugăm metode la Serviciu
pentru sări la următoarea și cea anterioară. Începeți cu funcția anterioară:
public void playPrev () songPosn--; în cazul în care (songPosn<0) songPosn=songs.size()-1; playSong();
Redimensionăm variabila indexului de melodii, verificăm faptul că nu am ieșit în afara domeniului listei și sunați playSong
metoda pe care am adăugat-o. Acum adăugați metoda pentru a trece la următoarea pistă:
// sări la următorul public void playNext () songPosn ++; dacă (songPosn> = songs.size ()) songPosn = 0; playSong ();
Acest lucru este similar cu metoda de redare a piesei anterioare în acest moment, dar vom modifica mai târziu această metodă pentru a implementa funcția shuffle.
Acum întoarce-te la tine Activitate
pentru a putea folosi aceste metode. Mai întâi adăugați metodele pe care le-am sunat când am setat controlerul:
// juca urmatorul privat void playNext () musicSrv.playNext (); controller.show (0); // a reda jocul privat anterior voidPrev () musicSrv.playPrev (); controller.show (0);
Noi numim metodele pe care le-am adăugat la Serviciu
clasă. Vom adăuga mai mult cod la acestea mai târziu pentru a avea grijă de situații particulare. Acum hai să ne întoarcem la MediaPlayerControl
metodele de interfață, care vor fi apelate de sistem în timpul redării și atunci când utilizatorul interacționează cu comenzile. Aceste metode ar trebui să fie deja în dvs. Activitate
clasa, așa că vom modifica implementarea lor.
Începeți cu canPause
metoda, stabilind-o Adevărat:
@Override boolean public canPause () return true;
Faceți același lucru și pentru canSeekBackward
și canSeekForward
metode:
@Override boolean public canSeekBackward () return true; @Override public boolean canSeekForward () return true;
Puteți să părăsiți getAudioSessionId
și getBufferPercentage
așa cum sunt. Modificați getCurrentPosition
după cum urmează:
@Override public int getCurrentPosition () if (musicSrv! = Null && musicBound && musicSrv.isPng ()) retur musicSrv.getPosn (); altul retur 0;
Testele condiționale sunt pentru a evita diferite excepții care pot apărea atunci când se utilizează Media Player
și MediaController
clase. Dacă încercați să îmbunătățiți aplicația în orice mod, probabil veți găsi că trebuie să faceți astfel de pași, deoarece clasele de redare media aruncă o mulțime de excepții. Observați că suntem getPosn
metodă a Serviciu
clasă.
Modificați getDuration
metoda similară:
@Override publică int getDuration () if (musicSrv! = Null && musicBound && musicSrv.isPng ()) retur musicSrv.getDur (); altul retur 0;
Modificați se joacă
prin invocarea isPng
metoda noastră Serviciu
clasă:
@Override boolean public estePlaying () if (musicSrv! = Null && musicBound) retur musicSrv.isPng (); return false;
Faceți același lucru pentru pauză
, încearcă să
și start
metode:
@ Pauza void publice void () musicSrv.pausePlayer (); @Override publice void seekTo (int pos) musicSrv.seek (pos); @Overide public void start () musicSrv.go ();
Rețineți că vom continua redarea chiar și atunci când utilizatorul se îndepărtează de aplicație. Pentru a facilita acest lucru, vom afișa o notificare care va afișa titlul piesei redate. Dacă faceți clic pe notificare, utilizatorul va reveni în aplicație. Întoarceți-vă la dvs. Serviciu
și adăugați următoarele importuri suplimentare:
import java.util.Random; import android.app.Notification; import șiroid.app.PendingIntent;
Acum treceți la onPrepared
, în care începem pur și simplu redarea. După ce ați sunat la player.start ()
, adăugați următorul cod:
Intent notIntent = intenție nouă (aceasta, MainActivity.class); notIntent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendInt = PendingIntent.getActivity (aceasta, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT); Notification.Builder builder = nou Notification.Builder (this); builder.setContentIntent (pendInt) .setSmallIcon (R.drawable.play) .setTicker (melodieTitle) .setOngoing (true) .setContentTitle ("Redarea") .setContentText (songTitle); Notificarea nu = builder.build (); Începutul terenului (NOTIFY_ID, nu);
Vom adăuga variabilele care lipsesc în continuare. PendingIntent
clasa va duce utilizatorul înapoi la principalele Activitate
când selectează notificarea. Adăugați variabile pentru titlul melodiei și codul de notificare din partea de sus a clasei:
melodie privată StringTitle = ""; statică finală privată int NOTIFY_ID = 1;
Acum trebuie să setăm titlul cântecului în playSong
, după linia în care extragem melodia din listă (Song playSong = melodii (songPosn);
):
= playSong.getTitle titlul cântecului ();
De când am sunat setForeground
pe notificare, trebuie să ne asigurăm că o oprim când Serviciu
instanța este distrusă. Înlocuiți următoarea metodă:
@Override public void peDestroy () stopForeground (adevărat);
Amintiți-vă că am adăugat un buton de amestecare, așa că implementați-l acum. Mai întâi adăugați variabile de instanță noi la Serviciu
clasă:
private boolean shuffle = false; privat Random rand;
Instanțiați generatorul de numere aleatorii în onCreate
:
rand = new Random ();
Acum adăugați o metodă pentru a seta steagul de shuffle:
public void setSuffle () if (shuffle) shuffle = false; altceva shuffle = adevărat;
Vom schimba pur și simplu setarea de shuffle. Vom verifica acest steag atunci când utilizatorul trece fie la piesa următoare, fie când se termină o pistă, iar următoarea începe. Modificați playNext
după cum urmează:
public void playNext () if (shuffle) int newSong = cântecPosn; în timp ce (newSong == songPosn) newSong = rand.nextInt (songs.size ()); songPosn = newSong; altceva songPosn ++; dacă (songPosn> = songs.size ()) songPosn = 0; playSong ();
Dacă pavilionul de amestecare este activat, alegem din nou o melodie nouă din listă, asigurându-ne că nu vom repeta ultima melodie jucată. Puteți îmbunătăți această funcție utilizând o coadă de melodii și împiedicând repetarea oricărei melodii până când toate melodiile au fost redate.
Acum putem lăsa utilizatorul să selecteze funcția Shuffle. Înapoi în principal Activitate
clasa în onOptionsItemSelected
, modificați secțiunea pentru acțiunea de amestecare pentru a apela noua metodă pe care am adăugat-o Serviciu
clasă:
caz R.id.action_shuffle: musicSrv.setShuffle (); pauză;
Acum, utilizatorul va putea utiliza elementul de meniu pentru a comuta funcția de amestecare.
Aproape am terminat, dar încă mai trebuie să adăugăm câțiva biți de procesare pentru a avea grijă de anumite schimbări, cum ar fi faptul că utilizatorul a părăsit aplicația sau a întrerupt redarea. În tine Activitate
clasă, adăugați mai multe variabile de instanță:
privat boolean paused = false, playbackPaused = false;
Vom folosi aceste pentru a face față cu utilizatorul care revine la aplicație după ce a părăsit-o și a interacționa cu comenzile atunci când redarea în sine este întreruptă. Trece peste onPause
pentru a seta unul dintre aceste steaguri:
@Override protejat void onPause () super.onPause (); întrerupte = true;
Acum suprascrie onResume
:
@Override protejate void onResume () super.onResume (); dacă (întrerupt) setController (); întrerupte = false;
Acest lucru va asigura afișarea controlerului atunci când utilizatorul revine la aplicație. Trece peste onStop
pentru al ascunde:
@Override protejat void onStop () controller.hide (); super.onStop ();
Dacă utilizatorul interacționează cu comenzile în timp ce redarea este întreruptă, Media Player
obiect se poate comporta imprevizibil. Pentru a face față acestei situații, vom stabili și utiliza playbackPaused
steag. Mai întâi modificați playNext
și playPrev
metode:
private void playNext () musicSrv.playNext (); dacă (playbackPaused) setController (); playbackPaused = false; controller.show (0); void play privatPrev () musicSrv.playPrev (); dacă (playbackPaused) setController (); playbackPaused = false; controller.show (0);
Resetăm controlerul și actualizăm playbackPaused
semnalizare atunci când redarea a fost întreruptă. Faceți acum modificări similare cu playSong
metodă:
public void songPicked (Vizualizare vedere) musicSrv.setSong (Integer.parseInt (view.getTag (). toString ())); musicSrv.playSong (); dacă (playbackPaused) setController (); playbackPaused = false; controller.show (0);
Acum setați playbackPaused
la Adevărat în pauză
metodă:
@ Pauză void publice void () playbackPaused = true; musicSrv.pausePlayer ();
Pe măsură ce lucrați cu Media Player
și MediaController
clase, veți găsi că acest tip de procesare este o cerință necesară pentru a evita erorile. De exemplu, uneori veți găsi că bara de căutare a controlerului nu se actualizează până când utilizatorul nu interacționează cu acesta. Aceste resurse se comportă diferit pe diferite niveluri API, astfel încât testarea și optimizarea detaliată sunt esențiale dacă intenționați să lansați aplicația dvs. către public. Aplicația pe care o creăm în această serie este într-adevăr doar o fundație.
Să facem niște pași finali pentru a face ca aplicația să se comporte în mod consecvent. Înapoi în Serviciu
clasa, modificați onerror
metodă:
@Override public boolean onError (MediaPlayer mp, int ce, int extra) mp.reset (); return false;
Restabilim pur și simplu player-ul, dar, bineînțeles, doriți să îmbunătățiți această abordare.
onCompletion
metoda se va declanșa când o piesă se termină, inclusiv cazurile în care utilizatorul a ales o piesă nouă sau a omis la pista următoare / anterioară, precum și atunci când piesa atinge sfârșitul redării. În cel de-al doilea caz, dorim să continuăm redarea prin redarea piesei următoare. Pentru a face acest lucru trebuie să verificăm starea de redare. Modificați-vă onCompletion
metodă:
@Override publice void onCompletion (MediaPlayer mp) if (player.getCurrentPosition ()> 0) mp.reset (); playNext ();
Noi numim playNext
dacă piesa curentă a ajuns la final.
Serviciu
clasa de a pune în aplicare AudioManager.OnAudioFocusChangeListener
interfață. În onCreate
metoda, creați o instanță a AudioManager
clasa și apelul requestAudioFocus
pe el. În cele din urmă, pune în aplicare onAudioFocusChange
metoda din clasa ta pentru a controla ce ar trebui să se întâmple când aplicația câștigă sau pierde focalizarea audio. Vedeți secțiunea Focalizare audio în Ghidul dezvoltatorului pentru mai multe detalii. Aceasta este completă aplicația de bază! Cu toate acestea, este posibil să trebuiască să efectuați îmbunătățiri suplimentare pentru a funcționa în mod fiabil între dispozitivele utilizatorilor și nivelurile API-urilor. Comenzile ar trebui să apară ori de câte ori interacționați cu aplicația.
Notificarea vă va permite să reveniți la aplicație în timp ce redarea continuă.
Am terminat acum playerul de bază pentru Android. Există multe modalități prin care puteți îmbunătăți aplicația, cum ar fi adăugarea de suport pentru media streaming, video, focalizare audio și furnizarea de metode diferite pentru a interacționa cu piesele muzicale de pe dispozitiv. Vom analiza unele dintre aceste îmbunătățiri în viitoarele tutoriale, subliniind cum le puteți adăuga în aplicație sau în alte proiecte de redare media. Între timp, verificați dacă puteți extinde aplicația pentru a crea funcții suplimentare sau pentru a îmbunătăți fiabilitatea pe diferite dispozitive. Consultați secțiunea Redarea în mass-media a Ghidului pentru dezvoltatori Android pentru mai multe informații.