Laboratorium programowania na Androida w Cloud Firestore

Cele

W tym ćwiczeniu z kodowania zbudujesz aplikację polecającą restauracje na Androida wspieraną przez Cloud Firestore. Nauczysz się jak:

  • Odczytuj i zapisuj dane w Firestore z aplikacji na Androida
  • Słuchaj zmian w danych Firestore w czasie rzeczywistym
  • Użyj uwierzytelniania Firebase i reguł bezpieczeństwa, aby zabezpieczyć dane Firestore
  • Pisz złożone zapytania Firestore

Warunki wstępne

Przed rozpoczęciem tego ćwiczenia z programowania upewnij się, że masz:

  • Studio Android 4.0 lub nowszy
  • Emulator Androida
  • Node.js wersja 10 lub nowsza
  • Java w wersji 8 lub wyższej
  1. Zaloguj się do konsoli Firebase ze swojego konta Google.
  2. W konsoli Firebase , kliknij przycisk Dodaj projekt.
  3. Jak pokazano na zrzut ekranu poniżej wpisz nazwę projektu Firebase (na przykład „Przyjazny posiłki”), a następnie kliknij przycisk Kontynuuj.

9d2f625aebcab6af.png

  1. Możesz zostać poproszony o włączenie Google Analytics, dla celów tego ćwiczenia z programowania Twój wybór nie ma znaczenia.
  2. Po około minucie Twój projekt Firebase będzie gotowy. Kliknij Kontynuuj.

Pobierz kod

Uruchom następujące polecenie, aby sklonować przykładowy kod dla tego ćwiczenia z programowania. Spowoduje to utworzenie folderu o nazwie friendlyeats-android na komputerze:

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

Jeśli nie masz git na swoim komputerze, możesz również pobrać kod bezpośrednio z GitHub.

Zaimportować do projektu Android Studio. Prawdopodobnie będzie zobaczyć kilka błędów kompilacji czy może ostrzeżenie o brakującym google-services.json pliku. Poprawimy to w następnej sekcji.

Dodaj konfigurację Firebase

  1. W konsoli Firebase wybierz Przegląd projektu w lewym panelu nawigacyjnym. Kliknij przycisk, aby wybrać Android platformy. Gdy pojawi się monit o podanie nazwy pakietu ruchu com.google.firebase.example.fireeats

73d151ed16016421.png

  1. Kliknij Register aplikację i postępować zgodnie z instrukcjami, aby pobrać google-services.json plik, a następnie przenieść go do app/ folderu kodu próbki. Następnie kliknij przycisk Dalej.

W tym codelab będziesz używać Firebase Emulator Suite do lokalnego naśladować Chmura FireStore i innych usług Firebase. Zapewnia to bezpieczne, szybkie i bezpłatne lokalne środowisko programistyczne do tworzenia aplikacji.

Zainstaluj Firebase CLI

Po pierwsze trzeba będzie zainstalować Firebase CLI . Najprostszym sposobem, aby to zrobić jest użycie npm :

npm install -g firebase-tools

Jeśli nie masz npm lub wystąpienia błędu, przeczytaj instrukcję instalacji , aby uzyskać samodzielny plik binarny dla danej platformy.

Po zainstalowaniu CLI, bieganie firebase --version powinien zgłosić wersji 9.0.0 lub wyższej:

$ firebase --version
9.0.0

Zaloguj sie

Uruchom firebase login do podłączenia CLI do swojego konta Google. Spowoduje to otwarcie nowego okna przeglądarki, aby zakończyć proces logowania. Pamiętaj, aby wybrać to samo konto, którego użyłeś wcześniej podczas tworzenia projektu Firebase.

Od obrębie friendlyeats-android folderu run firebase use --add połączyć się z lokalnym projektu do projektu Firebase. Postępuj zgodnie z instrukcjami, aby wybrać utworzony wcześniej projekt i jeśli poproszony o wybranie aliasu wprowadzić default .

Teraz nadszedł czas, aby po raz pierwszy uruchomić Firebase Emulator Suite i aplikację FriendlyEats na Androida.

Uruchom emulatory

