Atelier de programmation Android Cloud Firestore

Buts

Dans cet atelier de programmation, vous allez créer une application de recommandation de restaurants sur Android soutenue par Cloud Firestore. Vous apprendrez à :

  • Lire et écrire des données sur Firestore à partir d'une application Android
  • Écoutez les changements dans les données Firestore en temps réel
  • Utiliser l'authentification Firebase et les règles de sécurité pour sécuriser les données Firestore
  • Écrire des requêtes Firestore complexes

Conditions préalables

Avant de commencer cet atelier de programmation, assurez-vous d'avoir :

  • Android Studio 4.0 ou supérieur
  • Un émulateur Android
  • Version Node.js 10 ou supérieur
  • Java version 8 ou supérieure
  1. Connectez - vous à la console Firebase avec votre compte Google.
  2. Dans la console Firebase , cliquez sur Ajouter un projet.
  3. Comme le montre la capture d'écran ci - dessous, entrez un nom pour votre projet Firebase (par exemple, « Friendly Mange »), puis cliquez sur Continuer.

9d2f625aebcab6af.png

  1. Vous pouvez être invité à activer Google Analytics, pour les besoins de ce laboratoire de programmation, votre sélection n'a pas d'importance.
  2. Après environ une minute, votre projet Firebase sera prêt. Cliquez sur Continuer.

Télécharger le code

Exécutez la commande suivante pour cloner l'exemple de code pour cet atelier de programmation. Cela va créer un dossier appelé friendlyeats-android sur votre machine:

$ git clone https://github.com/firebase/friendlyeats-android

Si vous n'avez pas git sur votre machine, vous pouvez également télécharger le code directement depuis GitHub.

Importer le projet dans Android Studio. Vous verrez probablement des erreurs de compilation ou peut - être un avertissement au sujet d' un manque google-services.json fichier. Nous corrigerons cela dans la section suivante.

Ajouter une configuration Firebase

  1. Dans la console Firebase , sélectionnez Aperçu du projet dans la navigation de gauche. Cliquez sur le bouton Android pour sélectionner la plate - forme. Lorsque vous êtes invité à un usage Nom du package com.google.firebase.example.fireeats

73d151ed16016421.png

  1. Cliquez sur Enregistrer App et suivez les instructions pour télécharger le google-services.json fichier et le déplacer dans l' app/ dossier de l'exemple de code. Cliquez ensuite sur Suivant.

Dans ce codelab vous allez utiliser l' émulateur Firebase Suite à imiter localement nuage Firestore et d' autres services Firebase. Cela fournit un environnement de développement local sûr, rapide et gratuit pour créer votre application.

Installer la CLI Firebase

D' abord , vous devrez installer le Firebase CLI . La meilleure façon de le faire est d'utiliser npm :

npm install -g firebase-tools

Si vous n'avez pas npm ou si vous rencontrez une erreur, lisez les instructions d'installation pour obtenir un binaire autonome pour votre plate - forme.

Une fois que vous avez installé le CLI, en cours d' exécution firebase --version devrait signaler une version 9.0.0 ou plus:

$ firebase --version
9.0.0

Connexion

Exécutez firebase login pour connecter le CLI à votre compte Google. Cela ouvrira une nouvelle fenêtre de navigateur pour terminer le processus de connexion. Assurez-vous de choisir le même compte que vous avez utilisé lors de la création de votre projet Firebase plus tôt.

À partir de l' friendlyeats-android dossier run firebase use --add pour connecter votre projet local à votre projet Firebase. Suivez les instructions pour sélectionner le projet que vous avez créé précédemment et si on lui demande de choisir un alias entrer par default .

Il est maintenant temps d'exécuter la Firebase Emulator Suite et l'application FriendlyEats Android pour la première fois.

Exécuter les émulateurs

Dans le terminal à partir du friendlyeats-android run répertoire firebase emulators:start à démarrer le Firebase émulateurs. Vous devriez voir des journaux comme ceci :

$ firebase emulators:start
i  emulators: Starting emulators: auth, firestore
i  firestore: Firestore Emulator logging to firestore-debug.log
i  ui: Emulator UI logging to ui-debug.log

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ localhost:8080 │ http://localhost:4000/firestore │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

Vous disposez maintenant d'un environnement de développement local complet fonctionnant sur votre machine ! Assurez-vous de laisser cette commande en cours d'exécution pour le reste du labo, votre application Android devra se connecter aux émulateurs.

