Créer une application Android avec Firebase et Jetpack Compose

1. Introduction

Dernière mise à jour : 16/11/2022

Créer une application Android avec Firebase et Jetpack Compose

Dans cet atelier de programmation, vous allez créer une application Android appelée Make It So. L'UI de cette application est entièrement conçue avec Jetpack Compose, qui est le kit d'outils moderne d'Android pour créer des UI natives. Il est intuitif et nécessite moins de code que l'écriture de fichiers .xml et leur liaison à des activités, des fragments ou des vues.

Pour comprendre l'efficacité de la combinaison de Firebase et Jetpack Compose, vous devez d'abord comprendre l'architecture Android moderne. Une bonne architecture facilite la compréhension, le développement et la maintenance du système, car elle indique clairement comment les composants sont organisés et communiquent entre eux. Dans le monde Android, l'architecture recommandée s'appelle Model-View-ViewModel. Le modèle représente la couche qui accède aux données dans l'application. La vue est la couche d'UI et ne doit rien savoir de la logique métier. La ViewModel est l'endroit où la logique métier est appliquée, ce qui nécessite parfois que la ViewModel appelle la couche Model.

Nous vous recommandons vivement de lire cet article pour comprendre comment Model-View-ViewModel est appliqué à une application Android créée avec Jetpack Compose. Vous comprendrez ainsi plus facilement le codebase et pourrez effectuer plus facilement les prochaines étapes.

Objectifs de l'atelier

Make It So est une application de liste de tâches simple qui permet à l'utilisateur d'ajouter et de modifier des tâches, d'ajouter des indicateurs, des priorités et des dates limites, et de marquer les tâches comme terminées. Les images ci-dessous montrent les deux pages principales de cette application : la page de création de tâches et la page principale avec la liste des tâches créées.

Écran "Make it So Add Task" Écran d'accueil "Make it So"

Vous allez ajouter des fonctionnalités qui manquent dans cette application :

  • Authentifier les utilisateurs avec une adresse e-mail et un mot de passe
  • Ajouter un écouteur à une collection Firestore et faire réagir l'UI aux modifications
  • Ajouter des traces personnalisées pour surveiller les performances d'un code spécifique dans l'application
  • Créer un bouton bascule de fonctionnalité à l'aide de Remote Config et le lancer à l'aide du déploiement progressif

Points abordés

  • Utiliser Firebase Authentication, Performance Monitoring, Remote Config et Cloud Firestore dans une application Android moderne
  • Adapter les API Firebase à une architecture MVVM
  • Refléter les modifications apportées avec les API Firebase dans une UI Compose

Prérequis

2. Obtenir l'application exemple et configurer Firebase

Obtenir le code de l'exemple d'application

Clonez le dépôt GitHub à partir de la ligne de commande :

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Créer un projet Firebase

  1. Connectez-vous à la console Firebase à l'aide de votre compte Google.
  2. Cliquez sur le bouton pour créer un projet, puis saisissez un nom (par exemple, Compose Firebase codelab).
  3. Cliquez sur Continuer.
  4. Si vous y êtes invité, lisez et acceptez les Conditions d'utilisation de Firebase, puis cliquez sur Continuer.
  5. (Facultatif) Activez l'assistance IA dans la console Firebase (appelée "Gemini dans Firebase").
  6. Pour cet atelier de programmation, vous avez besoin de Google Analytics pour utiliser les options de ciblage avancé avec Remote Config. Par conséquent, laissez l'option Google Analytics activée. Suivez les instructions à l'écran pour configurer Google Analytics.
  7. Cliquez sur Créer un projet, attendez que votre projet soit provisionné, puis cliquez sur Continuer.

Ajouter une application Android à votre projet Firebase

Dans votre projet Firebase, vous pouvez enregistrer différentes applications : pour Android, iOS, le Web, Flutter et Unity.

Sélectionnez l'option Android, comme indiqué ci-dessous :

Présentation du projet Firebase

Ensuite, procédez comme suit :

  1. Saisissez com.example.makeitso comme nom de package et, éventuellement, un pseudo. Pour cet atelier de programmation, vous n'avez pas besoin d'ajouter le certificat de signature de débogage.
  2. Cliquez sur Suivant pour enregistrer votre application et accéder au fichier de configuration Firebase.
  3. Cliquez sur Télécharger google-services.json pour télécharger votre fichier de configuration et l'enregistrer dans le répertoire make-it-so-android/app.
  4. Cliquez sur Suivant. Étant donné que les SDK Firebase sont déjà inclus dans le fichier build.gradle du projet exemple, cliquez sur Suivant pour passer à Étapes suivantes.
  5. Cliquez sur Accéder à la console pour terminer.