W terminalu od wewnątrz friendlyeats-android metę katalogu firebase emulators:start , aby uruchomić Firebase emulatory. Powinieneś zobaczyć logi w ten sposób:

$ 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.

Masz teraz pełne lokalne środowisko programistyczne działające na Twoim komputerze! Pamiętaj, aby pozostawić to polecenie uruchomione przez resztę ćwiczenia z kodowania, Twoja aplikacja na Androida będzie musiała połączyć się z emulatorami.

Połącz aplikację z emulatorami

Otwórz plik FirebaseUtil.java w Android Studio. Ten plik zawiera logikę łączenia pakietów SDK Firebase z lokalnymi emulatorami działającymi na Twoim komputerze.

U góry pliku sprawdź ten wiersz:

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

Używamy BuildConfig aby upewnić się, że tylko podłączyć do emulatorów gdy nasza aplikacja jest uruchomiona w debug mode. Kiedy skompilować aplikację w release tryb ten warunek będzie fałszywy.

Teraz spójrz na getFirestore() metody:

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

Widzimy, że jest to za pomocą useEmulator(host, port) metody, aby podłączyć Firebase SDK do lokalnego emulatora FireStore. Całej aplikacji użyjemy FirebaseUtil.getFirestore() , aby uzyskać dostęp do tej instancji FirebaseFirestore więc jesteśmy pewni, że mamy zawsze do podłączenia emulatora FireStore podczas pracy w debug mode.

Uruchom aplikację

Jeśli dodał google-services.json plik poprawnie, projekt powinien teraz skompilować. W Android Studio kliknij polecenie Build> Rebuild projektu i upewnić się, że nie istnieją żadne pozostałe błędy.

W Android Studio Uruchom aplikację na Android emulatora. Na początku pojawi się ekran „Zaloguj się”. Aby zalogować się do aplikacji, możesz użyć dowolnego adresu e-mail i hasła. Ten proces logowania łączy się z emulatorem uwierzytelniania Firebase, więc nie są przesyłane żadne prawdziwe dane uwierzytelniające.

Teraz otwórz emulatory UI, przechodząc do http: // localhost: 4000 w swojej przeglądarce internetowej. Następnie kliknij na zakładkę Uwierzytelnianie i powinieneś zobaczyć po prostu założeniu konta:

Emulator uwierzytelniania Firebase

Po zakończeniu procesu logowania powinieneś zobaczyć ekran główny aplikacji:

de06424023ffb4b9.png

Wkrótce dodamy trochę danych, aby wypełnić ekran główny.

W tej sekcji napiszemy trochę danych do Firestore, aby wypełnić pusty ekran główny.

Głównym model obiektowy w naszej aplikacji znajduje się restauracja (patrz model/Restaurant.java ). Dane Firestore są podzielone na dokumenty, kolekcje i podkolekcje. Będziemy przechowywać każdej restauracji jako dokumentu w kolekcji najwyższego poziomu o nazwie "restaurants" . Aby dowiedzieć się więcej na temat modelu danych FireStore przeczytasz dokumentów i zbiorów w dokumentacji .

W celach demonstracyjnych dodamy funkcjonalność w aplikacji, aby utworzyć dziesięć losowych restauracji, gdy klikniemy przycisk „Dodaj losowe przedmioty” w rozszerzonym menu. Otwórz plik MainActivity.java i wypełnij onAddItemsClicked() metody:

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

W powyższym kodzie należy zwrócić uwagę na kilka ważnych rzeczy:

  • Zaczęliśmy się odniesienie do "restaurants" kolekcji. Kolekcje są tworzone niejawnie podczas dodawania dokumentów, więc nie było potrzeby tworzenia kolekcji przed zapisaniem danych.
  • Dokumenty można tworzyć za pomocą POJO, których używamy do tworzenia każdego dokumentu Restauracji.
  • add() metoda dodaje dokument do kolekcji z auto generowane ID, więc nie trzeba podać niepowtarzalny identyfikator dla każdej restauracji.

Teraz ponownie uruchom aplikację i kliknij przycisk „Dodaj losowe elementy” w rozszerzonym menu, aby wywołać kod, który właśnie napisałeś:

95691e9b71ba55e3.png

Teraz otwórz emulatory UI, przechodząc do http: // localhost: 4000 w swojej przeglądarce internetowej. Następnie kliknij na zakładkę FireStore i powinieneś zobaczyć dane po prostu dodał:

Emulator uwierzytelniania Firebase

Te dane są w 100% lokalne dla Twojego komputera. W rzeczywistości Twój prawdziwy projekt nie zawiera jeszcze bazy danych Firestore! Oznacza to, że można bezpiecznie eksperymentować z modyfikowaniem i usuwaniem tych danych bez konsekwencji.

Gratulacje, właśnie zapisałeś dane do Firestore! W następnym kroku dowiemy się, jak wyświetlać te dane w aplikacji.

W tym kroku dowiemy się, jak pobierać dane z Firestore i wyświetlać je w naszej aplikacji. Pierwszym krokiem do odczytu danych z FireStore jest utworzenie Query . Modyfikowanie onCreate() metodę:

        mFirestore = FirebaseUtil.getFirestore();

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

Teraz chcemy wysłuchać zapytania, aby otrzymać wszystkie pasujące dokumenty i być powiadamiani o przyszłych aktualizacjach w czasie rzeczywistym. Ponieważ nasz ostateczny cel jest powiązać te dane do RecyclerView , musimy stworzyć RecyclerView.Adapter klasę wysłuchać danych.

Otwórz FirestoreAdapter klasę, która została częściowo już realizowane. Najpierw zróbmy adapter wdrożyć EventListener i zdefiniować onEvent funkcję tak, że może otrzymywać aktualizacje na zapytanie 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();
    }

  // ...
}

Na wstępnym obciążeniem słuchacz otrzyma jeden ADDED zdarzenie dla każdego nowego dokumentu. Ponieważ zestaw wyników zapytania zmienia się w czasie, słuchacz otrzyma więcej zdarzeń zawierających zmiany. Zakończmy teraz implementację słuchacza. Pierwszy dodanie trzech nowych metod: onDocumentAdded , onDocumentModified , a na 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());
    }

Następnie nazwać tych nowych metod z 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();
    }

Wreszcie wdrożenie startListening() metodę, aby dołączyć do słuchacza:

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

Teraz aplikacja jest w pełni skonfigurowana do odczytu danych z Firestore. Uruchom aplikację ponownie i powinieneś zobaczyć restauracje dodanych w poprzednim kroku:

9e45f40faefce5d0.png

Teraz wróć do interfejsu użytkownika emulatora w przeglądarce i edytuj jedną z nazw restauracji. Powinieneś zobaczyć, jak zmienia się w aplikacji niemal natychmiast!

Aplikacja wyświetla obecnie najwyżej oceniane restauracje z całej kolekcji, ale w prawdziwej aplikacji restauracyjnej użytkownik chciałby sortować i filtrować dane. Na przykład aplikacja powinna być w stanie wyświetlić „Najlepsze restauracje z owocami morza w Filadelfii” lub „Najtańsza pizza”.

Kliknięcie białego paska u góry aplikacji powoduje wyświetlenie okna dialogowego filtrów. W tej sekcji użyjemy zapytań Firestore, aby to okno dialogowe działało:

67898572a35672a5.png

Edit Let był na onFilter() metoda MainActivity.java . Metoda ta przyjmuje Filters przedmiot, który jest obiektem pomocnika stworzyliśmy przechwycić wyjście z okna dialogowego filtrów. Zmienimy tę metodę, aby skonstruować zapytanie z filtrów:

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

W powyższym fragmencie budujemy Query obiektu poprzez dołączenie where i orderBy klauzule dopasować podane filtry.

Ponownie uruchomić aplikację i wybrać filtr następujące pokazać najbardziej popularnych restauracji niskiej cenie:

7a67a8a400c80c50.png

Powinieneś teraz zobaczyć przefiltrowaną listę restauracji zawierającą tylko opcje o niskich cenach:

a670188398c3c59.png

