Connexion Android avec FirebaseUI

Cet atelier de programmation fait partie du cours "Advanced Android" en langage Kotlin. Vous tirerez pleinement parti de ce cours si vous suivez les ateliers en séquence, mais ce n'est pas obligatoire. Tous les ateliers de programmation du cours sont répertoriés sur la page de destination des ateliers de programmation Android avancés sur Kotlin.

Introduction

La création d'une application Android présente de nombreux avantages par la prise en charge de la connexion de vos utilisateurs. En permettant aux utilisateurs de créer une identité dans votre application, vous leur offrez plus de possibilités d'interagir avec elle.

Les comptes personnalisés permettent aux utilisateurs de personnaliser leur expérience dans l'application, d'interagir avec d'autres utilisateurs et de conserver leurs données et de les transférer s'ils utilisent l'application sur un autre appareil (Web ou téléphone, par exemple).

Dans cet atelier de programmation, vous apprendrez les bases pour assurer la connexion à votre application à l'aide de la bibliothèque FirebaseUI. Entre autres choses, la bibliothèque FirebaseUI permet aux développeurs de créer un flux de connexion facilement et gère les comptes utilisateur à votre place.

Ce que vous devez déjà savoir

  • Principes de base de la création d'une application Android
  • LiveData et ViewModel

Points abordés

  • Ajouter Firebase à votre projet
  • Comment gérer la connexion à votre application Android
  • Vérifier l'état actuel de l'authentification de votre application
  • Déconnecter des utilisateurs

Objectifs de l'atelier

  • Utilisez la console Firebase pour intégrer Firebase à votre application.
  • Mettez en œuvre la fonctionnalité de connexion.
  • Personnalisez l'application pour les utilisateurs connectés.
  • Mettez en œuvre la déconnexion des utilisateurs.

En savoir plus sur LiveData et ViewModel

Pour l'application de cet atelier de programmation, vous devez comprendre LiveData et ViewModel. Lisez les présentations de LiveData et de ViewModel pour obtenir un aperçu de ces concepts.

Vous pouvez également suivre le cours "Developing Android Apps with Kotlin" (Développer des applications Android avec Kotlin) pour en savoir plus sur les sujets Android fondamentaux que vous rencontrerez dans cet atelier de programmation. Il est disponible en tant que cours Udacity et en tant que cours de programmation.

Dans cet atelier de programmation, vous allez créer une application qui affiche des faits Android amusants. En outre, l'application dispose d'un bouton Connexion/Déconnexion. Lorsque l'utilisateur est connecté à l'application, un fait Android affiché inclut un message d'accueil pour l'utilisateur afin d'ajouter une touche de personnalisation.

Téléchargez l'exemple d'application. Vous pouvez:

Télécharger le fichier ZIP

... ou clonez le dépôt GitHub à partir de la ligne de commande à l'aide de la commande suivante, puis accédez à la branche start du dépôt:

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

Important:Comme vous allez intégrer l'application pour utiliser Firebase, l'application de départ nécessite une certaine configuration afin de s'exécuter et de s'exécuter. Vous le ferez à l'étape suivante de l'atelier de programmation.

Étape 1: Créer un projet Firebase

Avant de pouvoir ajouter Firebase à votre application Android, vous devez créer un projet Firebase à associer à votre application Android.

  1. Dans la console Firebase, cliquez sur Ajouter un projet.
  2. Sélectionnez ou saisissez un nom de projet. Vous pouvez donner un nom à votre projet. Choisissez quand même un nom pertinent pour l'application que vous développez.
  3. Cliquez sur Continuer.
  4. Vous pouvez ignorer l'étape de configuration de Google Analytics et choisir l'option Pas maintenant.
  5. Cliquez sur Créer un projet pour terminer la configuration du projet Firebase.

Étape 2: Enregistrez votre application auprès de Firebase

Maintenant que vous disposez d'un projet Firebase, vous pouvez y ajouter votre application Android.

  1. Au centre de la page de présentation du projet Firebase, cliquez sur l'icône Android pour lancer le processus de configuration.
  2. Saisissez l'identifiant de votre application dans le champ Nom du package Android. Vérifiez que vous avez saisi l'ID utilisé par votre application, car vous ne pouvez pas ajouter ni modifier cette valeur une fois que vous avez enregistré votre application dans votre projet Firebase.
  1. Un ID d'application est parfois appelé nom de package.
  2. Recherchez cet ID application dans le fichier Gradle de votre module (au niveau de l'application), généralement app/build.gradle (exemple d'ID: com.yourcompany.yourproject).
  3. Saisissez le certificat de signature de débogage SHA-1. Vous pouvez générer cette clé en saisissant la commande suivante dans le terminal de ligne de commande.
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
  1. Cliquez sur Enregistrer l'application.

