Crea un lettore musicale su Android controlli utente

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.

Alla ricerca di una scorciatoia?

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 Android

O 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.

introduzione

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.

1. Creare un controller

Passo 1

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.

Passo 2

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.

Mancia: Potrebbe essere necessario modificare il tema utilizzato dall'app per garantire che il testo del controller multimediale sia chiaramente visibile.

Passaggio 3

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.

2. Implementare il controllo di riproduzione

Passo 1

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.

Passo 2

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.

Passaggio 3

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 (); 

3. Gestire la navigazione di nuovo nell'app

Passo 1

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); 

4. Riproduzione casuale

Passo 1

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.

Passo 2

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.

5. Tidy Up

Passo 1

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 (); 

Passo 2

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.

Passaggio 3

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.

Mancia: Per assicurarti che la tua app non interferisca con altri servizi audio sul dispositivo dell'utente, devi migliorarla per gestire con garbo l'audio. Fare il 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.


Conclusione

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.