Creați o aplicație de urmărire a greutăților cu Firestore pentru cloud

Stocarea datelor aplicației dvs. în cloud este foarte importantă în aceste zile, deoarece utilizatorii tind să dețină mai multe dispozitive și doresc ca aplicațiile lor să fie sincronizate între ele. Cu Cloud Firestore, o bază de date NoSQL în timp real disponibilă pe platforma Firebase, acest lucru este mai ușor și mai sigur decât oricând.

Într-un tutorial mai devreme, v-am prezentat toate caracteristicile puternice pe care le oferă Cloud Firestore. Astăzi, vă vom arăta cum să îl utilizați alături de alte produse Firebase, cum ar fi FirebaseUI Auth și Firebase Analytics, pentru a crea o aplicație de urmărire a greutății simplă, dar foarte scalabilă.

Cerințe preliminare

Pentru a urma acest tutorial pas cu pas, veți avea nevoie de:

  • cea mai recentă versiune de Android Studio
  • un cont Firebase
  • și un dispozitiv sau emulator care rulează Android 5.0 sau o versiune ulterioară

1. Configurarea proiectului

Pentru a putea utiliza produsele Firebase în proiectul Android Studio, veți avea nevoie de pluginul Google Services Gradle, un fișier de configurare Firebase și câteva punerea în aplicare dependențe. Cu Firebase Assistant, le puteți obține cu ușurință.

Deschide asistentul plecând la Instrumente> Firebase. Apoi, selectați Google Analytics și faceți clic pe Conectați un eveniment Google Analytics legătură.

Acum puteți apăsa butonul Conectați-vă la Firebase pentru a vă conecta proiectul Android Studio la un nou proiect Firebase.

Cu toate acestea, pentru a adăuga efectiv plugin-ul și punerea în aplicare dependențe, va trebui să apăsați și Adăugați Google Analytics la aplicația dvs. buton.

Aplicația de urmărire a greutății pe care o creăm astăzi va avea doar două caracteristici: stocarea greutăților și afișarea lor ca listă ordonată în ordine inversă cronologică. Desigur, vom folosi Firestore pentru a stoca greutățile. Pentru a le afișa ca o listă, cu toate acestea, vom folosi componente legate de Firestore disponibile în biblioteca FirebaseUI. Prin urmare, adăugați următoarele punerea în aplicare dependența față de aplicaţia ale modulului build.gradle fişier:

implementare "com.firebaseui: firebase-ui-firestore: 3.2.2"

Utilizatorii trebuie să aibă posibilitatea să vadă numai greutățile proprii, nu și greutatea fiecăruia care utilizează aplicația. Prin urmare, aplicația noastră trebuie să aibă capacitatea de a-și identifica în mod unic utilizatorii. FirebaseUI Auth oferă această abilitate, deci adăugați următoarea dependență:

implementare "com.firebaseui: firebase-ui-auth: 3.2.2"

De asemenea, vom avea nevoie de câteva widgeturi de design material pentru a oferi aplicației noastre un aspect plăcut. Deci, asigurați-vă că adăugați biblioteca Suport Design și biblioteca Dialoguri materiale ca dependențe.

implementare 'com.android.support:design:26.1.0' implementare 'com.afollestad.material-dialogs: core: 0.9.6.0'

În cele din urmă, apăsați pe Sincronizați acum pentru actualizarea proiectului.

2. Configurarea autentificării Firebase

Firebase Authentication acceptă o varietate de furnizori de identitate. Cu toate acestea, toate acestea sunt dezactivate în mod prestabilit. Pentru a activa una sau mai multe dintre ele, trebuie să vizitați consola Firebase.

În consola, selectați proiectul Firebase pe care l-ați creat în pasul anterior, accesați-l Autentificare și apăsați pe Configurați metoda de conectare buton.

Pentru a permite utilizatorilor să se conecteze la aplicația noastră utilizând un cont Google, activați Google ca furnizor, oferiți unui proiect un nume semnificativ cu care se confruntă publicul și apăsați pe Salvați buton.