Connecter l'application aux émulateurs

Ouvrez le fichier FirebaseUtil.java dans Android Studio. Ce fichier contient la logique pour connecter les SDK Firebase aux émulateurs locaux exécutés sur votre ordinateur.

En haut du fichier, examinez cette ligne :

    /** Use emulators only in debug builds **/
    private static final boolean sUseEmulators = BuildConfig.DEBUG;

Nous utilisons BuildConfig pour vous assurer que nous nous connectons seulement aux émulateurs lorsque notre application est en cours d' exécution en debug en mode. Lorsque nous compilons l'application en release en mode cette condition sera faux.

Maintenant , jetez un oeil à la getFirestore() méthode:

    public static FirebaseFirestore getFirestore() {
        if (FIRESTORE == null) {
            FIRESTORE = FirebaseFirestore.getInstance();

            // Connect to the Cloud Firestore emulator when appropriate. The host '10.0.2.2' is a
            // special IP address to let the Android emulator connect to 'localhost'.
            if (sUseEmulators) {
                FIRESTORE.useEmulator("10.0.2.2", 8080);
            }
        }

        return FIRESTORE;
    }

On peut voir qu'il utilise le useEmulator(host, port) méthode pour connecter le SDK Firebase à l'émulateur Firestore local. Tout au long de l'application , nous utiliserons FirebaseUtil.getFirestore() pour accéder à cette instance de FirebaseFirestore donc nous sommes sûrs que nous sommes toujours se connecter à l'émulateur Firestore lors de l' exécution en debug en mode.

Exécutez l'application

Si vous avez ajouté le google-services.json fichier correctement, le projet devrait maintenant compiler. Dans Android studio cliquez sur Créer> Reconstruire le projet et faire en sorte qu'il n'y a pas d' erreurs restantes.

Dans Android Studio Courez l'application sur votre émulateur Android. Au début, un écran "Connexion" vous sera présenté. Vous pouvez utiliser n'importe quel e-mail et mot de passe pour vous connecter à l'application. Ce processus de connexion se connecte à l'émulateur Firebase Authentication, donc aucune information d'identification réelle n'est transmise.

Maintenant , ouvrez l'interface utilisateur émulateurs en accédant à http: // localhost: 4000 dans votre navigateur Web. Cliquez ensuite sur l'onglet Authentification et vous devriez voir le compte que vous venez de créer:

Émulateur d'authentification Firebase

Une fois que vous avez terminé le processus de connexion, vous devriez voir l'écran d'accueil de l'application :

de06424023ffb4b9.png

Bientôt, nous ajouterons des données pour remplir l'écran d'accueil.

Dans cette section, nous écrirons des données dans Firestore afin de pouvoir remplir l'écran d'accueil actuellement vide.

Le principal objet de modèle dans notre application est un restaurant (voir model/Restaurant.java ). Les données Firestore sont divisées en documents, collections et sous-collections. Nous enregistrons chaque restaurant comme un document dans une collection de niveau supérieur appelé "restaurants" . Pour en savoir plus sur le modèle de données Firestore, lisez les documents et les collections dans la documentation .

À des fins de démonstration, nous ajouterons des fonctionnalités dans l'application pour créer dix restaurants aléatoires lorsque nous cliquerons sur le bouton "Ajouter des éléments aléatoires" dans le menu de débordement. Ouvrez le fichier MainActivity.java et remplissez le onAddItemsClicked() méthode:

    private void onAddItemsClicked() {
        // Get a reference to the restaurants collection
        CollectionReference restaurants = mFirestore.collection("restaurants");

        for (int i = 0; i < 10; i++) {
            // Get a random Restaurant POJO
            Restaurant restaurant = RestaurantUtil.getRandom(this);

            // Add a new document to the restaurants collection
            restaurants.add(restaurant);
        }
    }

Il y a quelques points importants à noter sur le code ci-dessus :

  • Nous avons commencé par faire une référence à la "restaurants" collection. Les collections sont créées implicitement lorsque des documents sont ajoutés, il n'était donc pas nécessaire de créer la collection avant d'écrire les données.
  • Les documents peuvent être créés à l'aide de POJO, que nous utilisons pour créer chaque document de restaurant.
  • L' add() méthode ajoute un document à une collection avec un ID généré automatiquement, donc on n'a pas besoin de spécifier un identifiant unique pour chaque restaurant.

