Accesso Android con FirebaseUI

Questo codelab fa parte del corso Advanced Android in Kotlin. Per ottenere il massimo valore da questo corso, ti consigliamo di seguire i codelab in sequenza, ma non è obbligatorio. Tutti i codelab del corso sono elencati nella pagina di destinazione dei codelab Advanced Android in Kotlin.

Introduzione

Quando crei un'app per Android, il supporto dell'accesso per i tuoi utenti offre molti vantaggi. Consentendo agli utenti di creare un'identità all'interno della tua app, puoi offrire loro più modi per interagire con l'app.

Con gli account personalizzati, gli utenti possono personalizzare la propria esperienza in-app, interagire con altri utenti e trasferire i propri dati se utilizzano l'app su un altro dispositivo (ad esempio web o un nuovo smartphone).

In questo codelab, imparerai le nozioni di base su come supportare l'accesso per la tua app utilizzando la libreria FirebaseUI. Tra le altre cose, la libreria FirebaseUI semplifica la creazione di un flusso di accesso per gli sviluppatori e gestisce il lavoro di gestione degli account utente.

Cosa devi già sapere

  • Principi di base per la creazione di un'app per Android
  • LiveData e ViewModel

Obiettivi didattici

  • Come aggiungere Firebase al tuo progetto
  • Come supportare l'accesso per la tua app per Android
  • Come osservare lo stato di autenticazione attuale della tua app
  • Come disconnettere gli utenti

In questo lab proverai a:

  • Utilizza la console Firebase per integrare Firebase nella tua app.
  • Implementa la funzionalità di accesso.
  • Aggiungi personalizzazioni nell'app per gli utenti che hanno eseguito l'accesso.
  • Implementa la disconnessione degli utenti.

Scopri di più su LiveData e ViewModel

Per l'app in questo codelab, devi avere una conoscenza di base di LiveData e ViewModel. Leggi le panoramiche di LiveData e ViewModel se vuoi una breve panoramica di questi concetti.

Puoi anche seguire il corso Developing Android Apps with Kotlin per scoprire gli argomenti fondamentali di Android che incontrerai in questo codelab. Questo corso è disponibile sia come corso Udacity che come corso codelab.

In questo codelab, creerai un'app che mostra curiosità divertenti su Android. Ancora più importante, l'app avrà un pulsante Accedi/Esci. Quando l'utente ha eseguito l'accesso all'app, qualsiasi fatto di Android visualizzato includerà un saluto per l'utente come modo per aggiungere un tocco di personalizzazione.

Scarica l'app di esempio:

Scarica zip

... oppure clona il repository GitHub dalla riga di comando utilizzando il seguente comando e passa al branch start del repository:

$  git clone https://github.com/googlecodelabs/android-kotlin-login

Importante:poiché integrerai l'app per utilizzare Firebase, l'app iniziale richiede una configurazione per poter essere creata ed eseguita. Lo farai nel passaggio successivo del codelab.

Passaggio 1: crea un progetto Firebase

Prima di poter aggiungere Firebase alla tua app per Android, devi creare un progetto Firebase a cui connetterti.

  1. Nella console Firebase, fai clic su Aggiungi progetto.
  2. Seleziona o inserisci un nome del progetto. Puoi dare al progetto qualsiasi nome, ma cerca di sceglierne uno pertinente all'app che stai creando.
  3. Fai clic su Continua.
  4. Puoi saltare la configurazione di Google Analytics e scegliere l'opzione Non ora.
  5. Fai clic su Crea progetto per completare la configurazione del progetto Firebase.

Passaggio 2: registra la tua app con Firebase

Ora che hai un progetto Firebase, puoi aggiungervi la tua app per Android.

  1. Al centro della pagina di riepilogo del progetto della console Firebase, fai clic sull'icona Android per avviare il flusso di lavoro di configurazione.
  2. Inserisci l'ID applicazione della tua app nel campo Nome pacchetto Android. Assicurati di inserire l'ID utilizzato dalla tua app, poiché non puoi aggiungere o modificare questo valore dopo aver registrato l'app con il tuo progetto Firebase.
  1. Un ID applicazione a volte viene chiamato nome del pacchetto.
  2. Trova questo ID applicazione nel file Gradle del modulo (a livello di app), di solito app/build.gradle (ID di esempio: com.yourcompany.yourproject).
  3. Inserisci il certificato SHA-1 per la firma di debug. Puoi generare questa chiave inserendo il seguente comando nel terminale della riga di comando.
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
  1. Fai clic su Registra app.