Étape 3: Ajoutez le fichier de configuration Firebase à votre projet

Ajoutez le fichier de configuration Firebase pour Android à votre application:

  1. Cliquez sur Télécharger google-services.json pour obtenir votre fichier de configuration Firebase pour Android (google-services.json).
  • Vous pouvez télécharger de nouveau votre fichier de configuration Android pour Firebase à tout moment.
  • Assurez-vous que le fichier de configuration n'est pas ajouté avec des caractères supplémentaires et qu'il ne doit être nommé que google-services.json.
  1. Déplacez votre fichier de configuration dans le répertoire des modules (au niveau de l'application) de votre application.

Étape 4: Configurez votre projet Android pour activer les produits Firebase

  1. Pour activer les produits Firebase dans votre application, ajoutez le plug-in google-services à vos fichiers Gradle.
  1. Dans votre fichier Gradle au niveau du projet (build.gradle), ajoutez des règles pour inclure le plug-in Google Services. Vérifiez que vous disposez également du dépôt Maven de 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. Dans le fichier Gradle de votre module (au niveau de l'application), généralement app/build.gradle, ajoutez une ligne au bas du fichier.

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

Étape 4: Ajoutez la dépendance Firebase

Dans cet atelier de programmation, le principal objectif d'intégration de Firebase est de pouvoir créer et gérer des utilisateurs. Pour cela, vous devez ajouter une bibliothèque Firebase qui vous permet de implémenter la connexion.

  1. Ajoutez la dépendance suivante à votre fichier build.gradle (Module:app) pour pouvoir utiliser le SDK dans votre application. Le SDK firebase-auth permet de gérer les utilisateurs authentifiés de votre application.

app/build.gradle:

implementation 'com.firebaseui:firebase-ui-auth:5.0.0'
  1. Synchronisez votre projet avec les fichiers Gradle pour vous assurer que l'ensemble des dépendances sont disponibles pour votre application. Si ce n'est pas le cas, sélectionnez File > Sync Project with Gradle Files (Fichier &gt, Synchroniser le projet avec les fichiers Gradle) dans Android Studio ou dans la barre d'outils.

Étape 5: Exécuter l'application et inspecter le code

  1. Exécutez l'application sur un émulateur ou un appareil physique pour vous assurer que votre environnement est correctement configuré.

Si le problème est résolu, l'écran d'accueil doit afficher un élément Android amusant et un bouton de connexion en haut à gauche. Appuyer sur le bouton de connexion n'a aucune incidence sur le moment.

De manière générale, il s'agit d'une application d'activité unique avec plusieurs fragments. Le MainFragment contient toutes les interfaces affichées à l'écran. (Vous travaillerez avec LoginFragment et SettingsFragment dans un atelier de programmation de suivi.)

  1. Familiarisez-vous avec le code. À noter:
  • FirebaseUserLiveData est la classe que vous allez implémenter pour observer l'utilisateur Firebase actuel associé à l'application. Vous utiliserez l'instance FirebaseAuth comme point d'entrée pour obtenir ces informations utilisateur ultérieurement.
  • MainFragment est lié à LoginViewModel. LoginViewModel est la classe que vous allez implémenter pour utiliser FirebaseUserLiveData afin de créer une variable authenticationState. À l'aide de cette variable authenticationState, MainFragment peut ensuite observer la valeur pour mettre à jour l'interface utilisateur en conséquence.

Au cours de cette étape, vous allez utiliser la console Firebase pour configurer les méthodes d'authentification que votre application doit accepter. Dans cet atelier de programmation, vous allez permettre aux utilisateurs de se connecter avec une adresse e-mail ou leur compte Google.

  1. Accédez à la console Firebase. Remarque: si vous êtes toujours dans le workflow d'ajout de Firebase, cliquez sur X en haut à gauche pour revenir à la console.
  2. Sélectionnez votre projet, si ce n'est pas déjà fait.
  3. Ouvrez le panneau de navigation de gauche, puis sélectionnez Develop > Authentication (Développer et valider l'authentification).

  1. Sélectionnez l'onglet Sign-in Method (Méthode de connexion) dans la barre de navigation supérieure.

  1. Cliquez sur la ligne E-mail/Mot de passe.
  2. Dans la fenêtre pop-up, cochez l'option Activé, puis cliquez sur Enregistrer.
  3. De même, cliquez sur la ligne Google.
  4. Activez l'option Enabled (Activé), saisissez une adresse e-mail d'assistance associée au projet, puis cliquez sur Save (Enregistrer).

Dans cette tâche, vous allez implémenter la fonctionnalité de connexion pour vos utilisateurs.

  1. Ouvrez MainFragment.kt.
  2. Dans la mise en page MainFragment, notez la valeur de auth_button. Ce paramètre n'est actuellement pas configuré pour gérer les entrées utilisateur.
  3. Dans onViewCreated(),, ajoutez un onClickListener à auth_button pour appeler launchSignInFlow().

MainFragment.kt

binding.authButton.setOnClickListener { launchSignInFlow() }
  1. Recherchez la méthode launchSignInFlow() dans MainFragment.kt. Il contient actuellement un TODO.
  2. Complétez la fonction launchSignInFlow() comme indiqué ci-dessous.

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
   )
}

Les utilisateurs peuvent ainsi s'inscrire et se connecter avec leur adresse e-mail ou leur compte Google. Si l'utilisateur choisit de s'inscrire avec son adresse e-mail, la combinaison adresse e-mail/mot de passe qu'il crée sera unique pour votre appli. Cela signifie qu'il pourra se connecter à votre application avec l'adresse e-mail et le mot de passe associés, mais cela ne signifie pas qu'il pourra également se connecter avec n'importe quelle autre application compatible Firebase avec les mêmes identifiants.

  1. Dans MainFragment.kt, vous pouvez écouter le résultat du processus de connexion en appliquant la méthode onActivityResult(), comme indiqué ci-dessous. Étant donné que vous avez commencé le processus de connexion avec SIGN_IN_REQUEST_CODE, vous pouvez également écouter le résultat du processus de connexion en filtrant sur les cas où SIGN_IN_REQUEST_CODE est renvoyé à onActivityResult(). Commencez par consulter les instructions de journalisation pour savoir si l'utilisateur s'est bien connecté.

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}")
       }
   }
}