Maintenant, exécutez à nouveau l'application et cliquez sur le bouton "Ajouter des éléments aléatoires" dans le menu de débordement pour appeler le code que vous venez d'écrire :

95691e9b71ba55e3.png

Maintenant , ouvrez l'interface utilisateur émulateurs en accédant à http: // localhost: 4000 dans votre navigateur Web. Cliquez ensuite sur l'onglet Firestore et vous devriez voir les données que vous venez d' ajouter:

Émulateur d'authentification Firebase

Ces données sont 100% locales sur votre machine. En fait, votre projet réel ne contient même pas encore de base de données Firestore ! Cela signifie qu'il est sûr d'expérimenter la modification et la suppression de ces données sans conséquence.

Félicitations, vous venez d'écrire des données dans Firestore ! Dans l'étape suivante, nous apprendrons comment afficher ces données dans l'application.

Dans cette étape, nous allons apprendre à récupérer les données de Firestore et à les afficher dans notre application. La première étape pour la lecture de données à partir de Firestore est de créer une Query . Modifier le onCreate() méthode:

        mFirestore = FirebaseUtil.getFirestore();

        // Get the 50 highest rated restaurants
        mQuery = mFirestore.collection("restaurants")
                .orderBy("avgRating", Query.Direction.DESCENDING)
                .limit(LIMIT);

Maintenant, nous voulons écouter la requête, afin que nous obtenions tous les documents correspondants et que nous soyons informés des futures mises à jour en temps réel. Parce que notre objectif final est de lier ces données à un RecyclerView , nous devons créer une RecyclerView.Adapter classe pour écouter les données.

Ouvrez la FirestoreAdapter classe, qui a été partiellement mis en œuvre déjà. Tout d' abord, nous allons faire l'adaptateur mettre en œuvre EventListener et définir la onEvent fonction afin qu'il puisse recevoir des mises à jour une requête Firestore:

public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<VH>
        implements EventListener<QuerySnapshot> { // Add this "implements"

    // ...

    // Add this method
    @Override
    public void onEvent(QuerySnapshot documentSnapshots,
                        FirebaseFirestoreException e) {

        // Handle errors
        if (e != null) {
            Log.w(TAG, "onEvent:error", e);
            return;
        }

        // Dispatch the event
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // Snapshot of the changed document
            DocumentSnapshot snapshot = change.getDocument();

            switch (change.getType()) {
                case ADDED:
                    // TODO: handle document added
                    break;
                case MODIFIED:
                    // TODO: handle document modified
                    break;
                case REMOVED:
                    // TODO: handle document removed
                    break;
            }
        }

        onDataChanged();
    }

  // ...
}

La charge initiale de l'auditeur recevra un ADDED événement pour chaque nouveau document. Au fur et à mesure que l'ensemble de résultats de la requête change au fil du temps, l'écouteur recevra plus d'événements contenant les modifications. Finissons maintenant d'implémenter l'écouteur. Tout d' abord ajouter trois nouvelles méthodes: onDocumentAdded , onDocumentModified , et onDocumentRemoved :

    protected void onDocumentAdded(DocumentChange change) {
        mSnapshots.add(change.getNewIndex(), change.getDocument());
        notifyItemInserted(change.getNewIndex());
    }

    protected void onDocumentModified(DocumentChange change) {
        if (change.getOldIndex() == change.getNewIndex()) {
            // Item changed but remained in same position
            mSnapshots.set(change.getOldIndex(), change.getDocument());
            notifyItemChanged(change.getOldIndex());
        } else {
            // Item changed and changed position
            mSnapshots.remove(change.getOldIndex());
            mSnapshots.add(change.getNewIndex(), change.getDocument());
            notifyItemMoved(change.getOldIndex(), change.getNewIndex());
        }
    }

    protected void onDocumentRemoved(DocumentChange change) {
        mSnapshots.remove(change.getOldIndex());
        notifyItemRemoved(change.getOldIndex());
    }

Ensuite , appelez ces nouvelles méthodes de onEvent :

    @Override
    public void onEvent(QuerySnapshot documentSnapshots,
                        FirebaseFirestoreException e) {

        // ...

        // Dispatch the event
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // Snapshot of the changed document
            DocumentSnapshot snapshot = change.getDocument();

            switch (change.getType()) {
                case ADDED:
                    onDocumentAdded(change); // Add this line
                    break;
                case MODIFIED:
                    onDocumentModified(change); // Add this line
                    break;
                case REMOVED:
                    onDocumentRemoved(change); // Add this line
                    break;
            }
        }

        onDataChanged();
    }

