Créez une application Android avec Firebase et Jetpack Compose

1. Introduction

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

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'interface utilisateur de cette application est entièrement construite avec Jetpack Compose , qui est la boîte à outils moderne d'Android pour créer une interface utilisateur native - elle est intuitive et nécessite moins de code que l'écriture de fichiers .xml et leur liaison à des activités, des fragments ou des vues.

La première étape pour comprendre dans quelle mesure Firebase et Jetpack Compose fonctionnent ensemble consiste à comprendre l'architecture Android moderne. Une bonne architecture rend le système facile à comprendre, facile à développer et à entretenir, car elle indique très 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'interface utilisateur et ne doit rien savoir de la logique métier. Et c'est dans ViewModel que la logique métier est appliquée, ce qui nécessite parfois que ViewModel appelle la couche Modèle .

Nous vous recommandons fortement de lire cet article pour comprendre comment Model - View - ViewModel est appliqué à une application Android créée avec Jetpack Compose, car cela rendra la base de code plus facile à comprendre et les étapes suivantes plus faciles à réaliser.

Ce que vous construirez

Make It So est une application simple de liste de tâches qui permet à l'utilisateur d'ajouter et de modifier des tâches, d'ajouter des indicateurs, des priorités et des dates d'échéance, 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.

Faites en sorte que l'écran Ajouter une tâcheFaites-en ainsi Écran d'accueil

Vous ajouterez certaines fonctionnalités qui manquent dans cette application :

  • Authentifier les utilisateurs avec e-mail et mot de passe
  • Ajouter un écouteur à une collection Firestore et faire réagir l'interface utilisateur aux modifications
  • Ajoutez des traces personnalisées pour surveiller les performances d'un code spécifique dans l'application
  • Créez une bascule de fonctionnalité à l'aide de Remote Config et utilisez un déploiement par étapes pour la lancer

Ce que vous apprendrez

  • Comment utiliser l'authentification Firebase, la surveillance des performances, la configuration à distance et Cloud Firestore dans une application Android moderne
  • Comment intégrer les API Firebase dans une architecture MVVM
  • Comment refléter les modifications apportées avec les API Firebase dans une interface utilisateur Compose

Ce dont vous aurez besoin

2. Obtenez l'exemple d'application et configurez Firebase

Obtenez 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

Configurer Firebase

La première chose à faire est d'aller dans la console Firebase et de créer un projet Firebase en cliquant sur le bouton "+ Ajouter un projet", comme vous pouvez le voir ci-dessous :

Console Firebase

Suivez les étapes à l'écran pour terminer la création du projet.

Dans chaque projet Firebase, vous pouvez créer différentes applications : pour Android, iOS, Web, Flutter et Unity. Choisissez l'option Android, comme vous le voyez ici :

Présentation du projet Firebase

Suivez ensuite ces étapes :

  1. Entrez com.example.makeitso comme nom de package et, éventuellement, entrez un surnom. 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 enregistrez-le 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 de l'exemple de projet, cliquez sur Suivant pour passer aux étapes suivantes .
  5. Cliquez sur Continuer vers la console pour terminer.

Pour que l'application Make it So fonctionne correctement, vous devez faire deux choses dans la console avant de passer au code : activer les fournisseurs d'authentification et créer la base de données Firestore. Tout d'abord, activons l'authentification afin que les utilisateurs puissent se connecter à l'application :

  1. Dans le menu Créer , sélectionnez Authentification , puis cliquez sur Commencer .
  2. Dans la carte Méthode de connexion , sélectionnez E-mail/Mot de passe et activez-le.
  3. Ensuite, cliquez sur Ajouter un nouveau fournisseur , puis sélectionnez et activez Anonyme .

Ensuite, configurez Firestore. Vous utiliserez Firestore pour stocker les tâches d'un utilisateur connecté. Chaque utilisateur obtiendra son propre document au sein d'une collection de la base de données.

  1. Dans le menu Créer , sélectionnez Firestore , puis cliquez sur Créer une base de données .
  2. Gardez Démarrer en mode production activé et cliquez sur Suivant .
  3. Lorsque vous y êtes invité, sélectionnez l'emplacement où vos données Cloud Firestore seront stockées. Lorsque vous développez une application de production, vous souhaiterez qu'elle se trouve dans une région proche de la majorité de vos utilisateurs et commune avec d'autres services Firebase, comme Functions. Pour cet atelier de programmation, vous pouvez conserver la région par défaut ou sélectionner la région la plus proche de chez vous.
  4. Cliquez sur Activer pour provisionner votre base de données Firestore.

