Un buon approccio per diventare abili in un nuovo linguaggio o libreria di programmazione è cercare di creare qualcosa di utile con esso. Nel mio tutorial su come semplificare lo sviluppo di Android con Anko, ho introdotto la lingua e le funzioni di supporto specifiche di Anko. Anche se sono sicuro che li hai trovati impressionanti, potresti essere ancora preoccupato di utilizzarli in app grandi e complesse, dal momento che sono così diverse dalle tradizionali classi e metodi Android.
Quindi, oggi useremo Kotlin e Anko per creare un'app per music player per Android, una che possa selezionare e riprodurre automaticamente brani casuali dal dispositivo dell'utente. La sua interfaccia utente abbastanza complessa, che avrà diversi widget che interagiscono tra loro, dovrebbe aiutarti a capire meglio come funzionano le app Anko.
Per poter seguire questo tutorial passo passo, avrai bisogno di:
Se non lo hai già fatto, leggi il seguente tutorial prima di procedere:
Avvia Android Studio e premi il tasto Avvia un nuovo progetto Android Studio pulsante per avviare la procedura guidata di creazione del progetto. Nella schermata successiva, dai un nome alla tua app e assicurati che il Include il supporto Kotlin il campo è selezionato.
Successivamente, seleziona API di livello 21 o versione successiva e scegli Attività vuota modello. Poiché non avremo bisogno di alcun file XML di layout, assicurati di deselezionare l'opzione Genera file di layout campo.
Finalmente, premi finire per creare il progetto.
Per aggiungere Anko al progetto, aggiungi quanto segue implementazione
dipendenza nel build.gradle file del App
modulo:
implementazione 'org.jetbrains.anko: anko: 0.10.1'
Useremo le coroutine di Kotlin per eseguire alcune operazioni in modo asincrono, quindi aggiungiamo una dipendenza per il prossimo.
implementazione 'org.jetbrains.kotlinx: kotlinx-coroutines-android: 0.19.3'
Il nostro lettore musicale, poiché riproduce le canzoni in modo casuale, necessita di un elenco di tutti i brani disponibili sul dispositivo. Per evitare di implementare la logica per creare un elenco di questo tipo, aggiungi DroidMelody, una libreria che ho creato appositamente per questo tutorial, come ultima dipendenza. Poiché è approvato e pubblicato da jcenter, il repository predefinito di Android Studio, aggiungendolo non è diverso dall'aggiunta di altre dipendenze.
implementazione 'com.progur.droidmelody: droidmelody: 1.0.2'
Inoltre, avremo bisogno di alcune icone relative ai media, quindi apri Vector Asset Studio. Al suo interno, vai al AV categoria e scegli le icone con i simboli play, pause e shuffle.
A questo punto, i seguenti file dovrebbero essere presenti in res / drawable cartella del tuo progetto:
La maggior parte degli utenti memorizza le proprie canzoni su un supporto di memorizzazione esterno. Pertanto, su dispositivi con Android Marshmallow o versioni successive, sarà necessario richiedere esplicitamente READ_EXTERNAL_STORAGE
permesso in fase di esecuzione.
Prima di richiedere l'autorizzazione, tuttavia, è necessario verificare se l'utente lo ha già concesso. Puoi farlo chiamando il ContextCompat.checkSelfPermission ()
metodo all'interno del onCreate ()
metodo della tua attività. Se il permesso non è stato concesso, puoi richiederlo chiamando il ActivityCompat.requestPermissions ()
metodo.
Di conseguenza, aggiungere il seguente codice:
if (ContextCompat.checkSelfPermission (this, Manifest.permission.READ_EXTERNAL_STORAGE)! = PackageManager.PERMISSION_GRANTED) // Richiedi il permesso ActivityCompat.requestPermissions (this, arrayOf (Manifest.permission.READ_EXTERNAL_STORAGE), 0) else // Inizio creando l'interfaccia utente createPlayer ()
Nota che il codice sopra chiama un metodo chiamato createPlayer ()
se il permesso è già stato concesso. Creeremo questo metodo nel prossimo passaggio.
Dopo aver chiesto il permesso, è necessario ignorare il onRequestPermissionsResult ()
metodo dell'attività per determinare se l'utente ha accettato la richiesta. Se lo facessero, dovresti chiamare di nuovo il createPlayer ()
metodo. In caso contrario, visualizza un messaggio di errore utilizzando Anko longToast ()
aiutante e chiudi l'app.
override fun onRequestPermissionsResult (requestCode: Int, permessi: Array, grantResults: IntArray) super.onRequestPermissionsResult (requestCode, permissions, grantResults) if (grantResults [0] == PackageManager.PERMISSION_GRANTED) createPlayer () else longToast ("Autorizzazione non concessa. Chiusura.") finish ()
È giunto il momento di definire il createPlayer ()
metodo, che sarà responsabile sia dell'aspetto che della funzionalità della nostra app.
divertimento privato createPlayer () // Altro codice qui
All'interno del metodo, la prima cosa che devi fare è generare un elenco di tutti i brani disponibili sul dispositivo. Poiché questo è, come ci si potrebbe aspettare, un'operazione potenzialmente di lunga durata, è possibile avviarla in una nuova coroutine utilizzando il comando async ()
funzione.
All'interno della coroutine, crea una nuova istanza di DroidMelody SongFinder
classe e chiama il suo preparare()
metodo, che utilizza il risolutore del contenuto della tua attività per trovare effettivamente tutti i brani e inserirli in un elenco chiamato tutte le canzoni
. Una volta completato il metodo, puoi semplicemente tornare tutte le canzoni
dalla coroutine. Il seguente codice mostra come:
val songsJob = async val songFinder = SongFinder (contentResolver) songFinder.prepare () songFinder.allSongs
La suddetta coroutine funziona in modo asincrono. Per attendere il risultato, è necessario chiamare il attendere ()
metodo all'interno di un'altra coroutine creata usando il lanciare()
funzione. Poiché utilizzeremo il risultato per creare l'interfaccia utente della nostra app, la nuova coroutine dovrebbe essere eseguita sul thread dell'interfaccia utente. Questo è specificato passando kotlinx.coroutines.experimental.android.UI
come argomento a lanciare()
.
launch (kotlinx.coroutines.experimental.android.UI) val songs = songsJob.await () // Più codice qui
Ora hai un elenco di Canzone
oggetti. Ogni Canzone
oggetto avrà diversi dettagli importanti sulla canzone a cui fa riferimento, come il titolo, l'artista, la copertina dell'album e l'URI.
Per impostazione predefinita, il DSL di Anko è direttamente disponibile solo all'interno di onCreate ()
metodo di un'attività. Per essere in grado di usarlo all'interno del createPlayer ()
metodo, puoi o dipendere dal UI ()
funzione o creare un nuovo componente Anko. In questo tutorial andremo con quest'ultimo approccio perché è più riutilizzabile.
Per creare un nuovo componente Anko, devi estendere l'abstract AnkoComponent
classe e scavalca il suo createView ()
metodo, all'interno del quale si avrà accesso alla DSL.
val playerUI = object: AnkoComponentoverride fun createView (ui: AnkoContext ) = con (ui) // codice DSL qui
Poiché la nostra app è un lettore musicale casuale, e non è in grado di funzionare con le playlist, avrà un'interfaccia utente leggermente anticonvenzionale. Ecco i widget visibili che conterrà:
ImageView
widget per visualizzare le copertine degli album del brano attualmente in riproduzioneImageButton
widget che consente all'utente di mettere in pausa o riprendere la canzoneImageButton
widget che consente all'utente di scegliere un'altra canzone a casoTextView
widget per visualizzare il titolo del branoTextView
widget per visualizzare il nome dell'artista del branoDi conseguenza, aggiungere i seguenti campi al componente Anko:
var albumArt: ImageView? = null var playButton: ImageButton? = null var shuffleButton: ImageButton? = null var songTitle: TextView? = null var songArtist: TextView? = null
Inoltre, avremo bisogno di un RelativeLayout
e un paio di LinearLayout
contenitori per posizionare i widget di cui sopra e stabilire relazioni tra loro. Il seguente diagramma mostra la gerarchia della vista che verrà creata successivamente:
Perché il RelativeLayout
il widget si trova nella radice della gerarchia della vista, devi prima crearlo aggiungendo il seguente codice all'interno della createView ()
metodo del componente Anko:
relativeLayout backgroundColor = Color.BLACK // Altro codice qui
Nota che abbiamo usato il colore di sfondo
proprietà del widget per dargli un colore nero. Useremo diverse proprietà in questo tutorial per migliorare l'aspetto della nostra app. Sei libero di cambiare i loro valori per soddisfare le tue preferenze.
Dentro il RelativeLayout
widget, aggiungi il ImageView
widget per l'arte dell'album. Dovrebbe occupare tutto lo spazio disponibile sullo schermo, quindi utilizzare lparams ()
metodo dopo averlo aggiunto e passato il partita genitore
costante ad esso due volte, una volta per la larghezza e una volta per l'altezza. Ecco come:
albumArt = imageView scaleType = ImageView.ScaleType.FIT_CENTER .lparams (matchParent, matchParent)
Il lparams ()
metodo, come suggerisce il nome, consente di specificare i parametri di layout che dovrebbero essere associati a un widget. Usandolo, puoi specificare rapidamente dettagli come i margini che un widget dovrebbe avere, le sue dimensioni e la sua posizione.
Quindi, crea un LinearLayout
widget con un orientamento verticale chiamando il verticalLayout ()
funzione e aggiungere il TextView
widget ad esso. Il layout deve essere posizionato nella parte inferiore dello schermo, quindi è necessario chiamare il alignParentBottom ()
funzione mentre si specificano i suoi parametri di layout.
verticalLayout backgroundColor = Color.parseColor ("# 99000000") songTitle = textView textColor = Color.WHITE typeface = Typeface.DEFAULT_BOLD textSize = 18f songArtist = textView textColor = Color.WHITE // Più codice qui .lparams ( matchParent, wrapContent) alignParentBottom ()
Allo stesso modo, crea il LinearLayout
widget con un orientamento orizzontale chiamando il LinearLayout ()
funzione, e aggiungere i due ImageButton
widget ad esso. Assicurati di usare il imageResource
proprietà dei pulsanti per specificare le icone da visualizzare. Il seguente codice mostra come:
linearLayout playButton = imageButton imageResource = R.drawable.ic_play_arrow_black_24dp onClick playOrPause () .lparams (0, wrapContent, 0.5f) shuffleButton = imageButton imageResource = R.drawable.ic_shuffle_black_24dp onClick playRandom () .lparams (0, wrapContent, 0.5f) .lparams (matchParent, wrapContent) topMargin = dip (5)
È possibile vedere che il codice precedente ha gestori di eventi click per entrambi ImageButton
widgets. All'interno dei gestori, ci sono chiamate a due metodi denominati in modo intuitivo: playOrPause ()
e visualizzarloRandom ()
. Li creeremo nei prossimi passaggi.
A questo punto, abbiamo finito di definire l'aspetto della nostra app.
La nostra app non è ancora in grado di riprodurre alcuna musica. Risolviamolo creando il file visualizzarloRandom ()
metodo.
fun playRandom () // Altro codice qui
Useremo un'istanza di Media Player
classe per suonare la musica. È una risorsa piuttosto costosa e dovrebbe essere rilasciata quando l'utente chiude l'app. Pertanto, deve essere definito come un campo dell'attività - e non il componente Anko - e rilasciato all'interno di OnDestroy ()
metodo dell'attività.
private var mediaPlayer: MediaPlayer? = null override fun onDestroy () mediaPlayer? .release () super.onDestroy ()
Dentro il visualizzarloRandom ()
metodo, ora possiamo scegliere una canzone a caso dalla lista di canzoni che abbiamo generato in precedenza semplicemente mischiando la lista e selezionando il primo elemento. Questo approccio non è molto efficiente, ma è molto conciso.
Collections.shuffle (canzoni) val song = songs [0]
È ora possibile inizializzare il lettore multimediale con l'URI della nuova canzone scelta. Inoltre, utilizzare il setOnCompletionListener ()
metodo per assicurarsi che una nuova canzone casuale inizi a suonare non appena il brano corrente è completato.
mediaPlayer? .reset () mediaPlayer = MediaPlayer.create (ctx, song.uri) mediaPlayer? .setOnCompletionListener playRandom ()
Il contenuto del ImageView
e TextView
anche i widget devono essere aggiornati per visualizzare i dettagli associati alla nuova canzone.
albumArt? .imageURI = song.albumArt songTitle? .text = song.title songArtist? .text = song.artist
Infine, per iniziare effettivamente a suonare la canzone, puoi chiamare il inizio()
metodo del lettore multimediale. Ora sarebbe anche il momento giusto per aggiornare il ImageButton
widget per cambiare l'icona "riproduci" in un'icona "pausa".
mediaPlayer? .start () playButton? .imageResource = R.drawable.ic_pause_black_24dp
In un passo precedente, abbiamo chiamato un metodo chiamato playOrPause ()
all'interno del click-handler di uno dei ImageButton
widgets. Definirlo come un altro metodo del componente Anko.
fun playOrPause () // Altro codice qui
La logica che devi implementare all'interno di questo metodo dovrebbe essere abbastanza ovvia. Se il lettore multimediale sta già suonando una canzone, che puoi verificare usando il sta giocando
proprietà, chiamatela pausa()
metodo e visualizza l'icona "play" nel menu ImageButton
. Altrimenti, chiama il inizio()
metodo e visualizzare l'icona "pausa".
val songPlaying: Boolean? = mediaPlayer? .isPlaying if (songPlaying == true) mediaPlayer? .pause () playButton? .imageResource = R.drawable.ic_play_arrow_black_24dp else mediaPlayer? .start () playButton? .imageResource = R.drawable.ic_pause_black_24dp
Il nostro componente Anko è ora pronto.
La semplice creazione di un componente Anko non è sufficiente. Devi anche assicurarti di renderizzarlo chiamando il suo setContentView ()
metodo e passando un'attività ad esso. Per ora, puoi passare l'attività principale ad esso.
Se lo desideri, se vuoi che l'app inizi a riprodurre un brano non appena l'utente lo apre, puoi chiamare il visualizzarloRandom ()
metodo di nuovo ora.
playerUI.setContentView (this @ MainActivity) playerUI.playRandom ()
La nostra app è pronta. Se lo esegui su un dispositivo che ha uno o più file MP3 con tag ID3 formattati correttamente e copertine di album incorporati, dovresti vedere qualcosa di simile a questo:
In questo tutorial, hai imparato come creare un'app di lettore musicale con una complessa gerarchia di viste usando solo Anko e Kotlin. Mentre lo facevi, hai lavorato con diverse funzionalità avanzate di entrambi, come le coroutine e gli helper dei parametri di layout. Hai anche imparato come rendere il codice Anko più modulare e riutilizzabile creando componenti Anko.
Sentiti libero di aggiungere più funzionalità all'app o modificarne l'aspetto per dargli un tocco personale!
E mentre sei qui, dai uno sguardo ai nostri altri post su Kotlin e alla codifica delle app per Android!