Enfin la mise en œuvre de la startListening() méthode pour fixer l'auditeur:

    public void startListening() {
        if (mQuery != null && mRegistration == null) {
            mRegistration = mQuery.addSnapshotListener(this);
        }
    }

Maintenant, l'application est entièrement configurée pour lire les données de Firestore. Exécutez l'application à nouveau et vous devriez voir les restaurants vous avez ajoutés à l'étape précédente:

9e45f40faefce5d0.png

Revenez maintenant à l'interface utilisateur de l'émulateur dans votre navigateur et modifiez l'un des noms de restaurant. Vous devriez le voir changer dans l'application presque instantanément !

L'application affiche actuellement les restaurants les mieux notés de toute la collection, mais dans une vraie application de restaurant, l'utilisateur souhaiterait trier et filtrer les données. Par exemple, l'application devrait pouvoir afficher « Meilleurs restaurants de fruits de mer à Philadelphie » ou « Pizza la moins chère ».

En cliquant sur la barre blanche en haut de l'application, une boîte de dialogue de filtres s'affiche. Dans cette section, nous utiliserons les requêtes Firestore pour faire fonctionner cette boîte de dialogue :

67898572a35672a5.png

Edit Let le onFilter() méthode de MainActivity.java . Cette méthode accepte un Filters objet qui est un objet d'aide que nous avons créé pour capturer la sortie de la boîte de dialogue de filtres. Nous allons modifier cette méthode pour construire une requête à partir des filtres :

    @Override
    public void onFilter(Filters filters) {
        // Construct query basic query
        Query query = mFirestore.collection("restaurants");

        // Category (equality filter)
        if (filters.hasCategory()) {
            query = query.whereEqualTo("category", filters.getCategory());
        }

        // City (equality filter)
        if (filters.hasCity()) {
            query = query.whereEqualTo("city", filters.getCity());
        }

        // Price (equality filter)
        if (filters.hasPrice()) {
            query = query.whereEqualTo("price", filters.getPrice());
        }

        // Sort by (orderBy with direction)
        if (filters.hasSortBy()) {
            query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
        }

        // Limit items
        query = query.limit(LIMIT);

        // Update the query
        mQuery = query;
        mAdapter.setQuery(query);

        // Set header
        mCurrentSearchView.setText(Html.fromHtml(filters.getSearchDescription(this)));
        mCurrentSortByView.setText(filters.getOrderDescription(this));

        // Save filters
        mViewModel.setFilters(filters);
    }

Dans l'extrait ci - dessus , nous construisons une Query objet en attachant where et orderBy clauses correspondent aux filtres donnés.

Exécutez l'application et sélectionnez le filtre ci - dessous pour afficher les plus populaires restaurants à bas prix:

7a67a8a400c80c50.png

Vous devriez maintenant voir une liste filtrée de restaurants contenant uniquement des options à bas prix :

a670188398c3c59.png

Si vous êtes arrivé jusqu'ici, vous avez maintenant créé une application de visualisation de recommandations de restaurants entièrement fonctionnelle sur Firestore ! Vous pouvez désormais trier et filtrer les restaurants en temps réel. Dans les sections suivantes, nous publions des critiques et la sécurité de l'application.

Dans cette section, nous ajouterons des notes à l'application afin que les utilisateurs puissent évaluer leurs restaurants préférés (ou les moins préférés).

Collections et sous-collections

Jusqu'à présent, nous avons stocké toutes les données des restaurants dans une collection de haut niveau appelée "restaurants". Quand un taux d'utilisation d' un restaurant , nous voulons ajouter une nouvelle Rating objet aux restaurants. Pour cette tâche, nous utiliserons une sous-collection. Vous pouvez considérer une sous-collection comme une collection attachée à un document. Ainsi, chaque document de restaurant aura une sous-collection d'évaluations remplie de documents d'évaluation. Les sous-collections aident à organiser les données sans surcharger nos documents ni nécessiter de requêtes complexes.

Pour accéder à un sous - collection, appel .collection() sur le document parent:

CollectionReference subRef = mFirestore.collection("restaurants")
        .document("abc123")
        .collection("ratings");