Pour que l'application Make it So fonctionne correctement, vous devez effectuer deux opérations dans la console avant de passer au code : activer les fournisseurs d'authentification et créer la base de données Firestore.

Configurer l'authentification

Commençons par activer l'authentification pour que les utilisateurs puissent se connecter à l'application :

  1. Dans le menu Build (Créer), sélectionnez Authentication (Authentification), puis cliquez sur Get Started (Commencer).
  2. Dans la fiche Mode de connexion, sélectionnez Adresse e-mail/Mot de passe, puis activez-le.
  3. Cliquez ensuite sur Ajouter un fournisseur, puis sélectionnez et activez Anonyme.

Configurer Cloud Firestore

Configurez ensuite Firestore. Vous allez utiliser Firestore pour stocker les tâches d'un utilisateur connecté. Chaque utilisateur disposera de son propre document dans une collection de la base de données.

  1. Dans le panneau de gauche de la console Firebase, développez Créer, puis sélectionnez Base de données Firestore.
  2. Cliquez sur Créer une base de données.
  3. Laissez le champ ID de la base de données défini sur (default).
  4. Sélectionnez un emplacement pour votre base de données, puis cliquez sur Suivant.
    Pour une application réelle, choisissez un emplacement proche de vos utilisateurs.
  5. Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
    Dans les prochaines étapes de cette section, vous ajouterez des règles de sécurité pour protéger vos données. Ne distribuez ni n'exposez publiquement une application sans ajouter de règles de sécurité pour votre base de données.
  6. Cliquez sur Créer.

Prenons le temps de créer des règles de sécurité robustes pour la base de données Firestore.

  1. Ouvrez le tableau de bord Firestore et accédez à l'onglet Règles.
  2. Mettez à jour les règles de sécurité pour qu'elles se présentent comme suit :
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;
    }
  }
}

Ces règles indiquent essentiellement que tout utilisateur connecté à l'application peut créer un document pour lui-même dans n'importe quelle collection. Une fois le document créé, seul l'utilisateur qui l'a créé pourra l'afficher, le modifier ou le supprimer.

Exécuter l'application

Vous êtes maintenant prêt à exécuter l'application. Ouvrez le dossier make-it-so-android/start dans Android Studio et exécutez l'application (vous pouvez utiliser un émulateur Android ou un véritable appareil Android).

3. Firebase Authentication

Quelle fonctionnalité allez-vous ajouter ?

Dans l'état actuel de l'application exemple Make It So, un utilisateur peut commencer à utiliser l'application sans avoir à se connecter au préalable. Pour ce faire, il utilise l'authentification anonyme. Toutefois, les comptes anonymes ne permettent pas à un utilisateur d'accéder à ses données sur d'autres appareils ni même lors de futures sessions. Bien que l'authentification anonyme soit utile pour une intégration progressive, vous devez toujours permettre aux utilisateurs de passer à une autre forme de connexion. Dans cet atelier de programmation, vous allez ajouter l'authentification par e-mail et mot de passe à l'application Make It So.

C'est l'heure de coder !

Dès que l'utilisateur crée un compte en saisissant une adresse e-mail et un mot de passe, vous devez demander un identifiant d'adresse e-mail à l'API Firebase Authentication, puis associer le nouvel identifiant au compte anonyme. Ouvrez le fichier AccountServiceImpl.kt dans Android Studio et mettez à jour la fonction linkAccount pour qu'elle ressemble à ce qui suit :

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

Ouvrez SignUpViewModel.kt et appelez la fonction de service linkAccount dans le bloc launchCatching de la fonction onSignUpClick :

screens/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

Il tente d'abord de s'authentifier. Si l'appel réussit, il passe à l'écran suivant (SettingsScreen). Comme vous exécutez ces appels dans un bloc launchCatching, si une erreur se produit sur la première ligne, l'exception sera interceptée et gérée, et la deuxième ligne ne sera pas du tout atteinte.

Dès que SettingsScreen est rouvert, vous devez vous assurer que les options Se connecter et Créer un compte ont disparu, car l'utilisateur est désormais authentifié. Pour ce faire, faisons en sorte que SettingsViewModel écoute l'état de l'utilisateur actuel (disponible dans AccountService.kt) afin de vérifier si le compte est anonyme ou non. Pour ce faire, mettez à jour la uiState dans SettingsViewModel.kt comme suit :