Google este cel mai simplu furnizor de identitate pe care îl puteți utiliza. Nu are nevoie de nici o configurație și proiectul dvs. Android Studio nu va avea nevoie de alte dependențe pentru acesta.

3. Configurarea Firestore-ului Cloud

Trebuie să activați Firestore în consola Firebase înainte de a începe să o utilizați. Pentru a face acest lucru, mergeți la Bază de date și apăsați tasta Incepe butonul prezent în Cloud Firestore Beta card.

Acum vi se va solicita să selectați un mod de siguranță pentru baza de date. Asigurați-vă că alegeți Porniți în modul blocat și apăsați butonul Permite buton.

În modul blocat, în mod implicit, nimeni nu va putea accesa sau modifica conținutul bazei de date. Prin urmare, acum trebuie să creați o regulă de securitate care permite utilizatorilor să citească și să scrie numai acele documente care îi aparțin. Începeți prin deschiderea reguli fila.

Înainte de a crea o regulă de securitate pentru baza noastră de date, trebuie să finalizăm modul în care vom stoca datele în el. Deci, să spunem că vom avea o colecție de nivel superior numită utilizatori conținând documente care reprezintă utilizatorii noștri. Documentele pot avea ID-uri unice identice cu ID-urile pe care le generează serviciul de autentificare Firebase pentru utilizatori.

Deoarece utilizatorii vor adăuga mai multe intrări în greutate în documentele lor, utilizarea unei sub-colecții pentru a stoca acele intrări este ideală. Să numim sub-colecția greutăți.

Pe baza schemei de mai sus, putem crea acum o regulă pentru cale utilizatorii / user_id / greutățile / greutate. Regula va fi aceea că un utilizator este permis să citească și să scrie pe cale numai dacă numele de utilizator variabila este egală cu ID-ul de autentificare Firebase al utilizatorului.

În consecință, actualizați conținutul editorului de reguli.

serviciu cloud.firestore meci / baze de date / database / documents match / users / user_id / weights / weight permite citirea, scrie: if user_id == request.auth.uid; 

În cele din urmă, apăsați pe Publica pentru a activa regula.

4. Autentificarea utilizatorilor

Aplicația noastră trebuie să fie utilizabilă numai dacă utilizatorul este conectat la acesta folosind un cont Google. Prin urmare, de îndată ce se deschide, trebuie să verifice dacă utilizatorul are un ID valid de autentificare Firebase. Dacă utilizatorul are ID-ul, acesta ar trebui să meargă înainte și să facă interfața cu utilizatorul. Altfel, ar trebui să afișeze un ecran de conectare.

Pentru a verifica dacă utilizatorul are un ID, putem verifica dacă utilizator curent proprietate a FirebaseAuth clasa nu este nulă. Dacă este nulă, putem crea o intenție de conectare prin apelarea createSignInIntentBuilder () metodă a AuthUI clasă.

Următorul cod vă arată cum să faceți acest lucru pentru Google ca furnizor de identitate:

dacă (FirebaseAuth.getInstance (). curentUser == null) // Înscrieți startActivityForResult (AuthUI.getInstance (). createSignInIntentBuilder () .setAvailableProviders (arrayListOf () .build () ), 1) altceva // A fost deja semnat în showUI ()

Rețineți că sunăm o metodă numită showUI () dacă există deja un ID valid. Această metodă încă nu există, așa că creați-o și părăsiți acum corpul său gol.

spectacol privat distractiv () // Pentru a face

Pentru a prinde rezultatul intenției de conectare, trebuie să ignorăm onActivityResult () metodă a activității. În interiorul metodei, dacă valoarea lui resultCode argumentul este RESULT_OK si utilizator curent proprietatea nu mai este nulă, înseamnă că utilizatorul a reușit să se înregistreze cu succes. În acest caz, trebuie să sunăm din nou showUI () pentru a face interfața cu utilizatorul.

Dacă utilizatorul nu reușește să se conecteze, putem afișa un pâine prăjită și închidem aplicația apelând finalizarea() metodă.

În consecință, adăugați următorul cod la activitate:

