O bună abordare pentru a deveni competenți într-un nou limbaj de programare sau o bibliotecă este să încercați să creați ceva util cu el. În tutorialul meu privind simplificarea dezvoltării Android cu Anko, v-am prezentat funcțiile limbajului și funcțiile de ajutor ale lui Anko. Deși sunt sigur că le-ați găsit impresionante, ați putea fi totuși îngrijorat de utilizarea lor în aplicații mari și complexe, deoarece sunt atât de diferite de clase și metode tradiționale Android.
Așa că astăzi vom folosi Kotlin și Anko pentru a crea o aplicație pentru Android pentru muzică, care poate alege și reda automat melodii aleatorii de pe dispozitivul utilizatorului. Interfața sa de utilizator relativ complexă, care va avea mai multe widgeturi diferite care interacționează unul cu celălalt, ar trebui să vă ajute să înțelegeți mai bine cum funcționează aplicațiile Anko.
Pentru a putea urmări acest tutorial pas cu pas, veți avea nevoie de:
Dacă nu ați făcut deja acest lucru, citiți următorul tutorial înainte de a continua:
Lansați Android Studio și apăsați pe Porniți un nou proiect Android Studio pentru a porni expertul de creare a proiectului. În ecranul următor, dați aplicației dvs. un nume și asigurați-vă că Includeți suportul Kotlin câmpul este verificat.
Apoi, atingeți nivelul API 21 sau mai mare și alegeți Activitate goală șablon. Pentru că nu vom avea nevoie de fișiere XML, asigurați-vă că deselectați Generați fișierul de dispunere camp.
În cele din urmă, apăsați finalizarea pentru a crea proiectul.
Pentru a adăuga Anko la proiect, adăugați următoarele punerea în aplicare
dependența în build.gradle fișier al aplicaţia
modul:
implementare "org.jetbrains.anko: anko: 0.10.1 '
Vom folosi corutinele lui Kotlin pentru a efectua câteva operații în mod asincron, deci adăugați o dependență pentru el în continuare.
implementare "org.jetbrains.kotlinx: kotlinx-coroutines-android: 0.19.3 '
Playerul nostru de muzică, deoarece redă melodii la întâmplare, are nevoie de o listă cu toate melodiile disponibile pe dispozitiv. Pentru a evita implementarea logicii pentru crearea unei astfel de liste, adăugați DroidMelody, o bibliotecă pe care am creat-o special pentru acest tutorial, ca ultima dependență. Deoarece este aprobat și publicat de jcenter, depozitul implicit al Android Studio, adăugând că nu este diferit de adăugarea oricărei alte dependențe.
implementare 'com.progur.droidmelody: droidmelody: 1.0.2'
În plus, vom avea nevoie de câteva pictograme legate de mass-media, așa că deschideți Vector Asset Studio în continuare. Înăuntru, navigați la AV și selectați pictogramele cu simbolurile de redare, pauză și amestecare.
În acest moment, următoarele fișiere ar trebui să fie prezente în res / drawable dosarul proiectului:
Cei mai mulți utilizatori stochează melodiile pe medii de stocare externe. Prin urmare, pe dispozitive care rulează Android Marshmallow sau mai mult, va trebui să solicităm în mod explicit READ_EXTERNAL_STORAGE
permisiune la ora de rulare.
Înainte de a cere permisiunea, trebuie să verificați dacă utilizatorul a acordat-o deja. Puteți face acest lucru prin apelarea ContextCompat.checkSelfPermission ()
în interiorul metodei onCreate ()
metoda dvs. de activitate. Dacă permisiunea nu a fost acordată, puteți să o solicitați apelând ActivityCompat.requestPermissions ()
metodă.
În consecință, adăugați următorul cod:
dacă (ContextCompat.checkSelfPermission (this, Manifest.permission.READ_EXTERNAL_STORAGE)! = PackageManager.PERMISSION_GRANTED) // Cereți permisiunea ActivityCompat.requestPermissions (this, arrayOf (Manifest.permission.READ_EXTERNAL_STORAGE), 0) altceva // Start crearea interfeței cu utilizatorul createPlayer ()
Rețineți că codul de mai sus solicită o metodă numită createPlayer ()
dacă permisiunea a fost deja acordată. Vom crea această metodă în pasul următor.
După ce cereți permisiunea, trebuie să o înlocuiți onRequestPermissionsResult ()
metoda activității pentru a determina dacă utilizatorul a acceptat solicitarea dvs. Dacă au făcut-o, trebuie să sunați din nou createPlayer ()
metodă. Dacă nu, afișați un mesaj de eroare folosind Anko's longToast ()
helper și închideți aplicația.
suprascrie distracția onRequestPermissionsResult (requestCode: Int, permisiuni: Array, grantResults: IntArray) super.onRequestPermissionsResult (requestCode, permisiuni, grantResults) dacă grantResults [0] == PackageManager.PERMISSION_GRANTED) createPlayer () altceva longToast
Acum este momentul să definiți createPlayer ()
, care va fi responsabilă atât de aspectul, cât și de funcționalitatea aplicației noastre.
distracție privată createPlayer () // Mai mult cod aici
În interiorul metodei, primul lucru pe care trebuie să-l faceți este să generați o listă cu toate melodiile disponibile pe dispozitiv. Deoarece acest lucru este, după cum s-ar putea să vă așteptați, o operație potențial de lungă durată, o puteți lansa într-o nouă corutină folosind async ()
funcţie.
În interiorul corutinei, creați o nouă instanță a lui DroidMelody SongFinder
clasa și numesc-o a pregati()
, care utilizează resolverul de conținut al activității dvs. pentru a găsi toate melodiile și a le plasa într-o listă numită Toate cintecele
. După finalizarea metodei, puteți reveni pur și simplu Toate cintecele
din corutină. Următorul cod vă arată cum:
val melodiiJob = async val songFinder = SongFinder (contentResolver) songFinder.prepare () songFinder.allSongs
Corutina de mai sus rulează asincron. Pentru a aștepta rezultatul, trebuie să apelați așteaptă ()
în interiorul unei alte corutine creată folosind lansa()
funcţie. Pentru că vom folosi rezultatul pentru a crea interfața de utilizator a aplicației, noua corutină ar trebui să ruleze pe firul UI. Acest lucru este specificat prin trecere kotlinx.coroutines.experimental.android.UI
ca un argument pentru lansa()
.
lansați (kotlinx.coroutines.experimental.android.UI) val songs = songsJob.await () // Mai multe coduri aici
Acum ai o listă de Cântec
obiecte. Fiecare Cântec
obiect va avea mai multe detalii importante despre piesa pe care o citează, cum ar fi titlul, artistul, albumul și URI.
Implicit, DSL-ul Anko este disponibil direct numai în interiorul lui onCreate ()
metodă a unei activități. Pentru a putea folosi în interiorul createPlayer ()
metoda, puteți fie să depindeți de UI ()
sau creați o nouă componentă Anko. În acest tutorial, vom merge cu această din urmă abordare, deoarece este mai reutilizabilă.
Pentru a crea o nouă componentă Anko, trebuie să extindeți rezumatul AnkoComponent
clasa și suprascrie createView ()
în care veți avea acces la DSL.
val playerUI = obiect: AnkoComponentsuprascrie fun createView (ui: AnkoContext ) = cu (ui) // codul DSL aici
Deoarece aplicația noastră este un player de muzică aleatoriu și nu unul care poate funcționa cu playlisturi, va avea o interfață ușor neconvențională. Iată widget-urile vizibile pe care le va conține:
ImageView
widget pentru a afișa arta albumului pe care o cântați în prezentImageButton
widget care permite utilizatorului să întrerupă sau să reia melodiaImageButton
widget care permite utilizatorului să aleagă un alt cântec aleatoriuTextView
widget pentru a afișa titlul cânteculuiTextView
widget pentru a afișa numele artistului cânteculuiÎn consecință, adăugați următoarele câmpuri la Componentul Anko:
var albumArt: ImageView? = null var playButton: ImageButton? = null var shuffleButton: ImageButton? = null var songTitle: TextView? = null var songArtist: TextView? = nul
În plus, avem nevoie de a RelativeLayout
și câteva LinearLayout
containere pentru a poziționa widget-urile de mai sus și pentru a stabili relații între ele. Următoarea diagramă arată ierarhia de vizualizare pe care o vom crea în continuare:
Deoarece RelativeLayout
widget-ul este la baza ierarhiei de vizualizare, trebuie să îl creați mai întâi adăugând următorul cod în interiorul createView ()
metodă a componentei Anko:
relativeLayout backgroundColor = Culoare.BLACK // Mai mult cod aici
Rețineți că am folosit culoare de fundal
proprietate a widget-ului pentru a da o culoare neagră. Vom folosi mai multe astfel de proprietăți în acest tutorial pentru ca aplicația noastră să arate mai bine. Aveți libertatea de a vă schimba valorile pentru a se potrivi preferințelor dvs..
În interiorul RelativeLayout
widget, adăugați ImageView
widget pentru arta albumului. Ar trebui să ia tot spațiul disponibil pe ecran, deci utilizați lparams ()
după adăugarea lui și trecerea lui parinte potrivit
constante la ea de două ori, o dată pentru lățimea și o dată pentru înălțime. Iată cum:
albumArt = imagineView scaleType = ImageView.ScaleType.FIT_CENTER .lparams (matchParent, matchParent)
lparams ()
metoda, așa cum sugerează și numele, vă permite să specificați parametrii de aspect care ar trebui să fie asociați cu un widget. Folosind-o, puteți să specificați rapid detalii cum ar fi marginile pe care trebuie să le aibă un widget, dimensiunile și poziția sa.
Apoi, creați un LinearLayout
widget cu o orientare verticală prin apelarea verticalLayout ()
funcția și adăugați TextView
widget-uri pentru ea. Aspectul trebuie plasat în partea de jos a ecranului, deci trebuie să apelați alignParentBottom ()
funcție în timp ce specifică parametrii de aspect.
verticalLayout backgroundColor = Culoare.parseColor ("# 99000000") songTitle = textView textColor = Culoare.WHITE typeface = Tipface.DEFAULT_BOLD textSize = 18f songArtist = textView textColor = Culoare.WHITE matchParent, wrapContent) alignParentBottom ()
În mod similar, creați LinearLayout
widget cu o orientare orizontală prin apelarea LinearLayout ()
funcția și adăugați cele două ImageButton
widget-uri pentru ea. Asigurați-vă că utilizați imageResource
proprietățile butoanelor pentru a specifica pictogramele pe care ar trebui să le afișeze. Următorul cod vă arată cum:
lineLayout playButton = imagineButton 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 (0, wrapContent, 0.5f) .lparams (matchParent, wrapContent) topMargin = dip (5)
Puteți observa că codul de mai sus are dispozitive de procesare a evenimentului pentru clicuri pentru ambele ImageButton
widget-uri. În interiorul operatorilor, există apeluri la două metode intuitiv numite: playOrPause ()
și playRandom ()
. Îi vom crea în următorii pași.
În acest moment, am terminat să definim aspectul aplicației noastre.
Aplicația noastră este încă incapabilă să cânte muzică. Să rezolvăm asta creând playRandom ()
metodă.
fun playRandom () // Mai mult cod aici
Vom folosi o instanță a Media Player
clasa pentru a reda muzica. Este o resursă destul de scumpă și ar trebui lansată când utilizatorul închide aplicația. Prin urmare, trebuie definit ca un domeniu al activității - și nu componenta Anko - și eliberat în interiorul onDestroy ()
metodă a activității.
privat var mediaPlayer: MediaPlayer? = distruge distracția null onDestroy () mediaPlayer? .release () super.onDestroy ()
În interiorul playRandom ()
, acum putem alege un cântec aleatoriu din lista melodiilor pe care le-am generat mai devreme prin simpla amestecare a listei și alegerea primului element. Această abordare nu este foarte eficientă, dar este foarte concisă.
Collections.shuffle (melodii) val song = melodii [0]
Acum puteți inițializa playerul media cu URI-ul piesei noi selectate. În plus, utilizați setOnCompletionListener ()
pentru a vă asigura că o melodie nouă aleatorie începe să fie redată imediat ce piesa curentă se termină.
mediaPlayer? .reset () mediaPlayer = MediaPlayer.create (ctx, song.uri) mediaPlayer? .setOnCompletionListener playRandom ()
Conținutul mesajului ImageView
și TextView
și widget-urile trebuie să fie actualizate pentru a afișa detaliile asociate cu piesa nouă.
albumArt? .imageURI = song.albumArt songTitle? .text = song.title songArtist? .text = song.artist
În cele din urmă, pentru a începe să jucați melodia, puteți apela start()
metoda media player-ului. Acum ar fi momentul potrivit să actualizați ImageButton
widget pentru a schimba pictograma "play" în pictograma "pauză".
mediaPlayer? .start () playButton? .imageResource = R.drawable.ic_pause_black_24dp
Într-un pas anterior, am numit o metodă numită playOrPause ()
în interiorul handler-ului unui clic ImageButton
widget-uri. Definiți-o ca o altă metodă a componentei Anko.
distracție playOrPause () // Mai mult cod aici
Logica pe care trebuie să o implementați în cadrul acestei metode ar trebui să fie destul de evidentă. Dacă playerul media redă deja o melodie, pe care o puteți verifica folosind se joacă
proprietate, numiți-o pauză()
și afișați pictograma "play" în ImageButton
. În caz contrar, apelați start()
și afișați pictograma "pauză".
val songPlaying: Boolean? = MediaPlayer? .isPlaying dacă (songPlayer == true) mediaPlayer? .pause () playButton? .imageResource = R.drawable.ic_play_arrow_black_24dp altceva mediaPlayer? .start () playButton? .imageResource = R.drawable.ic_pause_black_24dp
Componenta noastră Anko este acum pregătită.
Doar crearea unei componente Anko nu este suficientă. Trebuie, de asemenea, să vă asigurați că o redați prin apelarea sa setContentView ()
și trecerea unei activități către el. Pentru moment, puteți trece activitatea principală la aceasta.
Opțional, dacă doriți ca aplicația să înceapă să cânte o melodie de îndată ce utilizatorul o deschide, puteți apela playRandom ()
din nou acum.
playerUI.setContentView (acest @ MainActivity) playerUI.playRandom ()
Aplicația noastră este gata. Dacă îl rulați pe un dispozitiv care are unul sau mai multe fișiere MP3 cu taguri ID3 corect formatate și artă de album încorporată, ar trebui să vedeți ceva similar cu acesta:
În acest tutorial, ați învățat cum să creați o aplicație pentru music player cu o ierarhizare complexă de vizualizare folosind doar Anko și Kotlin. În timp ce faceți acest lucru, ați lucrat cu mai multe caracteristici avansate ale ambelor, cum ar fi corutine și ajutoare pentru parametrii de aspect. De asemenea, ați învățat cum să faceți codul Anko mai modular și reutilizabil prin crearea componentelor Anko.
Simțiți-vă liber să adăugați mai multe funcționalități aplicației sau să modificați aspectul acesteia pentru a vă oferi o notă personală!
Și în timp ce sunteți aici, verificați câteva dintre celelalte postări de pe Kotlin și codificați aplicațiile Android!