Crea un'app Android con Firebase e Jetpack Compose

1. Introduzione

Ultimo aggiornamento: 2022-11-16

Creazione di un'app Android con Firebase e Jetpack Compose

In questo codelab creerai un'app Android chiamata Make It So . L'interfaccia utente di questa app è interamente realizzata con Jetpack Compose , il moderno toolkit di Android per la creazione di un'interfaccia utente nativa: è intuitivo e richiede meno codice rispetto alla scrittura di file .xml e al loro collegamento ad attività, frammenti o visualizzazioni.

Il primo passo per capire come funzionano bene Firebase e Jetpack Compose è comprendere la moderna architettura Android. Una buona architettura rende il sistema facile da comprendere, facile da sviluppare e facile da manutenere, poiché rende molto chiaro come i componenti sono organizzati e 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 vista è il livello dell'interfaccia utente e non dovrebbe sapere nulla della logica aziendale. E ViewModel è il luogo in cui viene applicata la logica aziendale, che a volte richiede che ViewModel chiami il livello Modello .

Consigliamo vivamente di leggere questo articolo per comprendere come Model - View - ViewModel viene applicato a un'app Android creata con Jetpack Compose, poiché renderà la base di codice più semplice da comprendere e i passaggi successivi più facili da completare.

Cosa costruirai

Make It So è una semplice applicazione per l'elenco delle cose da fare che consente all'utente di aggiungere e modificare attività, aggiungere contrassegni, priorità e date di scadenza e contrassegnare le attività come completate. Le immagini sottostanti mostrano le due pagine principali di questa applicazione: la pagina di creazione delle attività e la pagina principale con l'elenco delle attività create.

Schermata "Rendilo così" Aggiungi attivitàSchermata iniziale Rendilo così

Aggiungerai alcune funzionalità che mancano in questa app:

  • Autenticare gli utenti con email e password
  • Aggiungi un ascoltatore a una raccolta Firestore e fai in modo che l'interfaccia utente reagisca alle modifiche
  • Aggiungi tracce personalizzate per monitorare le prestazioni di codice specifico nell'app
  • Crea un'attivazione/disattivazione della funzionalità utilizzando Remote Config e utilizza l'implementazione graduale per avviarla

Cosa imparerai

  • Come utilizzare l'autenticazione Firebase, il monitoraggio delle prestazioni, la configurazione remota e Cloud Firestore in una moderna applicazione Android
  • Come adattare le API Firebase a un'architettura MVVM
  • Come riflettere le modifiche apportate con le API Firebase in un'interfaccia utente di Compose

Di cosa avrai bisogno

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

Configura Firebase

La prima cosa che devi fare è andare sulla console Firebase e creare un progetto Firebase facendo clic sul pulsante "+ Aggiungi progetto", come puoi vedere di seguito:

Console FireBase

Segui i passaggi sullo schermo per completare la creazione del progetto.

All'interno di ogni progetto Firebase puoi creare diverse app: per Android, iOS, Web, Flutter e Unity. Scegli l'opzione Android, come vedi qui:

Panoramica del progetto Firebase

Quindi segui questi passaggi:

  1. 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.
  2. Fai clic su Avanti per registrare la tua app e accedere al file di configurazione Firebase.
  3. Fai clic su Scarica google-services.json per scaricare il file di configurazione e salvarlo nella directory make-it-so-android/app .
  4. Fare clic su Avanti . Poiché gli SDK Firebase sono già inclusi nel file build.gradle nel progetto di esempio, fai clic su Avanti per passare ai passaggi successivi .
  5. Fare clic su Continua sulla console per terminare.

Per far funzionare correttamente l'app Make it So , ci sono due cose che devi fare nella Console prima di passare al codice: abilitare i provider di autenticazione e creare il database Firestore. Innanzitutto, abilitiamo l'autenticazione in modo che gli utenti possano accedere all'app:

  1. Dal menu Compila , seleziona Autenticazione , quindi fai clic su Inizia .
  2. Nella scheda Metodo di accesso , seleziona E-mail/Password e abilitala.
  3. Successivamente, fai clic su Aggiungi nuovo provider e seleziona e attiva Anonimo .

Successivamente, configura Firestore. Utilizzerai Firestore per archiviare le attività di un utente che ha effettuato l'accesso. Ogni utente riceverà il proprio documento all'interno di una raccolta del database.

  1. Dal menu Crea , seleziona Firestore , quindi fai clic su Crea database .
  2. Mantenere abilitato l'avvio in modalità produzione e fare clic su Avanti .
  3. Quando richiesto, seleziona la posizione in cui verranno archiviati i dati Cloud Firestore. Quando sviluppi un'app di produzione, ti consigliamo di trovarla in una regione vicina alla maggior parte dei tuoi utenti e in comune con altri servizi Firebase, come Funzioni. Per questo codelab, puoi mantenere la regione predefinita o selezionare la regione più vicina a te.
  4. Fai clic su Abilita per eseguire il provisioning del database Firestore.