(requestCode == 1) if (resultCode == Activity.RESULT_OK && FirebaseAuth.getInstance ()) () .currentUser! = null) // S-a semnat cu succes în showUI () altceva // Conectați-vă la Toast.makeText nereușit (trebuie să vă conectați pentru a continua, Toast.LENGTH_LONG) .show 

În acest moment, dacă rulați aplicația pentru prima dată, ar trebui să vedeți un ecran de conectare care arată astfel:

În continuare, datorită programului Google Smart Lock, care este activat implicit, veți fi conectat automat.

5. Definirea planurilor

Aplicația noastră are nevoie de două planuri: una pentru activitatea principală și una pentru intrările de greutate care vor fi afișate ca elemente ale listei ordonate în ordine cronologică.

Structura activității principale trebuie să aibă a RecyclerView widget, care va acționa ca listă, și a FloatingActionButton widget, pe care utilizatorul îl poate apăsa pentru a crea o intrare nouă în greutate. După ce le plasați pe ambele în interiorul unui RelativeLayout widgetul, fișierul XML de aspect al activității dvs. ar trebui să arate astfel:

     

Am asociat un handler de evenimente pe clic numit addWeight () cu FloatingActionButton widget. Handlerul nu există încă, așa că creați un stub pentru el în interiorul activității.

fun addWeight (v: Vizualizare) // Pentru a face

Pentru a păstra simplu aspectul introducerii în greutate, vom avea doar două TextView widget-uri din interiorul acestuia: unul pentru a afișa greutatea și celălalt pentru a afișa ora la care a fost creată înregistrarea. Folosind un LinearLayout widget ca un container pentru ei va fi suficient.

În consecință, creați un nou fișier XML cu aspect denumit weight_entry.xml și adăugați următorul cod:

    

6. Crearea unui model

În pasul anterior, ați văzut că fiecare intrare în greutate are o greutate și un timp asociat cu aceasta. Pentru a permite companiei Firestore să știe acest lucru, trebuie să creăm un model pentru intrarea în greutate.

Modelele Firestore sunt, de obicei, clase simple de date cu variabilele membre necesare.

clasa de date WeightEntry (greutate var: Double = 0.0, timestamp var: Long = 0)

Acum este, de asemenea, un moment bun pentru a crea un suport de vizualizare pentru fiecare intrare în greutate. Deținătorul de vizualizare, după cum probabil ați ghicit, va fi utilizat de către RecyclerView widget pentru a reda elementele listate. Deci, creați o nouă clasă numită WeightEntryVH, care extinde RecyclerView.ViewHolder clasă și să creeze variabile membre pentru ambele TextView widget-uri. Nu uitați să le inițializați utilizând findViewById () metodă. Următorul cod vă arată cum se face în mod concis:

Clasa WeightEntryVH (itemView: Vizualizare?): RecyclerView.ViewHolder (itemView) var weightView: TextView? = itemView? .findViewById (R.id.weight_view) var timpView: TextView? = itemView? .findViewById (R.id.time_view)

7. Crearea de documente unice pentru utilizatori

Atunci când un utilizator încearcă să creeze o înregistrare în greutate pentru prima dată, aplicația noastră trebuie să creeze un document separat pentru utilizatorul din interiorul utilizatori colectare pe Firestore. Așa cum am decis mai devreme, ID-ul documentului nu va fi altceva decât ID-ul de autentificare Firebase al utilizatorului, care poate fi obținut folosind uid proprietate a utilizator curent obiect.

Pentru a obține o referință la utilizatori de colectare, trebuie să folosim Colectie() metodă a FirebaseFirestore clasă. Atunci putem să-i sunăm document() și treceți uid ca argument pentru a crea documentul utilizatorului.

Va trebui să accesăm documentele specifice utilizatorului atât în ​​timpul citirii, cât și al creării intrărilor de greutate. Pentru a evita codarea logicii de mai sus, vă sugerăm să creați o metodă separată pentru aceasta.