Jeśli dotarłeś tak daleko, zbudowałeś teraz w pełni działającą aplikację do przeglądania rekomendacji restauracji w Firestore! Możesz teraz sortować i filtrować restauracje w czasie rzeczywistym. W kolejnych kilku sekcjach publikujemy recenzje i zabezpieczenia aplikacji.

W tej sekcji dodamy oceny do aplikacji, aby użytkownicy mogli przeglądać swoje ulubione (lub najmniej lubiane) restauracje.

Kolekcje i podkolekcje

Jak dotąd przechowujemy wszystkie dane restauracji w zbiorze najwyższego poziomu o nazwie „restauracje”. Gdy stopy użytkownika restauracja chcemy dodać nową Rating obiektu do restauracji. Do tego zadania użyjemy podkolekcji. Możesz myśleć o podkolekcji jako o kolekcji dołączonej do dokumentu. Tak więc każdy dokument dotyczący restauracji będzie zawierał podzbiór ocen pełen dokumentów oceny. Kolekcje podrzędne pomagają organizować dane bez nadmiernego rozrostu naszych dokumentów lub wymagających złożonych zapytań.

Aby uzyskać dostęp do subcollection, call .collection() na dokumencie dominującej:

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

Możesz uzyskać dostęp do podkolekcji i wysyłać do niej zapytania, tak jak w przypadku kolekcji najwyższego poziomu, nie ma ograniczeń rozmiaru ani zmian wydajności. Możesz przeczytać więcej o modelu danych FireStore tutaj .

Zapisywanie danych w transakcji

Dodanie Rating dla prawidłowego subcollection wymaga jedynie wywołanie .add() , ale musimy również zaktualizować Restaurant średnią ocenę i liczbę ocen obiektu w celu uwzględnienia nowych danych. Jeśli użyjemy oddzielnych operacji do wprowadzenia tych dwóch zmian, istnieje wiele sytuacji wyścigu, które mogą spowodować nieaktualne lub nieprawidłowe dane.

Aby upewnić się, że oceny są dodawane prawidłowo, użyjemy transakcji, aby dodać oceny do restauracji. Ta transakcja wykona kilka czynności:

  • Przeczytaj aktualną ocenę restauracji i oblicz nową
  • Dodaj ocenę do podkolekcji
  • Zaktualizuj średnią ocenę restauracji i liczbę ocen

Otwarte RestaurantDetailActivity.java i wdrożenie addRating funkcję:

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

addRating() funkcja zwraca Task reprezentujący całą transakcję. W onRating() słuchacze funkcyjne są dodawane do zadania, aby odpowiedzieć na skutek transakcji.

Teraz ponownie uruchomić aplikację i kliknąć na jedną z restauracji, które powinny wywołać ekran restauracja szczegół. Kliknij przycisk +, aby rozpocząć dodawanie opinii. Dodaj opinię, wybierając liczbę gwiazdek i wpisując tekst.

78fa16cdf8ef435a.png

Uderzanie Prześlij rozpocznie transakcję. Po zakończeniu transakcji zobaczysz swoją recenzję poniżej oraz aktualizację liczby recenzji restauracji:

f9e670f40bd615b0.png

Gratulacje! Masz teraz społecznościową, lokalną, mobilną aplikację do recenzowania restauracji opartą na Cloud Firestore. Słyszałem, że są one obecnie bardzo popularne.

Do tej pory nie braliśmy pod uwagę bezpieczeństwa tej aplikacji. Skąd wiemy, że użytkownicy mogą tylko odczytywać i zapisywać poprawne własne dane? FireStore datbases są zabezpieczone za pomocą pliku konfiguracyjnego o nazwie zasad bezpieczeństwa .

Otwórz firestore.rules plik, powinieneś zobaczyć, co następuje:

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

Zmieńmy się te zasady, aby uniknąć niechcianych danych acesss lub zmienia, otwórz firestore.rules plik i zastąpić zawartość z następujących powodów:

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

Te reguły ograniczają dostęp, aby zapewnić, że klienci wprowadzają tylko bezpieczne zmiany. Na przykład aktualizacje dokumentu restauracji mogą zmienić tylko oceny, a nie nazwę lub inne niezmienne dane. Oceny można tworzyć tylko wtedy, gdy identyfikator użytkownika jest zgodny z zalogowanym użytkownikiem, co zapobiega podszywaniu się.