Passaggio 3: aggiungi il file di configurazione Firebase al progetto

Aggiungi il file di configurazione Firebase Android alla tua app:

  1. Fai clic su Scarica google-services.json per ottenere il file di configurazione di Firebase per Android (google-services.json).
  • Puoi scaricare di nuovo il file di configurazione Firebase per Android in qualsiasi momento.
  • Assicurati che al file di configurazione non vengano aggiunti caratteri aggiuntivi e che il nome sia solo google-services.json
  1. Sposta il file di configurazione nella directory del modulo (a livello di app) della tua app.

Passaggio 4: configura il tuo progetto Android per attivare i prodotti Firebase

  1. Per attivare i prodotti Firebase nella tua app, aggiungi il plug-in google-services ai tuoi file Gradle.
  1. Nel file Gradle a livello di directory principale (a livello di progetto) (build.gradle), aggiungi regole per includere il plug-in dei servizi Google. Verifica di avere anche il repository Maven di Google.

build.gradle

buildscript {

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
  }

  dependencies {
    // ...

    // Add the following line:
    classpath 'com.google.gms:google-services:4.3.0'  // Google Services plugin
  }
}

allprojects {
  // ...

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
    // ...
  }
}
  1. Nel file Gradle del modulo (a livello di app, di solito app/build.gradle), aggiungi una riga in fondo al file.

app/build.gradle

apply plugin: 'com.android.application'

android {
  // ...
}

// Add the following line to the bottom of the file:
apply plugin: 'com.google.gms.google-services'  // Google Play services Gradle plugin

Passaggio 4: aggiungi la dipendenza Firebase

In questo codelab il motivo principale per l'integrazione di Firebase è avere un modo per creare e gestire gli utenti. Per farlo, devi aggiungere una libreria Firebase che ti consenta di implementare l'accesso.

  1. Aggiungi la seguente dipendenza nel file build.gradle (Module:app) per poter utilizzare l'SDK nella tua app. L'SDK firebase-auth consente la gestione degli utenti autenticati della tua applicazione.

app/build.gradle:

implementation 'com.firebaseui:firebase-ui-auth:5.0.0'
  1. Sincronizza il progetto con i file Gradle per assicurarti che tutte le dipendenze siano disponibili per la tua app. Se non ti viene richiesto, seleziona File > Sync Project with Gradle Files in Android Studio o dalla barra degli strumenti.

Passaggio 5: esegui l'app e ispeziona il codice

  1. Esegui l'app su un emulatore o un dispositivo fisico per assicurarti che l'ambiente sia configurato correttamente per iniziare lo sviluppo.

Se l'operazione ha esito positivo, nella schermata Home viene visualizzato un aneddoto divertente su Android e un pulsante di accesso nell'angolo in alto a sinistra. Se tocchi il pulsante di accesso, per il momento non succede nulla.

A livello generale, si tratta di un'app con una sola attività e più frammenti. Il MainFragment contiene tutta l'interfaccia utente che vedi nella schermata seguente. Lavoreremo con LoginFragment e SettingsFragment in un codelab successivo.

  1. Acquisisci familiarità con il codice. In particolare, nota:
  • FirebaseUserLiveData è la classe che implementerai per osservare l'utente Firebase corrente associato all'app. Utilizzerai l'istanza FirebaseAuth come punto di accesso per ottenere le informazioni dell'utente in un passaggio successivo.
  • MainFragment è legato a LoginViewModel. LoginViewModel è la classe che implementerai per utilizzare FirebaseUserLiveData per creare una variabile authenticationState. Utilizzando questa variabile authenticationState, MainFragment può quindi osservare il valore per aggiornare l'interfaccia utente di conseguenza.