distracție privată getUserDocument (): DocumentReference val db = FirebaseFirestore.getInstance () val users = db.collection ("utilizatori") val uid = FirebaseAuth.getInstance

Rețineți că documentul va fi creat o singură dată pentru fiecare utilizator. Cu alte cuvinte, apelurile multiple la metoda de mai sus vor întoarce întotdeauna același document, atât timp cât utilizatorul utilizează același cont Google.

8. Adăugarea înregistrărilor de greutate

Când utilizatorii apasă butonul de acțiune plutitor din aplicația noastră, trebuie să poată crea noi intrări în greutate. Pentru a le permite să introducă greutățile lor, să creăm un dialog care să conțină un Editează textul widget. Cu biblioteca Material Dialog, acest lucru este extrem de intuitiv.

În interiorul addWeight () , care servește ca un handler pentru evenimentul on-click al butonului, creați un MaterialDialog.Builder instanță și numiți-o titlu() și conţinut() metode pentru a oferi dialogului dvs. un titlu și un mesaj semnificativ. În mod similar, apelați tip de introducere() metodă și trecere TYPE_CLASS_NUMBER ca argument pentru a se asigura că utilizatorul poate introduce numai numere în dialog.

Apoi, apelați intrare() pentru a specifica un indiciu și a asocia un handler de evenimente cu dialogul. Operatorul va primi greutatea introdusă de utilizator ca argument.

În cele din urmă, asigurați-vă că apelați spectacol() pentru a afișa dialogul.