screens/settings/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

Enfin, vous devez mettre à jour uiState dans SettingsScreen.kt pour collecter les états émis par SettingsViewModel :

screens/settings/SettingsScreen.kt

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

Désormais, chaque fois que l'utilisateur change, SettingsScreen se recompose pour afficher les options en fonction du nouvel état d'authentification de l'utilisateur.

Il est temps de tester !

Exécutez Make it So et accédez aux paramètres en cliquant sur l'icône en forme de roue dentée en haut à droite de l'écran. Cliquez ensuite sur l'option de création de compte :

Écran des paramètres de Make it So Écran d'inscription à Make it So

Saisissez une adresse e-mail valide et un mot de passe sécurisé pour créer votre compte. Vous devriez être redirigé vers la page des paramètres, où vous verrez deux nouvelles options : se déconnecter et supprimer votre compte. Vous pouvez vérifier le nouveau compte créé dans le tableau de bord "Authentification" de la console Firebase en cliquant sur l'onglet "Utilisateurs".

4. Cloud Firestore

Quelle fonctionnalité allez-vous ajouter ?

Pour Cloud Firestore, vous allez ajouter un écouteur à la collection Firestore qui stocke les documents représentant les tâches affichées dans Make it So. Une fois cet écouteur ajouté, vous recevrez chaque mise à jour apportée à cette collection.

C'est l'heure de coder !

Modifiez le Flow disponible dans StorageServiceImpl.kt pour qu'il se présente comme suit :

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

Ce code ajoute un écouteur à la collection de tâches en fonction de user.id. Chaque tâche est représentée par un document dans une collection nommée tasks, et chacune d'elles possède un champ nommé userId. Notez qu'un nouvel Flow sera émis si l'état de currentUser change (en se déconnectant, par exemple).

Vous devez maintenant faire en sorte que Flow dans TasksViewModel.kt reflète la même chose que dans le service :

screens/tasks/TasksViewModel.kt

val tasks = storageService.tasks

Enfin, la dernière chose à faire sera de faire en sorte que le composable function dans TasksScreens.kt, qui représente l'UI, soit conscient de ce flux et le collecte en tant qu'état. Chaque fois que l'état change, la fonction composable se recompose automatiquement et affiche l'état le plus récent à l'utilisateur. Ajoutez ceci à TasksScreen composable function :

screens/tasks/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