Aby dowiedzieć się więcej na temat zasad bezpieczeństwa można znaleźć w dokumentacji .

Utworzyłeś teraz w pełni funkcjonalną aplikację na Firestore. Poznałeś najważniejsze funkcje Firestore, w tym:

  • Dokumenty i kolekcje
  • Odczytywanie i zapisywanie danych
  • Sortowanie i filtrowanie za pomocą zapytań
  • Podkolekcje
  • Transakcje

Ucz się więcej

Aby dalej uczyć się o Firestore, oto kilka dobrych miejsc, od których możesz zacząć:

Aplikacja restauracyjna w tym ćwiczeniu z kodowania została oparta na przykładowej aplikacji „Przyjazne jedzenie”. Można przeglądać kod źródłowy dla tej aplikacji tutaj .

Opcjonalnie: wdrożenie do produkcji

Do tej pory ta aplikacja korzystała tylko z pakietu emulatorów Firebase. Jeśli chcesz dowiedzieć się, jak wdrożyć tę aplikację w prawdziwym projekcie Firebase, przejdź do następnego kroku.

Do tej pory ta aplikacja była całkowicie lokalna, wszystkie dane są zawarte w pakiecie Firebase Emulator Suite. W tej sekcji dowiesz się, jak skonfigurować projekt Firebase, aby ta aplikacja działała w środowisku produkcyjnym.

Uwierzytelnianie Firebase

W Firebase consle przejść do sekcji Uwierzytelnianie i przejdź do logowania w zakładce Providers .

Włącz metodę logowania przez e-mail:

334ef7f6ff4da4ce.png

Firestore

Utwórz bazę danych

Przejdź do sekcji FireStore konsoli i kliknij przycisk Utwórz bazę danych:

  1. Gdy pojawi się monit o zasadach bezpieczeństwa zdecydować się rozpocząć w trybie Locked, będziemy aktualizować te zasady wkrótce.
  2. Wybierz lokalizację bazy danych, której chcesz używać dla swojej aplikacji. Należy pamiętać, że wybór lokalizacji bazy danych jest stałym decyzja i to zmienić trzeba będzie utworzyć nowy projekt. Aby uzyskać więcej informacji o wyborze lokalizacji inwestycji, zobacz dokumentację .

Zasady wdrażania

Aby wdrożyć reguły bezpieczeństwa, które napisałeś wcześniej, uruchom następujące polecenie w katalogu codelab:

$ firebase deploy --only firestore:rules

Pozwoli to wdrożyć zawartość firestore.rules do projektu, który można potwierdzić, przechodząc do zakładki zasad w konsoli.

Wdróż indeksy

Aplikacja FriendlyEats ma złożone sortowanie i filtrowanie, które wymaga wielu niestandardowych indeksów złożonych. Mogą być tworzone ręcznie w konsoli Firebase ale łatwiej jest napisać swoje definicje w firestore.indexes.json pliku i wdrożyć je za pomocą Firebase CLI.

Jeśli otworzysz firestore.indexes.json plik widać, że wymagane indeksy zostały już dostarczone:

{
  "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": []
}

Aby wdrożyć te indeksy, uruchom następujące polecenie:

$ firebase deploy --only firestore:indexes

Pamiętaj, że tworzenie indeksu nie jest natychmiastowe, możesz monitorować postęp w konsoli Firebase.

Skonfiguruj aplikację

W FirebaseUtil klasie mamy skonfigurowany Firebase SDK Aby połączyć się z emulatorów, gdy w trybie debugowania:

public class FirebaseUtil {

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

    // ...
}

Jeśli chcesz przetestować swoją aplikację w swoim prawdziwym projekcie Firebase, możesz:

  1. Zbuduj aplikację w trybie wydania i uruchom ją na urządzeniu.
  2. Tymczasowo zmienić sUseEmulators na false i ponownie uruchomić aplikację.

Należy pamiętać, że może trzeba wylogować się z aplikacji i zalogować się ponownie, aby prawidłowo podłączyć do produkcji.