In questo passaggio utilizzerai la console Firebase per configurare i metodi di autenticazione che vuoi che la tua app supporti. Per questo codelab, ti concentrerai sul consentire agli utenti di accedere con un indirizzo email fornito o con il proprio Account Google.

  1. Vai alla console Firebase. Nota: se ti trovi ancora nel flusso di lavoro Aggiungi Firebase, fai clic sulla X nell'angolo in alto a sinistra per tornare alla console.
  2. Seleziona il progetto, se non lo hai già fatto.
  3. Apri il menu di navigazione a sinistra e seleziona Sviluppa > Autenticazione .

  1. Seleziona la scheda Metodo di accesso nella barra di navigazione in alto.

  1. Fai clic sulla riga Email/Password.
  2. Nel popup, attiva/disattiva l'opzione Attivata e fai clic su Salva.
  3. Allo stesso modo, fai clic sulla riga Google.
  4. Attiva l'opzione Attivata, inserisci un'email di assistenza per il progetto e fai clic su Salva.

In questa attività implementerai la funzionalità di accesso per i tuoi utenti.

  1. Apri MainFragment.kt.
  2. Nel layout di MainFragment, nota auth_button. Al momento non è configurato per gestire l'input dell'utente.
  3. In onViewCreated(), aggiungi un onClickListener a auth_button per chiamare launchSignInFlow().

MainFragment.kt

binding.authButton.setOnClickListener { launchSignInFlow() }
  1. Cerca il metodo launchSignInFlow() in MainFragment.kt. Al momento contiene un TODO.
  2. Completa la funzione launchSignInFlow() come mostrato di seguito.

MainFragment.kt

private fun launchSignInFlow() {
   // Give users the option to sign in / register with their email or Google account.
   // If users choose to register with their email,
   // they will need to create a password as well.
   val providers = arrayListOf(
       AuthUI.IdpConfig.EmailBuilder().build(), AuthUI.IdpConfig.GoogleBuilder().build()

       // This is where you can provide more ways for users to register and 
       // sign in.
   )

   // Create and launch sign-in intent.
   // We listen to the response of this activity with the
   // SIGN_IN_REQUEST_CODE 
   startActivityForResult(
       AuthUI.getInstance()
           .createSignInIntentBuilder()
           .setAvailableProviders(providers)
           .build(),
       MainFragment.SIGN_IN_REQUEST_CODE
   )
}

Ciò consente agli utenti di registrarsi e accedere con il proprio indirizzo email o Account Google. Se l'utente sceglie di registrarsi con il proprio indirizzo email, la combinazione di email e password che crea è univoca per la tua app. Ciò significa che potrà accedere alla tua app con la combinazione di indirizzo email e password, ma non potrà accedere a qualsiasi altra app supportata da Firebase con le stesse credenziali.

  1. In MainFragment.kt, puoi ascoltare il risultato della procedura di accesso implementando il metodo onActivityResult(), come mostrato di seguito. Poiché hai avviato la procedura di accesso con SIGN_IN_REQUEST_CODE, puoi anche ascoltare il risultato della procedura di accesso filtrando i risultati in base al momento in cui SIGN_IN_REQUEST_CODE viene restituito a onActivityResult(). Inizia con alcune istruzioni di log per sapere se l'utente ha eseguito l'accesso correttamente.

MainFragment.kt

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
   super.onActivityResult(requestCode, resultCode, data)
   if (requestCode == SIGN_IN_REQUEST_CODE) {
       val response = IdpResponse.fromResultIntent(data)
       if (resultCode == Activity.RESULT_OK) {
           // User successfully signed in
           Log.i(TAG, "Successfully signed in user ${FirebaseAuth.getInstance().currentUser?.displayName}!")
       } else {
           // Sign in failed. If response is null the user canceled the
           // sign-in flow using the back button. Otherwise check
           // response.getError().getErrorCode() and handle the error.
           Log.i(TAG, "Sign in unsuccessful ${response?.error?.errorCode}")
       }
   }
}