Votre application devrait maintenant gérer l'inscription et la connexion des utilisateurs.

  1. Exécutez l'application et vérifiez que le bouton Login affiche l'écran de connexion.
  2. Vous pouvez maintenant vous connecter avec votre adresse e-mail et un mot de passe, ou avec votre compte Google.
  3. Aucune modification ne sera apportée à l'interface utilisateur après votre connexion (vous allez mettre à jour l'interface utilisateur à l'étape suivante), mais si tout fonctionne correctement, le message de journal Successfully signed in user ${your name}! devrait s'afficher une fois le processus d'inscription terminé.
  4. Vous pouvez également accéder à la console Firebase et accéder à Développer > Authentification > utilisateurs pour vérifier que l'application dispose désormais d'un utilisateur enregistré.
  5. Notez que lorsqu'un utilisateur crée un compte pour votre application, il est uniquement associé à votre application, et non à aucune application utilisant Firebase pour la connexion.

Dans cette tâche, vous allez mettre à jour l'interface utilisateur en fonction de l'état d'authentification. Lorsque l'utilisateur est connecté, vous pouvez personnaliser son écran d'accueil en affichant son nom. Vous allez également mettre à jour le bouton Login (Connexion) en le remplaçant Logout (Déconnexion) lorsque l'utilisateur sera connecté.

  1. Ouvrez la classe FirebaseUserLiveData.kt, qui a déjà été créée. La première chose à faire est de permettre aux autres classes de l'application de savoir quand un utilisateur s'est connecté ou déconnecté. Cependant, la classe n'effectue aucune action, car la valeur de l'attribut LiveData n'est pas mise à jour.
  2. Comme vous utilisez la bibliothèque FirebaseAuth, vous pouvez écouter les modifications apportées par l'utilisateur connecté avec le rappel FirebaseUser.AuthStateListener implémenté pour vous dans la bibliothèque FirebaseUI. Ce rappel est déclenché chaque fois qu'un utilisateur se connecte ou se déconnecte de votre application.
  3. Notez que FirebaseUserLiveData.kt définit la variable authStateListener. Vous utiliserez cette variable pour stocker la valeur de LiveData. La variable authStateListener a été créée, ce qui vous permet de commencer à écouter les modifications de l'état d'authentification en fonction de l'état de votre application. Par exemple, si l'utilisateur met l'application en arrière-plan, elle cesse d'écouter les modifications de l'état d'authentification afin d'éviter toute fuite potentielle de mémoire.
  4. Mettez à jour le authStateListener afin que la valeur de votre FirebaseUserLiveData corresponde à l'utilisateur Firebase actuel.

FirebaseUserLiveData.kt