Prenons un moment pour créer des règles de sécurité robustes pour la base de données Firestore. Ouvrez le tableau de bord Firestore et accédez à l'onglet Règles . Mettez ensuite à jour les règles de sécurité pour qu'elles ressemblent à ceci :

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

Ces règles stipulent essentiellement que tout utilisateur connecté à l'application peut créer lui-même un document au sein de n'importe quelle collection. Ensuite, une fois créé, seul l'utilisateur qui a créé ce document pourra afficher, mettre à jour ou supprimer ce document.

Exécutez 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 (cela peut être fait à l'aide d'un émulateur Android ou d'un véritable appareil Android).

3. Authentification Firebase

Quelle fonctionnalité allez-vous ajouter ?

Dans l’état actuel de l’exemple d’application Make It So , un utilisateur peut commencer à utiliser l’application sans avoir à se connecter au préalable. Il utilise une authentification anonyme pour y parvenir. Cependant, les comptes anonymes ne permettent pas à un utilisateur d'accéder à ses données sur d'autres appareils ou même lors de sessions futures. Bien que l'authentification anonyme soit utile pour une intégration chaleureuse, vous devez toujours offrir aux utilisateurs la possibilité de se convertir à une autre forme de connexion. Dans cette optique, dans cet atelier de programmation, vous ajouterez l'authentification par e-mail et par mot de passe à l'application Make It So.

Il est temps de coder !

Dès que l'utilisateur crée un compte, en saisissant un e-mail et un mot de passe, vous devez demander à l'API d'authentification Firebase un identifiant de messagerie, puis lier 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 :

modèle/service/impl/AccountServiceImpl.kt

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

Ouvrez maintenant 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 essaie d'abord de s'authentifier, et si l'appel réussit, il passe à l'écran suivant (le SettingsScreen ). Lorsque 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 atteinte du tout.

Dès que l' SettingsScreen est à nouveau ouvert, vous devez vous assurer que les options de connexion et de création de compte ont disparu, car l'utilisateur est désormais déjà authentifié. Pour ce faire, faisons en sorte que SettingsViewModel écoute le statut de l'utilisateur actuel (disponible dans AccountService.kt ), pour vérifier si le compte est anonyme ou non. Pour ce faire, mettez à jour le uiState dans SettingsViewModel.kt pour ressembler à ce qui suit :

écrans/paramètres/SettingsViewModel.kt

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

La dernière chose que vous devez faire est de mettre à jour le uiState dans SettingsScreen.kt pour collecter les états émis par le SettingsViewModel :

écrans/paramètres/SettingsScreen.kt

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

Désormais, chaque fois que l'utilisateur change, l' SettingsScreen se recomposera 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 d'engrenage dans le coin supérieur droit de l'écran. À partir de là, cliquez sur l'option Créer un compte :

Écran des paramètres Make it SoFaites-le, alors écran d'inscription

Tapez un email valide et un mot de passe fort pour créer votre compte. Cela devrait fonctionner et vous devriez être redirigé vers la page des paramètres, où vous verrez deux nouvelles options : vous 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 ajouterez un écouteur à la collection Firestore qui stocke les documents qui représentent les tâches affichées dans Make it So . Une fois que vous aurez ajouté cet écouteur, vous recevrez toutes les mises à jour apportées à cette collection.

Il est temps de coder !

Mettez à jour le Flow disponible dans StorageServiceImpl.kt pour qu'il ressemble à ceci :

modèle/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 basée sur user.id . Chaque tâche est représentée par un document dans une collection nommée tasks , et chacune d'entre elles possède un champ nommé userId . Veuillez noter qu'un nouveau Flow sera émis si le statut de l' currentUser change (en se déconnectant, par exemple).

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

écrans/tâches/TasksViewModel.kt

val tasks = storageService.tasks

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

écrans/tâches/TasksScreen.kt

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

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

écrans/tâches/TasksScreen.kt

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

Il est temps de tester !

Afin de tester que cela a fonctionné, ajoutez une nouvelle tâche à l'aide de l'application (en cliquant sur le bouton Ajouter en bas à droite de l'écran). Une fois que vous avez terminé de créer la tâche, 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 mises à jour sur tous les appareils en temps réel.

5. Surveillance des performances

Quelle fonctionnalité allez-vous ajouter ?

Les performances sont une chose très importante à laquelle il faut prêter attention, car les utilisateurs sont très susceptibles d'abandonner l'utilisation de votre application si les performances ne sont pas bonnes et qu'ils prennent trop de temps pour accomplir une tâche simple en l'utilisant. C'est pourquoi il est parfois utile de collecter des mesures sur un parcours spécifique effectué par un utilisateur dans votre application. Et 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érents morceaux de code dans Make it So .

Il est temps de coder !

Si vous ouvrez le fichier Performance.kt , vous verrez une fonction en ligne 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 est le temps nécessaire à son exécution complète :

modèle/service/Performance.kt

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

Vous pouvez choisir les parties de la base de 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 :

modèle/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 c'est ton tour! Ajoutez des traces personnalisées à l'application Make it So et passez à la section suivante pour tester si cela a fonctionné comme prévu.

Il est temps de tester !

Une fois que vous avez fini d'ajouter les traces personnalisées, exécutez l'application et assurez-vous d'utiliser les fonctionnalités que vous souhaitez mesurer plusieurs fois. Dirigez-vous ensuite vers la console Firebase et accédez au tableau de bord Performances . En bas de l'écran, vous trouverez trois onglets : Requêtes réseau , Traces personnalisées et Rendu d'écran .

Accédez à l'onglet Traces personnalisées et vérifiez que les traces que vous avez ajoutées dans la base de code y sont affichées et que vous pouvez voir combien de temps il faut habituellement pour exécuter ces morceaux de code.

6. Configuration à distance

Quelle fonctionnalité allez-vous ajouter ?

Il existe une multitude de cas d'utilisation de Remote Config, allant de la modification à distance de l'apparence de votre application à la configuration de différents comportements pour différents segments d'utilisateurs. Dans cet atelier de programmation, vous allez utiliser Remote Config pour créer une bascule de fonctionnalité qui affichera ou masquera la nouvelle fonctionnalité de tâche de modification dans l'application Make it So.

Il est temps de coder !

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

Boîte de dialogue Créer un paramètre de configuration à distance

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 dans 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 :

modèle/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 garantir que les valeurs les plus récentes seront disponibles sur tous les écrans dès le début. Ce n'est pas une bonne expérience utilisateur si vous modifiez l'interface utilisateur 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. Et vous devrez récupérer ces informations dans TasksViewModel.kt , en ajoutant ce qui suit à la fonction loadTaskOptions :

écrans/tâches/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 pour les éléments de tâche sur la deuxième ligne. Si la valeur est false , cela signifie que le menu ne contiendra pas l'option d'édition. Maintenant que vous avez la liste des options, vous devez faire en sorte que l’interface utilisateur l’affiche correctement. Lorsque vous créez une application avec Jetpack Compose, vous devez rechercher la composable function qui déclare à quoi devrait ressembler l'interface utilisateur de TasksScreen . Ouvrez donc le fichier TasksScreen.kt et mettez à jour le LazyColum pour pointer vers les options disponibles dans TasksViewModel.kt :

écrans/tâches/TasksScreen.kt

val options by viewModel.options

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

TaskItem est une autre composable function qui déclare à quoi devrait ressembler l'interface utilisateur d'une seule tâche. Et chaque tâche dispose d'un menu avec des options qui s'affichent lorsque l'utilisateur clique sur l'icône à trois points à la fin de celle-ci.

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 c'est false , vous ne devriez voir que deux options lorsque vous cliquez sur l'icône à trois points ;
  • Si c'est true , vous devriez voir trois options 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. C'est aussi simple que de lancer de nouvelles fonctionnalités dans votre application à l'aide de Remote Config !

7. Félicitations

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

Vous avez ajouté l'authentification Firebase, la surveillance des performances, la configuration à distance et Cloud Firestore à une application Android entièrement construite avec Jetpack Compose pour l'interface utilisateur, et vous l'avez adaptée à l'architecture MVVM recommandée !

Lectures complémentaires

Documents de référence