Ora la tua app dovrebbe essere in grado di gestire la registrazione e l'accesso degli utenti.

  1. Esegui l'app e verifica che toccando il pulsante Accedi venga visualizzata la schermata di accesso.
  2. Ora puoi accedere con il tuo indirizzo email e una password oppure con il tuo Account Google.
  3. Non ci saranno modifiche all'interfaccia utente dopo l'accesso (implementerai l'aggiornamento dell'interfaccia utente nel passaggio successivo), ma se tutto funziona correttamente, dovresti visualizzare il messaggio di log Successfully signed in user ${your name}! dopo aver completato il flusso di registrazione.
  4. Puoi anche accedere alla console Firebase e andare a Sviluppa > Autenticazione > Utenti per verificare che l'app ora abbia un utente registrato.
  5. Tieni presente che quando gli utenti creano un account per la tua app, questo account è collegato specificamente solo alla tua app e non a qualsiasi app che utilizza Firebase per la funzionalità di accesso.

In questa attività implementerai l'aggiornamento della UI in base allo stato di autenticazione. Quando l'utente ha eseguito l'accesso, puoi personalizzare la schermata Home visualizzando il suo nome. Aggiornerai anche il pulsante Accedi in modo che diventi un pulsante Esci quando l'utente ha eseguito l'accesso.

  1. Apri il corso FirebaseUserLiveData.kt, che è già stato creato per te. La prima cosa da fare è fornire un modo per far sapere alle altre classi dell'app quando un utente ha eseguito l'accesso o la disconnessione. Tuttavia, la classe non fa ancora nulla perché il valore di LiveData non viene aggiornato.
  2. Poiché utilizzi la libreria FirebaseAuth, puoi ascoltare le modifiche all'utente che ha eseguito l'accesso con il callback FirebaseUser.AuthStateListener implementato per te nell'ambito della libreria FirebaseUI. Questo callback viene attivato ogni volta che un utente esegue l'accesso o la disconnessione dalla tua app.
  3. Tieni presente che FirebaseUserLiveData.kt definisce la variabile authStateListener. Utilizzerai questa variabile per memorizzare il valore di LiveData. La variabile authStateListener è stata creata per consentirti di avviare e interrompere correttamente l'ascolto delle modifiche nello stato di autenticazione in base allo stato della tua applicazione. Ad esempio, se l'utente mette l'app in background, l'app deve smettere di ascoltare le modifiche dello stato di autenticazione per evitare potenziali perdite di memoria.
  4. Aggiorna authStateListener in modo che il valore di FirebaseUserLiveData corrisponda all'utente Firebase corrente.

FirebaseUserLiveData.kt

private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
   value = firebaseAuth.currentUser
}
  1. Apri LoginViewModel.kt.
  2. In LoginViewModel.kt, crea una variabile authenticationState basata sull'oggetto FirebaseUserLiveData che hai appena implementato. Con la creazione di questa variabile authenticationState, le altre classi possono ora eseguire query per verificare se l'utente ha eseguito l'accesso o meno tramite LoginViewModel.

LoginViewModel.kt

val authenticationState = FirebaseUserLiveData().map { user ->
   if (user != null) {
       AuthenticationState.AUTHENTICATED
   } else {
       AuthenticationState.UNAUTHENTICATED
   }
}
  1. Apri MainFragment.kt.
  2. Nel file observeAuthenticationState() di MainFragment.kt puoi utilizzare la variabile authenticationState che hai appena aggiunto in LoginViewModel e modificare di conseguenza l'interfaccia utente. Se è presente un utente che ha eseguito l'accesso, authButton deve mostrare Disconnessione.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   // TODO implement logging out user in next step
               }

                // TODO 2. If the user is logged in, 
                 // you can customize the welcome message they see by
                 // utilizing the getFactWithPersonalization() function provided

           }
           else -> {
               // TODO 3. Lastly, if there is no logged-in user, 
                // auth_button should display Login and
                //  launch the sign in screen when clicked.
           }
       }
   })
}
  1. Se l'utente ha eseguito l'accesso, puoi anche personalizzare il messaggio di benvenuto che vede utilizzando la funzione getFactWithPersonalization() fornita in MainFragment.

MainFragment.kt

binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
  1. Infine, se non è presente alcun utente connesso (quando authenticationState è diverso da LoginViewModel.AuthenticationState.AUTHENTICATED), auth_button deve visualizzare Accedi e avviare la schermata di accesso quando viene selezionato. Inoltre, non deve essere presente alcuna personalizzazione del messaggio visualizzato.

MainFragment.kt

binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener { launchSignInFlow() }
binding.welcomeText.text = factToDisplay

Una volta completati tutti i passaggi, il metodo observeAuthenticationState() finale dovrebbe essere simile al codice riportato di seguito.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
        // TODO 1. Use the authenticationState variable you just added 
         // in LoginViewModel and change the UI accordingly.
       when (authenticationState) {
            // TODO 2.  If the user is logged in, 
             // you can customize the welcome message they see by
             // utilizing the getFactWithPersonalization() function provided
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   // TODO implement logging out user in next step
               }
           }
           else -> {
                // TODO 3. Lastly, if there is no logged-in user, 
                 // auth_button should display Login and
                 // launch the sign in screen when clicked.
               binding.welcomeText.text = factToDisplay

               binding.authButton.text = getString(R.string.login_button_text)
               binding.authButton.setOnClickListener {
                   launchSignInFlow()
               }
           }
       }
   })
}
  1. Esegui l'app. L'interfaccia utente deve aggiornarsi a seconda che un utente abbia eseguito l'accesso o meno. Se tutto funziona correttamente e hai eseguito l'accesso, la schermata Home dovrebbe ora salutarti con il tuo nome, oltre a mostrare una curiosità su Android. Ora il pulsante Accedi dovrebbe mostrare anche Esci.

In questa attività implementerai la funzionalità di disconnessione.

Poiché l'app consente agli utenti di accedere, deve anche fornire loro un modo per uscire. Ecco un esempio di come disconnettere un utente con una sola riga di codice:

AuthUI.getInstance().signOut(requireContext())
  1. Apri MainFragment.kt.
  2. In MainFragment.kt's observeAuthenticationState(), aggiungi la logica di disconnessione in modo che auth_button funzioni correttamente quando è presente un utente connesso. Il risultato finale del metodo è simile al codice riportato di seguito.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.welcomeText.text = getFactWithPersonalization(factToDisplay)

               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   AuthUI.getInstance().signOut(requireContext())
               }
           }
           else -> {
               binding.welcomeText.text = factToDisplay

               binding.authButton.text = getString(R.string.login_button_text)
               binding.authButton.setOnClickListener {
                   launchSignInFlow()
               }
           }
       }
   })
}
  1. Esegui l'app.
  2. Tocca il pulsante Esci e verifica che l'utente abbia eseguito la disconnessione e che lo stato del pulsante cambi in Accedi.

Puoi trovare la versione finale dell'app completata qui https://github.com/googlecodelabs/android-kotlin-login.

In questo codelab hai imparato:

  • Come aggiungere Firebase al tuo progetto aggiungendo le dipendenze necessarie nel file gradle e configurando il progetto nella console Firebase.
  • Come implementare l'accesso per la tua app utilizzando la libreria FirebaseUI e specificando in che modo vuoi consentire agli utenti di accedere. Tieni presente che qualsiasi account creato da un utente nella tua app è specifico solo per la tua app e non viene condiviso con tutte le app che utilizzano Firebase per la funzionalità di accesso.
  • Come osservare lo stato di autenticazione attuale della tua app utilizzando LiveData.
  • Come disconnettere gli utenti.

Questo codelab ha trattato le nozioni di base su come supportare l'accesso per un'app per Android.

In questo codelab hai consentito agli utenti di registrarsi e accedere con il proprio indirizzo email. Tuttavia, con la libreria FirebaseUI puoi supportare anche altri metodi di autenticazione, ad esempio l'accesso con un numero di telefono. Per saperne di più sulle funzionalità della libreria FirebaseUI e su come utilizzare le altre funzionalità che offre, consulta le seguenti risorse:

Per saperne di più sulle best practice relative all'accesso, consulta queste altre risorse:

Codelab:

Documentazione per sviluppatori Android:

Video:

Per i link ad altri codelab di questo corso, consulta la pagina di destinazione dei codelab Advanced Android in Kotlin.