Vous pouvez accéder et interroger une sous-collection comme avec une collection de premier niveau, il n'y a pas de limitations de taille ni de changements de performances. Vous pouvez en savoir plus sur le modèle de données Firestore ici .

Ecrire des données dans une transaction

Ajout d' une Rating à la sous - collection appropriée ne nécessite l' appel .add() , mais il faut aussi mettre à jour le Restaurant note moyenne de l' objet et le nombre de notes pour refléter les nouvelles données. Si nous utilisons des opérations distinctes pour effectuer ces deux modifications, il existe un certain nombre de conditions de concurrence qui pourraient entraîner des données périmées ou incorrectes.

Pour nous assurer que les notes sont ajoutées correctement, nous utiliserons une transaction pour ajouter des notes à un restaurant. Cette transaction effectuera quelques actions :

  • Lisez la note actuelle du restaurant et calculez la nouvelle
  • Ajouter la note à la sous-collection
  • Mettre à jour la note moyenne et le nombre de notes du restaurant

Ouvrez RestaurantDetailActivity.java et mettre en œuvre la addRating fonction:

    private Task<Void> addRating(final DocumentReference restaurantRef,
                                 final Rating rating) {
        // Create reference for new rating, for use inside the transaction
        final DocumentReference ratingRef = restaurantRef.collection("ratings")
                .document();

        // In a transaction, add the new rating and update the aggregate totals
        return mFirestore.runTransaction(new Transaction.Function<Void>() {
            @Override
            public Void apply(Transaction transaction)
                    throws FirebaseFirestoreException {

                Restaurant restaurant = transaction.get(restaurantRef)
                        .toObject(Restaurant.class);

                // Compute new number of ratings
                int newNumRatings = restaurant.getNumRatings() + 1;

                // Compute new average rating
                double oldRatingTotal = restaurant.getAvgRating() *
                        restaurant.getNumRatings();
                double newAvgRating = (oldRatingTotal + rating.getRating()) /
                        newNumRatings;

                // Set new restaurant info
                restaurant.setNumRatings(newNumRatings);
                restaurant.setAvgRating(newAvgRating);

                // Commit to Firestore
                transaction.set(restaurantRef, restaurant);
                transaction.set(ratingRef, rating);

                return null;
            }
        });
    }

Le addRating() fonction retourne une Task représentant l'ensemble de la transaction. Dans le onRating() les auditeurs de fonction sont ajoutés à la tâche de répondre au résultat de la transaction.

Exécutez maintenant à nouveau l'application et cliquez sur l' un des restaurants, ce qui devrait faire apparaître l'écran de détail de restaurant. Cliquez sur le bouton + pour commencer à ajouter un commentaire. Ajoutez un avis en sélectionnant un certain nombre d'étoiles et en saisissant du texte.

78fa16cdf8ef435a.png

Frapper Submit donnera le coup de la transaction. Une fois la transaction terminée, vous verrez votre avis affiché ci-dessous et une mise à jour du nombre d'avis du restaurant :

f9e670f40bd615b0.png

Félicitations! Vous disposez maintenant d'une application d'avis sur les restaurants sociale, locale et mobile, construite sur Cloud Firestore. J'ai entendu dire que ceux-ci sont très populaires ces jours-ci.

Jusqu'à présent, nous n'avons pas pris en compte la sécurité de cette application. Comment savons-nous que les utilisateurs ne peuvent lire et écrire que les propres données correctes ? FireStore datbases sont sécurisées par un fichier de configuration appelé Règles de sécurité .

Ouvrez le firestore.rules fichier, vous devriez voir ce qui suit:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

Changement Let ces règles pour éviter que des données indésirables acesss ou des modifications, ouvrez le firestore.rules fichier et remplacer le contenu par le texte suivant:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Determine if the value of the field "key" is the same
    // before and after the request.
    function isUnchanged(key) {
      return (key in resource.data)
        && (key in request.resource.data)
        && (resource.data[key] == request.resource.data[key]);
    }

    // Restaurants
    match /restaurants/{restaurantId} {
      // Any signed-in user can read
      allow read: if request.auth != null;

      // Any signed-in user can create
      // WARNING: this rule is for demo purposes only!
      allow create: if request.auth != null;

      // Updates are allowed if no fields are added and name is unchanged
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && isUnchanged("name");

      // Deletes are not allowed.
      // Note: this is the default, there is no need to explicitly state this.
      allow delete: if false;

      // Ratings
      match /ratings/{ratingId} {
        // Any signed-in user can read
        allow read: if request.auth != null;

        // Any signed-in user can create if their uid matches the document
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;

        // Deletes and updates are not allowed (default)
        allow update, delete: if false;
      }
    }
  }
}