private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
   value = firebaseAuth.currentUser
}
  1. Ouvrez LoginViewModel.kt.
  2. Dans LoginViewModel.kt, créez une variable authenticationState basée sur l'objet FirebaseUserLiveData que vous venez d'implémenter. En créant cette variable authenticationState, d'autres classes peuvent maintenant demander si l'utilisateur est connecté ou non via LoginViewModel.

LoginViewModel.kt.

val authenticationState = FirebaseUserLiveData().map { user ->
   if (user != null) {
       AuthenticationState.AUTHENTICATED
   } else {
       AuthenticationState.UNAUTHENTICATED
   }
}
  1. Ouvrir MainFragment.kt.
  2. Dans MainFragment.kt, observeAuthenticationState() peut utiliser la variable authenticationState que vous venez d'ajouter dans LoginViewModel et modifier l'interface utilisateur en conséquence. Si l'utilisateur est connecté, authButton doit afficher Déconnexion.

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. Si l'utilisateur est connecté, vous pouvez également personnaliser le message de bienvenue qu'il voit à l'aide de la fonction getFactWithPersonalization() fournie dans MainFragment.

MainFragment.kt

binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
  1. Enfin, s'il n'y a pas d'utilisateur connecté (lorsque authenticationState n'est rien d'autre que LoginViewModel.AuthenticationState.AUTHENTICATED), auth_button doit afficher Connexion et lancer l'écran de connexion lorsqu'un utilisateur clique dessus. Le message ne doit pas être personnalisé.

MainFragment.kt

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

Une fois toutes les étapes effectuées, votre méthode finale observeAuthenticationState() devrait ressembler à l'exemple de code ci-dessous.

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. Exécutez votre application. L'interface utilisateur doit se mettre à jour selon que l'utilisateur est connecté ou non. Si tout fonctionne correctement et que vous êtes connecté, l'écran d'accueil devrait maintenant vous accueillir à côté de votre nom, en plus d'un élément Android. Le bouton Login (Connexion) doit désormais afficher Logout (Déconnexion).

Dans cette tâche, vous allez implémenter la fonctionnalité de déconnexion.

Étant donné que l'application permet aux utilisateurs de se connecter, elle devrait également leur donner la possibilité de se déconnecter. Voici un exemple de déconnexion d'un utilisateur à l'aide d'une seule ligne de code:

AuthUI.getInstance().signOut(requireContext())
  1. Ouvrez MainFragment.kt.
  2. Dans MainFragment.kt&observeAuthenticationState(), ajoutez la logique de déconnexion afin que auth_button fonctionne correctement lorsqu'un utilisateur connecté est connecté. Le résultat final de la méthode ressemble au code ci-dessous.

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. Exécutez l'application.
  2. Appuyez sur le bouton Déconnexion et vérifiez que l'utilisateur est déconnecté, et que l'état du bouton devient Connexion.

Vous trouverez la version finale de l'application terminée sur https://github.com/googlecodelabs/android-kotlin-login.

Dans cet atelier de programmation, vous avez appris ce qui suit :

  • Comment ajouter Firebase à votre projet en ajoutant les dépendances nécessaires à votre fichier Gradle et en configurant le projet dans la console Firebase
  • Mettre en œuvre la connexion pour votre application à l'aide de la bibliothèque FirebaseUI et préciser comment vous souhaitez autoriser vos utilisateurs à se connecter. Notez que les comptes créés par un utilisateur dans votre application sont spécifiques à cette dernière et ne sont pas partagés avec toutes les applications qui utilisent Firebase pour la connexion.
  • Comment observer l'état d'authentification actuel de votre application à l'aide de LiveData.
  • Comment déconnecter des utilisateurs

Cet atelier de programmation a traité les principes de base de la prise en charge de la connexion à une application Android.

Dans cet atelier de programmation, vous avez autorisé les utilisateurs à s'inscrire et à se connecter avec leur adresse e-mail. Toutefois, la bibliothèque FirebaseUI permet aussi d'utiliser d'autres méthodes d'authentification, comme la connexion par numéro de téléphone. Pour en savoir plus sur les fonctionnalités de la bibliothèque FirebaseUI et découvrir comment utiliser ses autres fonctionnalités, consultez les ressources suivantes:

Pour en savoir plus sur les bonnes pratiques de connexion, consultez les ressources suivantes:

Ateliers de programmation:

Documentation pour les développeurs Android:

Vidéos :

Pour obtenir des liens vers d'autres ateliers de programmation dans ce cours, consultez la page de destination "Avancé Android" dans les ateliers de programmation Kotlin.