Une fois que la fonction composable a accès à ces états, vous pouvez mettre à jour LazyColumn (qui est la structure que vous utilisez pour afficher une liste à l'écran) pour qu'elle ressemble à ceci :

screens/tasks/TasksScreen.kt

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

Il est temps de tester !

Pour vérifier que cela a fonctionné, ajoutez une tâche à l'aide de l'application (en cliquant sur le bouton Ajouter en bas à droite de l'écran). Une fois la tâche créée, elle devrait apparaître dans la collection Firestore de la console Firestore. Si vous vous connectez à Make it So sur d'autres appareils avec le même compte, vous pourrez modifier vos tâches et les voir se mettre à jour en temps réel sur tous les appareils.

5. Performance Monitoring

Quelle fonctionnalité allez-vous ajouter ?

Les performances sont un aspect très important à prendre en compte, car les utilisateurs sont très susceptibles d'abandonner votre application si les performances ne sont pas bonnes et qu'ils mettent trop de temps à effectuer une tâche simple. C'est pourquoi il est parfois utile de collecter des métriques sur un parcours spécifique qu'un utilisateur effectue dans votre application. Pour vous aider, Firebase Performance Monitoring propose des traces personnalisées. Suivez les étapes suivantes pour ajouter des traces personnalisées et mesurer les performances de différentes parties du code dans Make it So.

C'est l'heure de coder !

Si vous ouvrez le fichier Performance.kt, vous verrez une fonction intégrée appelée "trace". Cette fonction appelle l'API Performance Monitoring pour créer une trace personnalisée, en transmettant le nom de la trace en tant que paramètre. L'autre paramètre que vous voyez est le bloc de code que vous souhaitez surveiller. La métrique par défaut collectée pour chaque trace correspond au temps nécessaire à son exécution complète :

model/service/Performance.kt

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

Vous pouvez choisir les parties du code que vous jugez importantes à mesurer et y ajouter des traces personnalisées. Voici un exemple d'ajout d'une trace personnalisée à la fonction linkAccount que vous avez vue précédemment (dans AccountServiceImpl.kt) dans cet atelier de programmation :

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

Maintenant, à vous de jouer ! Ajoutez des traces personnalisées à l'application Make it So, puis passez à la section suivante pour vérifier si cela a fonctionné comme prévu.

Il est temps de tester !

Une fois les traces personnalisées ajoutées, exécutez l'application et veillez à utiliser plusieurs fois les fonctionnalités que vous souhaitez mesurer. Accédez ensuite à la console Firebase et au tableau de bord des performances. En bas de l'écran, vous trouverez trois onglets : Requêtes réseau, Traces personnalisées et Rendu de l'écran.

Accédez à l'onglet Traces personnalisées et vérifiez que les traces que vous avez ajoutées dans la base de code s'affichent et que vous pouvez voir le temps qu'il faut généralement pour exécuter ces éléments de code.

6. Remote Config

Quelle fonctionnalité allez-vous ajouter ?

Remote Config peut être utilisé dans de nombreux cas, par exemple pour modifier l'apparence de votre application à distance ou pour configurer différents comportements pour différents segments d'utilisateurs. Dans cet atelier de programmation, vous allez utiliser Remote Config pour créer un bouton bascule de fonctionnalité qui affichera ou masquera la nouvelle fonctionnalité Modifier la tâche dans l'application Make it So.

C'est l'heure de coder !

La première chose à faire est de créer la configuration dans la console Firebase. Pour ce faire, accédez au tableau de bord Remote Config et cliquez sur le bouton Ajouter un paramètre. Remplissez les champs comme indiqué dans l'image ci-dessous :

Boîte de dialogue &quot;Créer un paramètre&quot; de Remote Config

Une fois tous les champs remplis, vous pouvez cliquer sur le bouton Enregistrer, puis sur Publier. Maintenant que le paramètre est créé et disponible pour votre base de code, vous devez ajouter le code qui récupérera les nouvelles valeurs dans votre application. Ouvrez le fichier ConfigurationServiceImpl.kt et mettez à jour l'implémentation de ces deux fonctions :

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 première fonction récupère les valeurs du serveur et est appelée dès le démarrage de l'application, dans SplashViewModel.kt. C'est le meilleur moyen de s'assurer que les valeurs les plus récentes seront disponibles sur tous les écrans dès le début. Il n'est pas recommandé de modifier l'UI ou le comportement de l'application plus tard, lorsque l'utilisateur est en train de faire quelque chose.

La deuxième fonction renvoie la valeur booléenne publiée pour le paramètre que vous venez de créer dans la console. Vous devrez récupérer ces informations dans TasksViewModel.kt en ajoutant ce qui suit à la fonction loadTaskOptions :

screens/tasks/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

Vous récupérez la valeur sur la première ligne et l'utilisez pour charger les options de menu des éléments de tâche sur la deuxième ligne. Si la valeur est false, cela signifie que le menu ne contient pas l'option de modification. Maintenant que vous disposez de la liste des options, vous devez faire en sorte que l'UI l'affiche correctement. Lorsque vous créez une application avec Jetpack Compose, vous devez rechercher le composable function qui déclare l'apparence de l'UI du TasksScreen. Ouvrez le fichier TasksScreen.kt et mettez à jour LazyColum pour qu'il pointe vers les options disponibles dans TasksViewModel.kt :

screens/tasks/TasksScreen.kt

val options by viewModel.options

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

TaskItem est un autre composable function qui déclare l'apparence de l'UI d'une seule tâche. Chaque tâche comporte un menu d'options qui s'affiche lorsque l'utilisateur clique sur l'icône à trois points à la fin de la tâche.

Il est temps de tester !

Vous êtes maintenant prêt à exécuter l'application. Vérifiez que la valeur que vous avez publiée à l'aide de la console Firebase correspond au comportement de l'application :

  • Si la valeur est false, vous ne devriez voir que deux options lorsque vous cliquez sur l'icône à trois points :
  • Si la version est true, trois options devraient s'afficher lorsque vous cliquez sur l'icône à trois points :

Essayez de modifier la valeur plusieurs fois dans la console et de redémarrer l'application. Vous verrez à quel point il est facile de lancer de nouvelles fonctionnalités dans votre application à l'aide de Remote Config.

7. Félicitations

Félicitations, vous avez créé une application Android avec Firebase et Jetpack Compose !

Vous avez ajouté Firebase Authentication, Performance Monitoring, Remote Config et Cloud Firestore à une application Android entièrement conçue avec Jetpack Compose pour l'UI, et vous l'avez adaptée à l'architecture MVVM recommandée.

Complément d'informations

Documents de référence