MaterialDialog.Builder (acest) .title ("Care este greutatea dvs. de azi?") .InputType (InputType.TYPE_CLASS_NUMBER sau InputType.TYPE_NUMBER_FLAG_DECIMAL) .input ("greutate in kilograme", " _, greutate -> // Să facă) .show ()

În cadrul procesatorului de evenimente, trebuie să adăugăm acum un cod pentru a crea și a completa un nou document de intrare în greutate. Deoarece documentul trebuie să aparțină greutăți colectarea documentului unic al utilizatorului, pentru a accesa colecția, trebuie să apelați Colectie() metoda documentului returnat de către getUserDocument () metodă.

Odată ce ai colecția, poți să-i suni adăuga() și să treacă o nouă instanță a WeightEntry clasați-l pentru a stoca intrarea.

getUserDocument () .collection ("greutăți") .add (WeightEntry (greutate până la șir () până la dublu (), dată ().

În codul de mai sus, puteți vedea că folosim timp proprietate a Data pentru a asocia o marcă de timp cu intrarea.

Dacă rulați aplicația acum, ar trebui să puteți adăuga noi intrări în greutate la Firestore. Încă nu le veți vedea în App, dar vor fi vizibile în consola Firebase.

9. Afișarea înregistrărilor de greutate

Acum este momentul să populați RecyclerView widgetul aspectului nostru. Începeți prin a crea o referință pentru aceasta folosind findViewById () și atribuirea unei noi instanțe a LinearLayoutManager clasa la ea. Acest lucru trebuie făcut în interiorul showUI () metoda pe care am creat-o mai devreme.

val weightsView = findViewById(Greutatea totală) weightsView.layoutManager = LinearLayoutManager (acest lucru)

RecyclerView widgetul trebuie să afișeze toate documentele care sunt prezente în interiorul greutăți colectarea documentului utilizatorului. În plus, ar trebui să apară mai întâi cele mai recente documente. Pentru a îndeplini aceste cerințe, trebuie să creați acum o interogare sunând la Colectie() și orderby () metode.

Din motive de eficiență, puteți limita numărul de valori returnate de interogare apelând limită() metodă.

Următorul cod creează o interogare care returnează ultimele 90 de intrări în greutate create de utilizator:

val interogare = getUserDocument () colecție ("weights") .orderBy ("timestamp", Query.Direction.DESCENDING) .limit (90)

Utilizând interogarea, trebuie să creați acum o FirestoreRecyclerOptions obiect, pe care îl vom folosi mai târziu pentru a configura adaptorul nostru RecyclerView widget. Când treceți întrebare exemplu la setQuery () metoda constructorului său, asigurați-vă că specificați că rezultatele returnate sunt sub formă de WeightEntry obiecte. Următorul cod vă arată cum să faceți acest lucru:

val opțiuni = FirestoreRecyclerOptions.Builder() .setQuery (interogare, WeightEntry :: class.java) .setLifecycleOwner (this) .build ()

S-ar putea să fi observat că facem activitatea curentă proprietarul ciclului de viață al companiei FirestoreRecyclerOptions obiect. Acest lucru este important deoarece dorim ca adaptorul nostru să răspundă în mod adecvat la evenimentele comune pe durata ciclului de viață, cum ar fi deschiderea sau închiderea aplicației.

În acest moment putem crea o FirestoreRecyclerAdapter obiect, care utilizează FirestoreRecyclerOptions obiect pentru a se configura. Deoarece FirestoreRecyclerAdapter clasa este abstractă, Android Studio ar trebui să suprascrie automat metodele de generare a codului care arată astfel:

val adapter = obiect: FirestoreRecyclerAdapter(optiune) suprascrie distractie onBindViewHolder (titular: WeightEntryVH, pozitie: Int, model: WeightEntry) // Pentru a face suprascrie fun onCreateViewHolder (parent: ViewGroup ?, viewType: Int): WeightEntryVH // To do

După cum puteți vedea, FirestoreRecyclerAdapter clasa este foarte asemănătoare cu RecyclerView.Adapter clasă. De fapt, este derivat din ea. Asta inseamna ca o poti folosi in acelasi mod in care ai putea folosi RecyclerView.Adapter clasă.

În interiorul onCreateViewHolder () metoda, tot ce trebuie să faceți este să umflați weight_entry.xml planificați fișierul și returnați a WeightEntryVH vizualizați obiectul titularului pe baza acestuia.

val layout = layoutInflater.inflate (R.layout.weight_entry, null) întoarcere WeightEntryVH (layout)

Și înăuntru onBindViewHolder () metoda, trebuie să utilizați model argument pentru a actualiza conținutul TextView widget-uri care sunt prezente în interiorul suportului de vizualizare.

În timpul actualizării weightView widget este simplu, actualizarea timeView widget-ul este ușor complicat, deoarece nu vrem să afișăm semnalul de timp, care este în milisecunde, direct utilizatorului.

Cea mai ușoară modalitate de a transforma marca de timp într-o dată și o dată de citit este să utilizați formatDateTime () metodă a DateUtils clasă. În plus față de marca de timp, metoda poate accepta mai multe drapele diferite, pe care le va folosi pentru a formata data și ora. Sunteți liber să utilizați steaguri care corespund preferințelor dvs..

Afișați data și ora val.dataData = DataUtils.formatDateTime (applicationContext, model.timestamp, DateUtils.FORMAT_SHOW_DATE sau DateUtils.FORMAT_SHOW_TIME sau DateUtils.FORMAT_SHOW_YEAR ) holder.timeView? .text = "Pe $ formattedDate"

În cele din urmă, nu uitați să indicați RecyclerView widget la adaptorul pe care tocmai l-am creat.

weightsView.adapter = adaptor

Aplicația este gata. Acum ar trebui să puteți adăuga intrări noi și să le puteți vedea imediat în listă. Dacă rulați aplicația pe un alt dispozitiv care are același cont Google, veți vedea că aceleași intrări de greutate apar și pe ea.

Concluzie

În acest tutorial, ați văzut cât de rapid și ușor este să creați o aplicație de urmărire a greutății pe deplin funcțională pentru Android utilizând Cloud Firestore ca bază de date. Simțiți-vă liber să adăugați mai multe funcționalități la acesta! Vă sugerăm, de asemenea, să încercați să o publicați pe Google Play. Cu ajutorul planului Firebase Spark, care oferă acum 1 GB de stocare a datelor gratuit, nu veți avea probleme în a servi cel puțin câteva mii de utilizatori.

Și în timp ce sunteți aici, verificați câteva dintre celelalte postări despre dezvoltarea aplicațiilor Android!

Cod