1. Introduzione
Ultimo aggiornamento: 16/11/2022
Creare un'app per Android con Firebase e Jetpack Compose
In questo codelab, creerai un'app per Android chiamata Make It So. La UI di questa app è interamente realizzata con Jetpack Compose, il moderno toolkit di Android per la creazione di una UI nativa. È intuitiva e richiede meno codice rispetto alla scrittura di file .xml e alla loro associazione ad Attività, Frammenti o Viste.
Il primo passo per capire l'efficacia dell'interazione tra Firebase e Jetpack Compose è comprendere l'architettura moderna di Android. Una buona architettura rende il sistema facile da comprendere, da sviluppare e da mantenere, poiché chiarisce molto bene come i componenti sono organizzati e comunicano tra loro. Nel mondo Android, l'architettura consigliata è Model - View - ViewModel. Il modello rappresenta il livello che accede ai dati nell'applicazione. L'elemento View è il livello UI e non deve conoscere la logica di business. Inoltre, ViewModel è il luogo in cui viene applicata la logica di business, che a volte richiede a ViewModel di chiamare il livello Model.
Ti consigliamo vivamente di leggere questo articolo per capire come Model - View - ViewModel viene applicato a un'app per Android creata con Jetpack Compose, poiché renderà il codebase più comprensibile e i passaggi successivi più facili da completare.
Cosa creerai
Make It So è una semplice applicazione per elenchi di cose da fare che consente all'utente di aggiungere e modificare attività, aggiungere indicatori, priorità e date di scadenza e contrassegnare le attività come completate. Le immagini seguenti mostrano le due pagine principali di questa applicazione: la pagina di creazione delle attività e la pagina principale con l'elenco delle attività create.
Aggiungerai alcune funzionalità che non sono presenti in questa app:
- Autentica gli utenti con email e password
- Aggiungere un listener a una raccolta Firestore e fare in modo che l'interfaccia utente reagisca alle modifiche
- Aggiungere tracce personalizzate per monitorare il rendimento di un codice specifico nell'app
- Crea un pulsante di attivazione/disattivazione di una funzionalità con Remote Config e utilizza l'implementazione graduale per avviarla
Cosa imparerai a fare
- Come utilizzare Firebase Authentication, Performance Monitoring, Remote Config e Cloud Firestore in un'applicazione Android moderna
- Come adattare le API Firebase a un'architettura MVVM
- Come rispecchiare le modifiche apportate con le API Firebase in una UI di Compose
Che cosa ti serve
- Android Studio: Flamingo e versioni successive
- Emulatore Android con API 21 o versioni successive
- Familiarità con il linguaggio di programmazione Kotlin
2. Scarica l'app di esempio e configura Firebase
Ottenere il codice dell'app di esempio
Clona il repository GitHub dalla riga di comando:
git clone https://github.com/FirebaseExtended/make-it-so-android.git
Creare un progetto Firebase
La prima cosa da fare è accedere alla console di Firebase e creare un progetto Firebase facendo clic sul pulsante "+ Aggiungi progetto", come puoi vedere di seguito:
Segui i passaggi sullo schermo per completare la creazione del progetto.
Aggiungi un'app per Android al tuo progetto Firebase
Nel tuo progetto Firebase puoi registrare app diverse: per Android, iOS, web, Flutter e Unity.
Scegli l'opzione Android, come mostrato di seguito:
Quindi, segui questi passaggi:
- Inserisci
com.example.makeitso
come nome del pacchetto e, facoltativamente, inserisci un nickname. Per questo codelab, non è necessario aggiungere il certificato di firma di debug. - Fai clic su Avanti per registrare la tua app e accedere al file di configurazione di Firebase.
- Fai clic su Scarica google-services.json per scaricare il file di configurazione e salvalo nella directory
make-it-so-android/app
. - Fai clic su Avanti. Poiché gli SDK Firebase sono già inclusi nel file
build.gradle
del progetto di esempio, fai clic su Avanti per passare a Passaggi successivi. - Per completare l'operazione, fai clic su Vai alla console.
Per far funzionare correttamente l'app Make it So, devi eseguire due operazioni nella Console prima di passare al codice: attivare i provider di autenticazione e creare il database Firestore.
Configurare l'autenticazione
Innanzitutto, abilitiamo l'autenticazione in modo che gli utenti possano accedere all'app:
- Dal menu Crea, seleziona Autenticazione e fai clic su Inizia.
- Nella scheda Metodo di accesso, seleziona Email/Password e attiva l'opzione.
- Poi, fai clic su Aggiungi nuovo fornitore e seleziona e attiva Anonimo.
Configura Cloud Firestore
A questo punto, configura Firestore. Utilizzerai Firestore per archiviare le attività di un utente che ha eseguito l'accesso. Ogni utente riceverà il proprio documento all'interno di una raccolta del database.
- Nel riquadro a sinistra della console Firebase, espandi Crea e seleziona Database Firestore.
- Fai clic su Crea database.
- Lascia l'ID database impostato su
(default)
. - Seleziona una posizione per il database, poi fai clic su Avanti.
Per un'app reale, devi scegliere una località vicina agli utenti. - Fai clic su Avvia in modalità di test. Leggi il disclaimer sulle regole di sicurezza.
Nei passaggi successivi di questa sezione, aggiungerai regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo database. - Fai clic su Crea.
Prenditi un momento per creare regole di sicurezza efficaci nel database Firestore.
- Apri la dashboard di Firestore e vai alla scheda Regole.
- Aggiorna le regole di sicurezza in questo modo:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow create: if request.auth != null;
allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
}
}
}
Queste regole sostanzialmente stabiliscono che qualsiasi utente dell'app che ha eseguito l'accesso può creare un documento all'interno di qualsiasi raccolta. Una volta creato, solo l'utente che ha creato il documento potrà visualizzarlo, aggiornarlo o eliminarlo.
Esegui l'applicazione
Ora puoi eseguire l'applicazione. Apri la cartella make-it-so-android/start
in Android Studio ed esegui l'app (l'operazione può essere eseguita utilizzando un emulatore Android o un dispositivo Android reale).
3. Firebase Authentication
Quale funzionalità aggiungerai?
Nello stato attuale dell'app di esempio Rendilo valido, un utente può iniziare a utilizzarla senza dover prima accedere. A questo scopo, utilizza l'autenticazione anonima. Tuttavia, gli account anonimi non consentono agli utenti di accedere ai propri dati su altri dispositivi o nemmeno in sessioni future. Sebbene l'autenticazione anonima sia utile per le operazioni preliminari in modalità tiepida, dovresti sempre offrire agli utenti la possibilità di passare a una forma di accesso diversa. Tenendo presente questo, in questo codelab aggiungerai l'autenticazione tramite email e password all'app Make It So.
È ora di programmare!
Non appena l'utente crea un account, digitando un'email e una password, dovrai richiedere all'API Firebase Authentication le credenziali email, quindi collegarle all'account anonimo. Apri il file AccountServiceImpl.kt
in Android Studio e aggiorna la funzione linkAccount
in modo che sia simile al seguente:
model/service/impl/AccountServiceImpl.kt
override suspend fun linkAccount(email: String, password: String) {
val credential = EmailAuthProvider.getCredential(email, password)
auth.currentUser!!.linkWithCredential(credential).await()
}
Ora apri SignUpViewModel.kt
e chiama la funzione di servizio linkAccount
all'interno del blocco launchCatching
della funzione onSignUpClick
:
screens/sign_up/SignUpViewModel.kt
launchCatching {
accountService.linkAccount(email, password)
openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}
Innanzitutto, tenta di autenticarsi e, se la chiamata va a buon fine, passa alla schermata successiva (SettingsScreen
). Quando esegui queste chiamate all'interno di un blocco launchCatching
, se si verifica un errore nella prima riga, l'eccezione verrà rilevata e gestita e la seconda riga non verrà raggiunta.
Non appena SettingsScreen
viene aperto di nuovo, devi assicurarti che le opzioni Accedi e Crea account non siano più disponibili, perché l'utente è già autenticato. Per farlo, facciamo in modo che SettingsViewModel
ascolti lo stato dell'utente corrente (disponibile in AccountService.kt
) per verificare se l'account è anonimo o meno. A questo scopo, aggiorna uiState
in SettingsViewModel.kt
in modo che abbia il seguente aspetto:
screens/settings/SettingsViewModel.kt
val uiState = accountService.currentUser.map {
SettingsUiState(it.isAnonymous)
}
L'ultima cosa che devi fare è aggiornare uiState
in SettingsScreen.kt
per raccogliere gli stati emessi da SettingsViewModel
:
schermate/impostazioni/schermoImpostazioni.kt
val uiState by viewModel.uiState.collectAsState(
initial = SettingsUiState(false)
)
Ora, ogni volta che l'utente cambia, il SettingsScreen
si ricompone per mostrare le opzioni in base al nuovo stato di autenticazione dell'utente.
È ora di fare il test.
Esegui Realizza e vai alle impostazioni facendo clic sull'icona a forma di ingranaggio nell'angolo in alto a destra dello schermo. Da qui, fai clic sull'opzione per creare un account:
Digita un indirizzo email valido e una password efficace per creare il tuo account. Dovrebbe funzionare e dovresti essere reindirizzato alla pagina delle impostazioni, dove vedrai due nuove opzioni: per uscire ed eliminare l'account. Puoi controllare il nuovo account creato nella dashboard Autenticazione nella console Firebase facendo clic sulla scheda Utenti.
4. Cloud Firestore
Quale funzionalità aggiungerai?
Per Cloud Firestore, aggiungi un ascoltatore alla raccolta Firestore che memorizza i documenti che rappresentano le attività visualizzate in Realizza. Dopo aver aggiunto questo ascoltatore, riceverai tutti gli aggiornamenti apportati a questa raccolta.
È ora di programmare!
Aggiorna il Flow
disponibile in StorageServiceImpl.kt
in questo modo:
model/service/impl/StorageServiceImpl.kt
override val tasks: Flow<List<Task>>
get() =
auth.currentUser.flatMapLatest { user ->
firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
}
Questo codice aggiunge un ascoltatore alla raccolta di attività in base a user.id
. Ogni attività è rappresentata da un documento in una raccolta denominata tasks
e ogni attività ha un campo denominato userId
. Tieni presente che verrà emesso un nuovo Flow
se lo stato di currentUser
cambia (ad esempio uscendo).
Ora devi fare in modo che Flow
in TasksViewModel.kt
corrisponda a quello del servizio:
screens/tasks/TasksViewModel.kt
val tasks = storageService.tasks
L'ultima cosa sarà creare composable function
in TasksScreens.kt
, che rappresenta l'interfaccia utente, conoscere questo flusso e raccoglierlo come stato. Ogni volta che lo stato cambia, la funzione componibile si ricompone automaticamente e mostra all'utente lo stato più recente. Aggiungi questo a TasksScreen composable function
:
schermate/attività/tasksScreen.kt
val tasks = viewModel
.tasks
.collectAsStateWithLifecycle(emptyList())
Una volta che la funzione componibile ha accesso a questi stati, puoi aggiornare LazyColumn
(che è la struttura utilizzata per visualizzare un elenco sullo schermo) in modo che abbia il seguente aspetto:
screens/tasks/TasksScreen.kt
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem( [...] )
}
}
È ora di fare il test.
Per verificare che funzioni, aggiungi una nuova attività utilizzando l'app (facendo clic sul pulsante Aggiungi nell'angolo in basso a destra dello schermo). Una volta completata la creazione dell'attività, questa dovrebbe essere visualizzata nella raccolta Firestore della console Firestore. Se accedi a Make it So su altri dispositivi con lo stesso account, potrai modificare le tue attività da svolgere e osservarne l'aggiornamento in tempo reale su tutti i dispositivi.
5. Performance Monitoring
Quale funzionalità aggiungerai?
Il rendimento è un aspetto molto importante a cui fare attenzione, in quanto è molto probabile che gli utenti rinuncino a utilizzare la tua app se le prestazioni non sono buone e impiegano troppo tempo per completare una semplice attività utilizzandola. Ecco perché a volte è utile raccogliere alcune metriche su un percorso specifico intrapreso da un utente nella tua app. Per aiutarti, Firebase Performance Monitoring offre tracce personalizzate. Segui i passaggi successivi per aggiungere tracce personalizzate e misurare le prestazioni in diverse porzioni di codice in Rendilo così.
È ora di programmare.
Se apri il file Performance.kt
, vedrai una funzione in linea chiamata traccia. Questa funzione chiama l'API Performance Monitoring per creare una traccia personalizzata, passando il nome della traccia come parametro. L'altro parametro che vedi è il blocco di codice che vuoi monitorare. La metrica predefinita raccolta per ogni traccia è il tempo necessario per l'esecuzione completa:
model/service/Performance.kt
inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)
Puoi scegliere le parti del codebase che ritieni importanti misurare e aggiungere tracce personalizzate. Ecco un esempio di aggiunta di una traccia personalizzata alla funzione linkAccount
che hai visto in precedenza (in AccountServiceImpl.kt
) in questo codelab:
model/service/impl/AccountServiceImpl.kt
override suspend fun linkAccount(email: String, password: String): Unit =
trace(LINK_ACCOUNT_TRACE) {
val credential = EmailAuthProvider.getCredential(email, password)
auth.currentUser!!.linkWithCredential(credential).await()
}
Ora tocca a voi! Aggiungi alcune tracce personalizzate all'app Make It So e vai alla sezione successiva per verificare se ha funzionato come previsto.
È il momento di fare una prova.
Dopo aver aggiunto le tracce personalizzate, esegui l'app e assicurati di utilizzare le funzionalità che vuoi misurare alcune volte. Poi, vai alla console Firebase e alla dashboard delle prestazioni. Nella parte inferiore dello schermo sono presenti tre schede: Richieste di rete, Tracce personalizzate e Rendering schermo.
Vai alla scheda Tracce personalizzate e controlla che le tracce che hai aggiunto nel codebase vengano visualizzate e che tu possa vedere quanto tempo richiede solitamente l'esecuzione di queste porzioni di codice.
6. Remote Config
Quale funzionalità aggiungerai?
Esistono numerosi casi d'uso per Remote Config, dalla modifica dell'aspetto dell'app da remoto alla configurazione di comportamenti diversi per segmenti utenti diversi. In questo codelab utilizzerai Remote Config per creare un pulsante di attivazione/disattivazione della funzionalità che mostrerà o nasconderà la nuova funzionalità di modifica dell'attività nell'app Make it So.
È ora di programmare!
La prima cosa da fare è creare la configurazione nella console Firebase. Per farlo, devi accedere alla dashboard di Remote Config e fare clic sul pulsante Aggiungi parametro. Compila i campi in base all'immagine seguente:
Una volta compilati tutti i campi, puoi fare clic sul pulsante Salva e poi su Pubblica. Ora che il parametro è stato creato e reso disponibile per il tuo codice di base, devi aggiungere il codice che recupererà i nuovi valori nella tua app. Apri il file ConfigurationServiceImpl.kt
e aggiorna l'implementazione di queste due funzioni:
model/service/impl/ConfigurationServiceImpl.kt
override suspend fun fetchConfiguration(): Boolean {
return remoteConfig.fetchAndActivate().await()
}
override val isShowTaskEditButtonConfig: Boolean
get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()
La prima funzione recupera i valori dal server e viene chiamata non appena l'app viene avviata, in SplashViewModel.kt
. È il modo migliore per assicurarti che i valori più aggiornati siano disponibili in tutte le schermate fin dall'inizio. Non è un'esperienza utente positiva se modifichi l'interfaccia utente o il comportamento dell'app in un secondo momento, quando l'utente sta facendo qualcosa.
La seconda funzione restituisce il valore booleano pubblicato per il parametro che hai appena creato nella console. Inoltre, dovrai recuperare queste informazioni in TasksViewModel.kt
aggiungendo quanto segue alla funzione loadTaskOptions
:
schermate/attività/TasksViewModel.kt
fun loadTaskOptions() {
val hasEditOption = configurationService.isShowTaskEditButtonConfig
options.value = TaskActionOption.getOptions(hasEditOption)
}
Recuperi il valore nella prima riga e lo utilizzi per caricare le opzioni di menu per gli elementi della task nella seconda riga. Se il valore è false
, significa che il menu non conterrà l'opzione di modifica. Ora che hai l'elenco di opzioni, devi fare in modo che la UI lo visualizzi correttamente. Quando crei un'app con Jetpack Compose, devi cercare il composable function
che dichiara l'aspetto dell'interfaccia utente del TasksScreen
. Apri quindi il file TasksScreen.kt
e aggiorna LazyColum
in modo che indichi le opzioni disponibili in TasksViewModel.kt
:
schermate/attività/tasksScreen.kt
val options by viewModel.options
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem(
options = options,
[...]
)
}
}
TaskItem
è un altro composable function
che dichiara l'aspetto dell'interfaccia utente di una singola attività. Ogni attività ha un menu con opzioni che vengono visualizzate quando l'utente fa clic sull'icona con i tre puntini alla fine.
È ora di fare il test.
Ora puoi eseguire l'app. Verifica che il valore pubblicato utilizzando la Console Firebase corrisponda al comportamento dell'app:
- Se è
false
, dovresti vedere solo due opzioni quando fai clic sull'icona con i tre puntini: - Se è
true
, dovresti vedere tre opzioni quando fai clic sull'icona con i tre puntini.
Prova a modificare il valore un paio di volte nella console e a riavviare l'app. È così facile lanciare nuove funzionalità nella tua app utilizzando Remote Config.
7. Complimenti
Complimenti, hai creato un'app per Android con Firebase e Jetpack Compose.
Hai aggiunto Firebase Authentication, Performance Monitoring, Remote Config e Cloud Firestore a un'app per Android interamente creata con Jetpack Compose per l'interfaccia utente e l'hai adattata all'architettura MVVM consigliata.
Letture aggiuntive
- Creare un'app per Android con Firebase e Compose
- Aggiunta di Firebase Authentication a un'app Jetpack Compose
- Aggiunta di Cloud Firestore a un'app Jetpack Compose
- Aggiunta di Coroutines e Flow a un'app per Android creata con Firebase e Compose
- Aggiunta di Firebase Performance Monitoring a un'app Jetpack Compose
- Aggiunta di Firebase Remote Config a un'app Jetpack Compose