In questa serie stiamo costruendo un'app per lettore musicale semplice per Android. Finora, abbiamo presentato un elenco dei brani sul dispositivo e permesso all'utente di effettuare selezioni da esso, avviando la riproduzione usando il Media Player
classe in a Servizio
classe. In questa parte finale della serie, consentiremo all'utente di controllare la riproduzione, incluso saltare alla traccia successiva e precedente, avanzare rapidamente, riavvolgere, suonare, mettere in pausa e cercare determinati punti nella traccia. Visualizzeremo anche una notifica durante la riproduzione in modo che l'utente possa tornare al lettore musicale dopo aver usato altre app.
Questa serie di tutorial ti guida attraverso il processo di creazione di un'app di lettore musicale da zero. Se vuoi una soluzione pronta, prova Android Music Player, un lettore musicale avanzato per dispositivi Android. Ti consente di sfogliare e riprodurre la tua musica per album, artisti, brani, playlist, cartelle e album artisti e ha una gamma di altre funzionalità.
Lettore musicale AndroidO se vuoi qualcosa di completamente personalizzato secondo le tue specifiche, puoi assumere uno sviluppatore Android su Envato Studio per fare qualsiasi cosa, dalle modifiche e correzioni di bug alla creazione di un'intera app da zero.
La funzionalità di controllo del lettore musicale sarà implementata usando il MediaController
classe, in cui a SeekBar
istanza visualizza l'avanzamento della riproduzione e consente all'utente di saltare a posizioni particolari in una traccia. Useremo il Notifica
e PendingIntent
classi per visualizzare il titolo della traccia in riproduzione e consentire all'utente di tornare all'app.
Ecco come deve apparire l'app quando completi questo tutorial:
Dopo questa serie esploreremo anche le funzionalità correlate che potresti voler utilizzare per migliorare l'app del lettore musicale. Ciò includerà la riproduzione di video, lo streaming multimediale, la gestione dell'audio focus e la presentazione di dati multimediali in diversi modi.
Apri il tuo principale Attività
classe e aggiungere la seguente dichiarazione di importazione:
import android.widget.MediaController.MediaPlayerControl;
Estendi la riga di apertura della dichiarazione di classe come segue, in modo che possiamo usare il Attività
classe per fornire il controllo della riproduzione:
public class MainActivity estende Activity implements MediaPlayerControl
Passa il mouse sopra il nome della classe e seleziona Aggiungi metodi non implementati. Eclipse aggiungerà vari metodi per il controllo della riproduzione, che modificheremo mentre procediamo.
Il MediaController
class presenta un widget standard con pulsanti play / pause, rewind, fast-forward e skip (precedente / successivo). Il widget contiene anche una barra di ricerca, che si aggiorna quando la canzone viene riprodotta e contiene un testo che indica la durata della canzone e la posizione corrente del giocatore. Per poter configurare i dettagli del controllo, implementeremo una classe per estenderla. Aggiungi una nuova classe al tuo progetto, nominandolo MusicController. In Eclipse, scegli android.widget.MediaController come la superclasse durante la creazione.
Dai alla classe il seguente contenuto:
public class MusicController estende MediaController public MusicController (Context c) super (c); public void hide ()
Puoi personalizzare il MediaController
classe in vari modi. Tutto ciò che vogliamo fare è impedirgli di nascondersi automaticamente dopo tre secondi ignorando il nascondere
metodo.
Torna nel tuo principale Attività
classe, aggiungi una nuova variabile di istanza:
controller MusicController privato;
Regoleremo il controller più di una volta nel ciclo di vita dell'app, quindi facciamolo con un metodo di supporto. Aggiungi il seguente snippet di codice al tuo Attività
classe:
private void setController () // imposta il controller su
All'interno del metodo, istanziare il controller:
controller = new MusicController (questo);
È possibile configurare vari aspetti del MediaController
esempio. Ad esempio, dovremo determinare cosa accadrà quando l'utente preme i pulsanti precedente / successivo. Dopo aver istanziato il controller, imposta questi listener di clic:
controller.setPrevNextListeners (new View.OnClickListener () @Override public void onClick (View v) playNext ();, new View.OnClickListener () @Override public void onClick (View v) playPrev (); );
Implementeremo visualizzarloNext
e playPrev
un po 'più tardi, quindi ignora gli errori per ora. Ancora dentro il setController
metodo, imposta il controller per lavorare sulla riproduzione multimediale nell'app, con la sua vista di ancoraggio che si riferisce all'elenco incluso nel layout:
controller.setMediaPlayer (questo); controller.setAnchorView (findViewById (R.id.song_list)); controller.setEnabled (true);
Di nuovo dentro onCreate
, chiama il metodo:
setController ();
Lo chiameremo anche altrove nella classe più tardi.
Ricorda che la riproduzione multimediale sta avvenendo nel Servizio
classe, ma che l'interfaccia utente proviene dal Attività
classe. Nel precedente tutorial, abbiamo rilegato il Attività
istanza al Servizio
esempio, in modo da poter controllare la riproduzione dall'interfaccia utente. I metodi nel nostro Attività
classe che abbiamo aggiunto per implementare il MediaPlayerControl
l'interfaccia verrà chiamata quando l'utente tenta di controllare la riproduzione. Avremo bisogno del Servizio
classe per agire su questo controllo, quindi apri il tuo Servizio
classe ora per aggiungere alcuni metodi ad esso:
public int getPosn () return player.getCurrentPosition (); public int getDur () return player.getDuration (); public boolean isPng () return player.isPlaying (); public void pausePlayer () player.pause (); public void seek (int posn) player.seekTo (posn); public void go () player.start ();
Questi metodi si applicano tutti alle funzioni di controllo della riproduzione standard che l'utente si aspetta.
Ora aggiungiamo metodi al Servizio
classe per saltare alla traccia successiva e precedente. Inizia con la funzione precedente:
public void playPrev () songPosn--; if (songPosn<0) songPosn=songs.size()-1; playSong();
Decrementiamo la variabile dell'indice del brano, controlliamo che non siamo andati oltre il range della lista e chiamiamo il playSong
metodo che abbiamo aggiunto. Ora aggiungi il metodo per saltare alla traccia successiva:
// passa al prossimo public public playNext () songPosn ++; if (songPosn> = songs.size ()) songPosn = 0; playSong ();
Questo è analogo al metodo per riprodurre la traccia precedente al momento, ma modificheremo questo metodo in un secondo momento per implementare la funzionalità shuffle.
Ora torna al tuo Attività
classe in modo che possiamo usare questi metodi. Per prima cosa aggiungi i metodi che abbiamo chiamato quando abbiamo impostato il controller:
// riproduce il prossimo vuoto privato playNext () musicSrv.playNext (); controller.show (0); // play previous private void playPrev () musicSrv.playPrev (); controller.show (0);
Chiamiamo i metodi che abbiamo aggiunto al Servizio
classe. Aggiungeremo più codice a questi in seguito per occuparci di situazioni particolari. Ora passiamo al MediaPlayerControl
metodi di interfaccia, che verranno chiamati dal sistema durante la riproduzione e quando l'utente interagisce con i controlli. Questi metodi dovrebbero già essere nel tuo Attività
classe, quindi modificheremo la loro implementazione.
Inizia con il canPause
metodo, impostandolo su vero:
@ Override public booleano canPause () return true;
Ora fai lo stesso per il canSeekBackward
e canSeekForward
metodi:
@Override public boolean canSeekBackward () return true; @Override public boolean canSeekForward () return true;
Puoi lasciare il getAudioSessionId
e getBufferPercentage
metodi come sono. Modificare il getCurrentPosition
metodo come segue:
@Override public int getCurrentPosition () if (musicSrv! = Null && musicBound && musicSrv.isPng ()) restituisce musicSrv.getPosn (); altrimenti restituisce 0;
I test condizionali devono evitare varie eccezioni che possono verificarsi quando si utilizza il Media Player
e MediaController
classi. Se si tenta di migliorare l'app in qualsiasi modo, è probabile che si verifichi che è necessario eseguire tali passaggi poiché le classi di riproduzione multimediale generano molte eccezioni. Si noti che chiamiamo il getPosn
metodo del Servizio
classe.
Modificare il getDuration
metodo allo stesso modo:
@Override public int getDuration () if (musicSrv! = Null && musicBound && musicSrv.isPng ()) restituisce musicSrv.getDur (); altrimenti restituisce 0;
Alterare il sta giocando
metodo invocando il isPng
metodo del nostro Servizio
classe:
@Override public boolean isPlaying () if (musicSrv! = Null && musicBound) restituisce musicSrv.isPng (); restituisce falso;
Fai lo stesso per il pausa
, cercare di
e inizio
metodi:
@Override public void pause () musicSrv.pausePlayer (); @Override public void seekTo (int pos) musicSrv.seek (pos); @Override public void start () musicSrv.go ();
Ricorda che continueremo la riproduzione anche quando l'utente si allontana dall'app. Per facilitare questo, verrà visualizzata una notifica che mostra il titolo della traccia in riproduzione. Facendo clic sulla notifica, l'utente tornerà nell'app. Ritorna al tuo Servizio
classe e aggiungere le seguenti importazioni aggiuntive:
import java.util.Random; importare android.app.Notification; importare android.app.PendingIntent;
Ora vai al onPrepared
metodo, in cui al momento si avvia semplicemente la riproduzione. Dopo la chiamata a Player.start ()
, aggiungi il seguente codice:
Intento notIntent = new Intent (this, MainActivity.class); notIntent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendInt = PendingIntent.getActivity (this, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT); Notification.Builder builder = new Notification.Builder (this); builder.setContentIntent (pendInt) .setSmallIcon (R.drawable.play) .setTicker (songTitle) .setOngoing (true) .setContentTitle ("Playing") .setContentText (songTitle); Notification not = builder.build (); startForeground (NOTIFY_ID, not);
Aggiungeremo le variabili mancanti dopo. Il PendingIntent
la classe riporta l'utente al principale Attività
classe quando selezionano la notifica. Aggiungi variabili per il titolo del brano e l'ID di notifica nella parte superiore della classe:
private String songTitle = ""; private static final int NOTIFY_ID = 1;
Ora abbiamo bisogno di impostare il titolo del brano, nel file playSong
metodo, dopo la riga in cui recuperiamo la canzone dalla lista (Song playSong = songs.get (songPosn);
):
songtitle = playSong.getTitle ();
Dal momento che abbiamo chiamato setForeground
sulla notifica, dobbiamo assicurarci di fermarlo quando il Servizio
l'istanza è distrutta. Sostituisci il seguente metodo:
@Override public void onDestroy () stopForeground (true);
Ricorda che abbiamo aggiunto un pulsante shuffle, quindi implementalo ora. Per prima cosa aggiungi nuove variabili di istanza al Servizio
classe:
private boolean shuffle = false; rand privato a caso;
Istanziare il generatore di numeri casuali in onCreate
:
rand = new Random ();
Ora aggiungi un metodo per impostare il flag shuffle:
public void setShuffle () if (shuffle) shuffle = false; else shuffle = true;
Attiveremo e disattiveremo semplicemente l'impostazione shuffle. Controlleremo questo flag quando l'utente salta alla traccia successiva o quando una traccia termina e inizia quella successiva. Modificare il visualizzarloNext
metodo come segue:
public void playNext () if (shuffle) int newSong = songPosn; while (newSong == songPosn) newSong = rand.nextInt (songs.size ()); songPosn = newSong; else songPosn ++; if (songPosn> = songs.size ()) songPosn = 0; playSong ();
Se il flag shuffle è attivo, scegliamo una nuova canzone dalla lista a caso, assicurandoci di non ripetere l'ultima canzone suonata. Potresti migliorare questa funzionalità utilizzando una coda di brani e impedendo che i brani vengano ripetuti fino a quando tutti i brani sono stati riprodotti.
Ora possiamo consentire all'utente di selezionare la funzione shuffle. Torna nel tuo principale Attività
classe nel onOptionsItemSelected
metodo, modifica la sezione per l'azione shuffle per chiamare il nuovo metodo che abbiamo aggiunto al Servizio
classe:
case R.id.action_shuffle: musicSrv.setShuffle (); rompere;
Ora l'utente sarà in grado di utilizzare la voce di menu per attivare la funzionalità di shuffling.
Abbiamo quasi finito, ma dobbiamo ancora aggiungere alcuni frammenti di elaborazione per gestire alcune modifiche, ad esempio l'uscita dall'app o la sospensione della riproduzione. Nel tuo Attività
classe, aggiungi un altro paio di variabili di istanza:
private boolean paused = false, playbackPaused = false;
Li useremo per far fronte all'utente che ritorna all'app dopo averlo lasciato e interagendo con i controlli quando la riproduzione stessa viene messa in pausa. Oltrepassare onPause
per impostare uno di questi flag:
@Override protected void onPause () super.onPause (); pausa = true;
Adesso sostituisci onResume
:
@Override protected void onResume () super.onResume (); se (in pausa) setController (); pausa = falso;
Ciò garantirà che il controller venga visualizzato quando l'utente torna all'app. Oltrepassare onStop
per nasconderlo:
@Override protected void onStop () controller.hide (); super.onStop ();
Se l'utente interagisce con i controlli mentre la riproduzione è in pausa, il Media Player
l'oggetto può comportarsi in modo imprevedibile. Per far fronte a questo, imposteremo e useremo il playbackPaused
bandiera. Prima modifica il visualizzarloNext
e playPrev
metodi:
private void playNext () musicSrv.playNext (); if (playbackPaused) setController (); playbackPaused = falso; controller.show (0); private void playPrev () musicSrv.playPrev (); if (playbackPaused) setController (); playbackPaused = falso; controller.show (0);
Ripristiniamo il controller e aggiorniamo il playbackPaused
flag quando la riproduzione è stata messa in pausa. Ora apportare modifiche simili al playSong
metodo:
public void songPicked (Visualizza vista) musicSrv.setSong (Integer.parseInt (view.getTag (). toString ())); musicSrv.playSong (); if (playbackPaused) setController (); playbackPaused = falso; controller.show (0);
Ora impostato playbackPaused
a vero nel pausa
metodo:
@Override public void pause () playbackPaused = true; musicSrv.pausePlayer ();
Mentre lavori con Media Player
e MediaController
classi, troverete che questo tipo di elaborazione è un requisito necessario per evitare errori. Ad esempio, a volte si scopre che la barra di ricerca del controller non si aggiorna finché l'utente non interagisce con esso. Queste risorse si comportano in modo diverso a livello di API differenti, quindi test e tweaking approfonditi sono essenziali se si prevede di rilasciare la propria app al pubblico. L'app che stiamo creando in questa serie è in realtà solo una base.
Facciamo alcuni passi finali per far sì che l'app si comporti in modo coerente. Indietro nel Servizio
classe, modificare il onError
metodo:
@Override public boolean onError (MediaPlayer mp, int what, int extra) mp.reset (); restituisce falso;
Semplicemente resettiamo il lettore, ma potreste naturalmente desiderare di migliorare questo approccio.
Il al termine
il metodo si attiva quando una traccia termina, compresi i casi in cui l'utente ha scelto una nuova traccia o saltato sulle tracce successive / precedenti e quando la traccia raggiunge la fine della sua riproduzione. In quest'ultimo caso, vogliamo continuare la riproduzione suonando la traccia successiva. Per fare questo dobbiamo controllare lo stato della riproduzione. Modifica il tuo al termine
metodo:
@Override public void onCompletion (MediaPlayer mp) if (player.getCurrentPosition ()> 0) mp.reset (); visualizzarloNext ();
Chiamiamo il visualizzarloNext
metodo se la traccia corrente ha raggiunto la sua fine.
Servizio
classe implementare il AudioManager.OnAudioFocusChangeListener
interfaccia. Nel onCreate
metodo, creare un'istanza di AudioManager
classe e chiamata requestAudioFocus
su di esso. Infine, implementa il onAudioFocusChange
metodo nella tua classe per controllare cosa dovrebbe accadere quando l'applicazione ottiene o perde audio focus. Vedi la sezione Audio Focus nella Guida per gli sviluppatori per maggiori dettagli. Questa è l'app di base completa! Tuttavia, potrebbe essere necessario eseguire ulteriori miglioramenti per renderlo funzionante in modo affidabile tra i dispositivi dell'utente e i livelli API. I controlli dovrebbero apparire ogni volta che interagisci con l'app.
La notifica dovrebbe consentire di tornare all'app mentre la riproduzione continua.
Ora abbiamo completato il lettore musicale di base per Android. Esistono molti modi in cui è possibile migliorare l'app, ad esempio l'aggiunta di supporto per streaming media, video, messa a fuoco audio e la fornitura di diversi metodi per interagire con le tracce musicali sul dispositivo. Vedremo alcuni di questi miglioramenti nei tutorial futuri, delineando come è possibile aggiungerli all'app o ad altri progetti di riproduzione multimediale. Nel frattempo, verifica se è possibile estendere l'app per creare funzionalità aggiuntive o migliorare l'affidabilità su dispositivi diversi. Per ulteriori informazioni, consulta la sezione Riproduzione multimediale della Guida per gli sviluppatori Android.