Ces règles restreignent l'accès pour garantir que les clients n'effectuent que des modifications sûres. Par exemple, les mises à jour d'un document de restaurant ne peuvent modifier que les notes, pas le nom ou toute autre donnée immuable. Les évaluations ne peuvent être créées que si l'ID utilisateur correspond à l'utilisateur connecté, ce qui empêche l'usurpation d'identité.

Pour en savoir plus sur les règles de sécurité, consultez la documentation .

Vous avez maintenant créé une application complète au-dessus de Firestore. Vous avez découvert les fonctionnalités les plus importantes de Firestore, notamment :

  • Documents et recueils
  • Lecture et écriture de données
  • Trier et filtrer avec des requêtes
  • Sous-collections
  • Transactions

Apprendre encore plus

Pour continuer à découvrir Firestore, voici quelques bons points de départ :

L'application de restauration de ce laboratoire de programmation était basée sur l'exemple d'application « Friendly Eats ». Vous pouvez parcourir le code source de cette application ici .

Facultatif : Déployer en production

Jusqu'à présent, cette application n'a utilisé que Firebase Emulator Suite. Si vous souhaitez apprendre à déployer cette application dans un véritable projet Firebase, passez à l'étape suivante.

Jusqu'à présent, cette application était entièrement locale, toutes les données sont contenues dans Firebase Emulator Suite. Dans cette section, vous apprendrez à configurer votre projet Firebase pour que cette application fonctionne en production.

Authentification Firebase

Dans le Firebase CONSLE aller à la section Authentification et accédez à l' inscription dans l' onglet Fournisseurs .

Activez la méthode de connexion par e-mail :

334ef7f6ff4da4ce.png

Firestore

Créer une base de données

Accédez à la section Firestore de la console et cliquez sur Créer la base de données:

  1. Lorsque vous êtes invité sur les règles de sécurité choisissent de démarrer en mode verrouillé, nous mettrons à jour ces règles bientôt.
  2. Choisissez l'emplacement de la base de données que vous souhaitez utiliser pour votre application. Notez que la sélection d' un emplacement de base de données est une décision permanente et de le changer , vous devrez créer un nouveau projet. Pour plus d' informations sur le choix d' un emplacement du projet, consultez la documentation .

Déployer des règles

Pour déployer les règles de sécurité que vous avez écrites précédemment, exécutez la commande suivante dans le répertoire codelab :

$ firebase deploy --only firestore:rules

Cela va déployer le contenu de firestore.rules à votre projet, que vous pouvez confirmer en accédant à l'onglet Règles dans la console.

Déployer des index

L'application FriendlyEats propose un tri et un filtrage complexes qui nécessitent un certain nombre d'index composés personnalisés. Ceux - ci peuvent être créés manuellement dans la console Firebase mais il est plus simple d'écrire leurs définitions dans le firestore.indexes.json fichier et les déployer à l' aide de la CLI Firebase.

Si vous ouvrez le firestore.indexes.json fichier , vous verrez que les indices nécessaires ont déjà été fournis:

{
  "indexes": [
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    }
  ],
  "fieldOverrides": []
}

Pour déployer ces index, exécutez la commande suivante :

$ firebase deploy --only firestore:indexes

Notez que la création d'index n'est pas instantanée, vous pouvez surveiller la progression dans la console Firebase.

Configurer l'application

Dans la FirebaseUtil classe nous avons configuré le SDK Firebase pour se connecter au émulateurs en mode débogage:

public class FirebaseUtil {

    /** Use emulators only in debug builds **/
    private static final boolean sUseEmulators = BuildConfig.DEBUG;

    // ...
}

Si vous souhaitez tester votre application avec votre projet Firebase réel, vous pouvez soit :

  1. Créez l'application en mode release et exécutez-la sur un appareil.
  2. Modifier temporairement sUseEmulators à false et exécuter l'application à nouveau.

Notez que vous devez vous déconnecter de l'application et connectez - vous à nouveau afin de se connecter correctement à la production.