Prendiamoci un momento per creare solide regole di sicurezza nel database Firestore. Apri la dashboard di Firestore e vai alla scheda Regole . Quindi 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 dicono che qualsiasi utente che ha effettuato l'accesso all'app può creare un documento per se stesso all'interno di qualsiasi raccolta. Quindi, una volta creato, solo l'utente che ha creato il documento potrà visualizzarlo, aggiornarlo o eliminarlo.

Eseguire l'applicazione

Ora sei pronto per eseguire l'applicazione! Apri la cartella make-it-so-android/start in Android Studio ed esegui l'app (può essere eseguita utilizzando un emulatore Android o un vero dispositivo Android).

3. Autenticazione Firebase

Quale funzionalità aggiungerai?

Nello stato corrente dell'app di esempio Make It So , un utente può iniziare a usare l'app senza dover prima accedere. Utilizza l'autenticazione anonima per raggiungere questo obiettivo. 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 rapido, dovresti sempre fornire agli utenti la possibilità di passare a una forma di accesso diversa. Tenendo presente questo, in questo codelab aggiungerai l'autenticazione tramite posta elettronica e password all'app Make It So.

È ora di programmare!

Non appena l'utente crea un account, digitando un'e-mail e una password, è necessario richiedere all'API di autenticazione Firebase una credenziale e-mail, quindi collegare la nuova credenziale all'account anonimo. Apri il file AccountServiceImpl.kt in Android Studio e aggiorna la funzione linkAccount in modo che assomigli al seguente:

modello/servizio/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 del 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 ha esito positivo, passa alla schermata successiva (la SettingsScreen ). Mentre esegui queste chiamate all'interno di un blocco launchCatching , se si verifica un errore sulla prima riga, l'eccezione verrà intercettata e gestita e la seconda riga non verrà raggiunta affatto.

Non appena si apre nuovamente la SettingsScreen , è necessario assicurarsi che le opzioni Accedi e Crea account siano sparite, perché ora l'utente è già autenticato. Per fare ciò, facciamo in modo che il SettingsViewModel ascolti lo stato dell'utente corrente (disponibile in AccountService.kt ), per verificare se l'account è anonimo o meno. Per fare ciò, aggiorna uiState in SettingsViewModel.kt in modo che assomigli al seguente:

schermate/impostazioni/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/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

Ora ogni volta che l'utente cambia, la SettingsScreen si ricomporrà per visualizzare le opzioni in base al nuovo stato di autenticazione dell'utente.

È ora di provare!

Esegui Make it So e accedi alle impostazioni facendo clic sull'icona a forma di ingranaggio nell'angolo in alto a destra dello schermo. Da lì, fai clic sull'opzione Crea account:

Schermata delle impostazioni Rendilo cosìFallo quindi schermata di registrazione

Digita un'e-mail valida e una password complessa per creare il tuo account. Dovrebbe funzionare e dovresti essere reindirizzato alla pagina delle impostazioni, dove vedrai due nuove opzioni: uscire ed eliminare il tuo account. Puoi controllare il nuovo account creato nella dashboard di autenticazione sulla console Firebase facendo clic sulla scheda Utenti.

4. Cloud Fire Store

Quale funzionalità aggiungerai?

Per Cloud Firestore, aggiungerai un ascoltatore alla raccolta Firestore che archivia i documenti che rappresentano le attività visualizzate in Make it So . Una volta aggiunto questo ascoltatore, riceverai ogni aggiornamento apportato a questa raccolta.

È ora di programmare!

Aggiorna il Flow disponibile in StorageServiceImpl.kt in modo che assomigli 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 ascoltatore alla raccolta di attività in base a user.id . Ogni attività è rappresentata da un documento in una raccolta denominata tasks e ognuna di esse ha un campo denominato userId . Tieni presente che verrà emesso un nuovo Flow se lo stato dell'utente currentUser cambia (ad esempio disconnettendosi).

Ora devi fare in modo che il Flow in TasksViewModel.kt rifletta lo stesso del servizio:

schermate/attività/TasksViewModel.kt

val tasks = storageService.tasks

E l'ultima cosa sarà rendere la composable function in TasksScreens.kt , che rappresenta l'interfaccia utente, essere consapevole di questo flusso e raccoglierlo come stato. Ogni volta che lo stato cambia, la funzione componibile si ricomporrà automaticamente e mostrerà all'utente lo stato più recente. Aggiungi questo alla 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 che usi per visualizzare un elenco sullo schermo) in questo modo:

schermate/attività/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

È ora di provare!

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 terminata la creazione dell'attività, questa dovrebbe essere visualizzata nella raccolta Firestore nella console Firestore. Se accedi a Make it So su altri dispositivi con lo stesso account, potrai modificare le tue cose da fare e vederle aggiornate su tutti i dispositivi in ​​tempo reale.

5. Monitoraggio delle prestazioni

Quale funzionalità aggiungerai?

Le prestazioni sono una cosa molto importante a cui prestare attenzione perché è molto probabile che gli utenti rinuncino a utilizzare la tua app se le prestazioni non sono buone e impiegano troppo tempo per completare un'attività semplice utilizzandola. Ecco perché a volte è utile raccogliere alcune metriche su un percorso specifico che un utente compie nella tua app. E per aiutarti in questo, Firebase Performance Monitoring offre tracce personalizzate . Segui i passaggi successivi per aggiungere tracce personalizzate e misurare le prestazioni in diverse parti di 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 desideri monitorare. La metrica predefinita raccolta per ogni traccia è il tempo necessario per l'esecuzione completa:

modello/servizio/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

Puoi scegliere quali parti della base di codice ritieni importanti misurare e aggiungervi 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:

modello/servizio/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 è il tuo turno! Aggiungi alcune tracce personalizzate all'app Make it So e procedi alla sezione successiva per verificare se ha funzionato come previsto.

È ora di provare!

Dopo aver finito di aggiungere le tracce personalizzate, esegui l'app e assicurati di utilizzare le funzionalità che desideri misurare alcune volte. Quindi vai alla console Firebase e vai al dashboard Prestazioni . Nella parte inferiore dello schermo troverai tre schede: Richieste di rete , Tracce personalizzate e Rendering dello schermo .

Vai alla scheda Tracce personalizzate e controlla che le tracce che hai aggiunto nella base di codice vengano visualizzate lì e che tu possa vedere quanto tempo impiega solitamente per eseguire queste parti di codice.

6. Configurazione remota

Quale funzionalità aggiungerai?

Esistono numerosi casi d'uso per Remote Config, dalla modifica dell'aspetto della tua app da remoto alla configurazione di comportamenti diversi per diversi segmenti di utenti. In questo codelab utilizzerai Remote Config per creare un interruttore di funzionalità che mostrerà o nasconderà la nuova funzionalità di attività di modifica nell'app Make it So.

È ora di programmare!

La prima cosa che devi fare è creare la configurazione nella console Firebase. Per fare ciò, è necessario accedere alla dashboard di Remote Config e fare clic sul pulsante Aggiungi parametro . Compila i campi secondo l'immagine qui sotto:

Configurazione remota Crea una finestra di dialogo Parametro

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 la tua 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 garantire che i valori più aggiornati siano disponibili in tutte le schermate fin dall'inizio. Non è una buona esperienza utente modificare l'interfaccia utente o il comportamento dell'app in un secondo momento, mentre l'utente è nel bel mezzo di un'operazione.

La seconda funzione restituisce il valore booleano pubblicato per il parametro appena creato nella Console. E 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)
}

Stai recuperando il valore sulla prima riga e lo stai utilizzando per caricare le opzioni di menu per le voci dell'attività sulla 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 l'interfaccia utente lo visualizzi correttamente. Mentre stai creando un'app con Jetpack Compose, devi cercare la composable function che dichiara come dovrebbe apparire l'interfaccia utente di TasksScreen . Quindi apri il file TasksScreen.kt e aggiorna LazyColum in modo che punti alle 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'altra composable function che dichiara come dovrebbe apparire l'interfaccia utente di una singola attività. E ogni attività ha un menu con opzioni che viene visualizzato quando l'utente fa clic sull'icona a tre punti alla fine.

È ora di provare!

Ora sei pronto per eseguire l'app! Verifica che il valore che hai pubblicato utilizzando la console Firebase corrisponda al comportamento dell'app:

  • Se è false , dovresti vedere solo due opzioni quando fai clic sull'icona con tre punti;
  • Se è true , dovresti vedere tre opzioni quando fai clic sull'icona con tre punti;

Prova a modificare il valore un paio di volte nella Console e a riavviare l'app. È così semplice lanciare nuove funzionalità nella tua app utilizzando Remote Config!

7. Congratulazioni

Congratulazioni, hai creato con successo un'app Android con Firebase e Jetpack Compose!

Hai aggiunto l'autenticazione Firebase, il monitoraggio delle prestazioni, la configurazione remota e Cloud Firestore a un'app Android interamente realizzata con Jetpack Compose per l'interfaccia utente e l'hai adattata all'architettura MVVM consigliata!

Ulteriori letture

Documenti di riferimento