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 toolkit moderno di Android per la creazione di UI native. È intuitivo e richiede meno codice rispetto alla scrittura di file .xml e all'associazione ad attività, fragment o visualizzazioni.
Il primo passo per capire come funzionano insieme Firebase e Jetpack Compose è comprendere l'architettura Android moderna. Una buona architettura rende il sistema facile da comprendere, sviluppare e gestire, in quanto chiarisce in modo molto chiaro come sono organizzati i componenti e come comunicano tra loro. Nel mondo Android, l'architettura consigliata si chiama Model - View - ViewModel. Il modello rappresenta il livello che accede ai dati nell'applicazione. La visualizzazione è il livello UI e non deve sapere nulla della logica di business. La ViewModel è il punto in cui viene applicata la logica di business, che a volte richiede alla ViewModel di chiamare il livello Model.
Ti consigliamo vivamente di leggere questo articolo per capire come viene applicato Model - View - ViewModel a un'app per Android creata con Jetpack Compose, in quanto renderà più facile la comprensione del codebase e il completamento dei passaggi successivi.
Cosa creerai
Make It So è una semplice applicazione di elenchi di cose da fare che consente all'utente di aggiungere e modificare attività, aggiungere flag, 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à mancanti in questa app:
- Autenticare gli utenti con email e password
- Aggiungi un listener a una raccolta Firestore e fai in modo che la UI reagisca alle modifiche
- Aggiungere tracce personalizzate per monitorare le prestazioni di un codice specifico nell'app
- Crea un flag di funzionalità utilizzando Remote Config e utilizza l'implementazione graduale per lanciarlo
Cosa imparerai a fare
- Come utilizzare Firebase Authentication, Performance Monitoring, Remote Config e Cloud Firestore in un'applicazione Android moderna
- Come integrare le API Firebase in un'architettura MVVM
- Come riflettere le modifiche apportate con le API Firebase in un'interfaccia utente Compose
Che cosa ti serve
- Android Studio Flamingo+
- Emulatore Android con API 21 o versioni successive
- Familiarità con il linguaggio di programmazione Kotlin
2. Ottieni l'app di esempio e configura Firebase
Ottieni 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
Crea un progetto Firebase
- Accedi alla console Firebase utilizzando il tuo Account Google.
- Fai clic sul pulsante per creare un nuovo progetto, quindi inserisci un nome (ad esempio,
Compose Firebase codelab
). - Fai clic su Continua.
- Se richiesto, leggi e accetta i termini di Firebase, quindi fai clic su Continua.
- (Facoltativo) Attiva l'assistenza AI nella console Firebase (denominata "Gemini in Firebase").
- Per questo codelab, hai bisogno di Google Analytics per utilizzare le opzioni di targeting avanzato con Remote Config, quindi mantieni l'opzione attiva per Google Analytics. Segui le istruzioni sullo schermo per configurare Google Analytics.
- Fai clic su Crea progetto, attendi il provisioning del progetto, poi fai clic su Continua.
Aggiungere un'app per Android al tuo progetto Firebase
Nel tuo progetto Firebase puoi registrare diverse app: per Android, iOS, web, Flutter e Unity.
Scegli l'opzione Android, come mostrato qui:
Poi segui questi passaggi:
- Inserisci
com.example.makeitso
come nome del pacchetto e, facoltativamente, 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 salvarlo nella directory
make-it-so-android/app
. - Fai clic su Avanti. Poiché gli SDK Firebase sono già inclusi nel file
build.gradle
nel progetto di esempio, fai clic su Avanti per passare a Passaggi successivi. - Fai clic su Continua alla console per completare l'operazione.
Per far funzionare correttamente l'app Make it So, devi fare due cose nella console prima di passare al codice: attivare i provider di autenticazione e creare il database Firestore.
Configurare l'autenticazione
Innanzitutto, attiviamo l'autenticazione in modo che gli utenti possano accedere all'app:
- Nel menu Build (Crea), seleziona Authentication (Autenticazione) e poi fai clic su Get Started (Inizia).
- Nella scheda Metodo di accesso, seleziona Email/Password e attivalo.
- A questo punto, fai clic su Aggiungi nuovo fornitore e seleziona e attiva Anonimo.
Configurare Cloud Firestore
Poi, 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 Build 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 posizione vicina ai tuoi utenti. - Fai clic su Avvia in modalità di test. Leggi l'esclusione di responsabilità relativa alle regole di sicurezza.
Nei passaggi successivi di questa sezione, aggiungerai le 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.
Prendiamoci un momento per creare regole di sicurezza efficaci per il database Firestore.
- Apri la dashboard di Firestore e vai alla scheda Regole.
- Aggiorna le regole di sicurezza in modo che siano simili a queste:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /tasks/{document} {
allow create: if request.auth != null;
allow read, update, delete: if request.auth != null
&& resource.data.userId == request.auth.uid
&& request.data.userId == resource.data.userId;
}
}
}
Queste regole stabiliscono che qualsiasi utente che ha eseguito l'accesso all'app può creare un documento per sé 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 (puoi farlo utilizzando un emulatore Android o un dispositivo Android reale).
3. Firebase Authentication
Quale funzionalità aggiungerai?
Nello stato attuale dell'app di esempio Make It So, un utente può iniziare a utilizzare l'app senza dover prima eseguire l'accesso. A questo scopo, utilizza l'autenticazione anonima. Tuttavia, gli account anonimi non consentono a un utente di accedere ai propri dati su altri dispositivi o anche in sessioni future. Sebbene l'autenticazione anonima sia utile per un onboarding iniziale, devi sempre offrire agli utenti la possibilità di passare a un'altra forma di accesso. Tenendo presente questo aspetto, 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 indirizzo email e una password, devi chiedere all'API Firebase Authentication una credenziale email, quindi collegare la nuova credenziale all'account anonimo. Apri il file AccountServiceImpl.kt
in Android Studio e aggiorna la funzione linkAccount
in modo che sia simile alla 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 l'autenticazione e, se la chiamata ha esito positivo, passa alla schermata successiva (SettingsScreen
). Poiché 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 viene riaperto SettingsScreen
, devi assicurarti che le opzioni Accedi e Crea account non siano più presenti, perché ora l'utente è già autenticato. Per farlo, facciamo in modo che SettingsViewModel
ascolti lo stato dell'utente attuale (disponibile in AccountService.kt
) per verificare se l'account è anonimo o meno. Per farlo, aggiorna uiState
in SettingsViewModel.kt
in modo che sia simile a quanto segue:
screens/settings/SettingsViewModel.kt
val uiState = accountService.currentUser.map {
SettingsUiState(it.isAnonymous)
}
L'ultima cosa da fare è aggiornare uiState
in SettingsScreen.kt
per raccogliere gli stati emessi da SettingsViewModel
:
screens/settings/SettingsScreen.kt
val uiState by viewModel.uiState.collectAsState(
initial = SettingsUiState(false)
)
Ora, ogni volta che l'utente cambia, il SettingsScreen
si ricompone per visualizzare le opzioni in base al nuovo stato di autenticazione dell'utente.
È il momento di fare il test.
Esegui Make it So 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 di creazione dell'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: disconnettersi ed eliminare l'account. Puoi controllare il nuovo account creato nella dashboard di Authentication della console Firebase facendo clic sulla scheda Utenti.
4. Cloud Firestore
Quale funzionalità aggiungerai?
Per Cloud Firestore, aggiungerai un listener alla raccolta Firestore che archivia i documenti che rappresentano le attività visualizzate in Make it So. Una volta aggiunto questo listener, riceverai ogni aggiornamento apportato a questa raccolta.
È ora di programmare.
Aggiorna il Flow
disponibile in StorageServiceImpl.kt
in modo che sia simile a questo:
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 listener alla raccolta di attività in base a user.id
. Ogni attività è rappresentata da un documento in una raccolta denominata tasks
e ognuna ha un campo denominato userId
. Tieni presente che verrà emesso un nuovo Flow
se lo stato di currentUser
cambia (ad esempio, se esci).
Ora devi fare in modo che Flow
in TasksViewModel.kt
rifletta lo stesso valore del servizio:
screens/tasks/TasksViewModel.kt
val tasks = storageService.tasks
L'ultima cosa da fare sarà rendere composable function
in TasksScreens.kt
, che rappresenta la UI, consapevole di 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 codice a TasksScreen composable function
:
screens/tasks/TasksScreen.kt
val tasks = viewModel
.tasks
.collectAsStateWithLifecycle(emptyList())
Una volta che la funzione componibile ha accesso a questi stati, puoi aggiornare LazyColumn
(la struttura che utilizzi per visualizzare un elenco sullo schermo) in questo modo:
screens/tasks/TasksScreen.kt
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem( [...] )
}
}
È il momento di fare il test.
Per verificare che l'operazione sia andata a buon fine, aggiungi una nuova attività utilizzando l'app (facendo clic sul pulsante Aggiungi nell'angolo in basso a destra dello schermo). Una volta terminata la creazione dell'attività, questa dovrebbe essere visualizzata nella raccolta Firestore nella console Firestore. Se accedi a Fai in modo che accada su altri dispositivi con lo stesso account, potrai modificare le tue attività e vederle aggiornate su tutti i dispositivi in tempo reale.
5. Performance Monitoring
Quale funzionalità aggiungerai?
Le prestazioni sono un aspetto molto importante a cui prestare attenzione, perché è molto probabile che gli utenti smettano di utilizzare la tua app se le prestazioni non sono buone e impiegano troppo tempo per completare un'attività semplice. Ecco perché a volte è utile raccogliere alcune metriche su un percorso specifico che un utente compie nella tua app. Per aiutarti in questo, Firebase Performance Monitoring offre tracce personalizzate. Segui i passaggi successivi per aggiungere tracce personalizzate e misurare il rendimento in diverse parti del codice in Make it So.
È ora di programmare.
Se apri il file Performance.kt
, vedrai una funzione inline chiamata trace. 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 da 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 il test.
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 sul rendimento. Nella parte inferiore dello schermo sono presenti tre schede: Richieste di rete, Tracciati personalizzati e Rendering dello schermo.
Vai alla scheda Tracce personalizzate e verifica che le tracce che hai aggiunto nel codebase vengano visualizzate e che tu possa vedere quanto tempo in genere è necessario per eseguire questi frammenti di codice.
6. Remote Config
Quale funzionalità aggiungerai?
Esistono una moltitudine di casi d'uso per Remote Config, dalla modifica remota dell'aspetto dell'app alla configurazione di comportamenti diversi per segmenti utenti diversi. In questo codelab, utilizzerai Remote Config per creare un toggle delle funzionalità che mostrerà o nasconderà la nuova funzionalità Modifica attività nell'app Make it So.
È ora di programmare.
La prima cosa da fare è creare la configurazione nella console Firebase. Per farlo, devi andare alla dashboard Remote Config e fare clic sul pulsante Aggiungi parametro. Compila i campi in base all'immagine riportata di seguito:
Una volta compilati tutti i campi, puoi fare clic sul pulsante Salva e poi su Pubblica. Ora che il parametro è stato creato ed è disponibile per il tuo codebase, 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 assicurarsi che i valori più aggiornati siano disponibili in tutte le schermate fin dall'inizio. Non è una buona esperienza utente se modifichi l'interfaccia utente o il comportamento dell'app in un secondo momento, quando l'utente è nel bel mezzo di un'attività.
La seconda funzione restituisce il valore booleano pubblicato per il parametro appena creato nella console. Dovrai recuperare queste informazioni in TasksViewModel.kt
aggiungendo quanto segue alla funzione loadTaskOptions
:
screens/tasks/TasksViewModel.kt
fun loadTaskOptions() {
val hasEditOption = configurationService.isShowTaskEditButtonConfig
options.value = TaskActionOption.getOptions(hasEditOption)
}
Stai recuperando il valore della prima riga e lo stai utilizzando per caricare le opzioni di menu per le attività nella seconda riga. Se il valore è false
, significa che il menu non conterrà l'opzione di modifica. Ora che hai l'elenco delle opzioni, devi fare in modo che la UI lo visualizzi correttamente. Quando crei un'app con Jetpack Compose, devi cercare composable function
che dichiara l'aspetto della UI di TasksScreen
. Quindi, apri il file TasksScreen.kt
e aggiorna LazyColum
in modo che punti alle opzioni disponibili in TasksViewModel.kt
:
screens/tasks/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 viene visualizzato quando l'utente fa clic sull'icona con tre puntini alla fine.
È il momento 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 tre puntini: - Se è
true
, dovresti vedere tre opzioni quando fai clic sull'icona con 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
Congratulazioni, hai creato correttamente 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 la UI e l'hai adattata all'architettura MVVM consigliata.
Further reading
- Creazione di un'app Android con Firebase e Compose
- Aggiungere Firebase Authentication a un'app Jetpack Compose
- Aggiungere Cloud Firestore a un'app Jetpack Compose
- Aggiunta di coroutine e Flow a un'app Android creata con Firebase e Compose
- Aggiunta di Firebase Performance Monitoring a un'app Jetpack Compose
- Aggiungere Firebase Remote Config a un'app Jetpack Compose