1. Przegląd
Cele
W tym ćwiczeniu z kodowania zbudujesz aplikację polecającą restauracje na Androida, wspieraną przez Cloud Firestore. Dowiesz 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:
- Android Studio 4.0 lub nowszy
- Emulator Androida z API 19 lub wyższym
- Node.js w wersji 10 lub nowszej
- Java w wersji 8 lub nowszej
2. Utwórz projekt Firebase
- Zaloguj się do konsoli Firebase za pomocą swojego konta Google.
- W konsoli Firebase kliknij Dodaj projekt .
- Jak pokazano na zrzucie ekranu poniżej, wpisz nazwę swojego projektu Firebase (na przykład „Przyjazne posiłki”) i kliknij Kontynuuj .
- Możesz zostać poproszony o włączenie Google Analytics, dla celów tego ćwiczenia z programowania Twój wybór nie ma znaczenia.
- Po około minucie Twój projekt Firebase będzie gotowy. Kliknij Kontynuuj .
3. Skonfiguruj przykładowy projekt
Pobierz kod
Uruchom następujące polecenie, aby sklonować przykładowy kod dla tego ćwiczenia z programowania. Spowoduje to utworzenie na twoim komputerze folderu o nazwie friendlyeats-android
:
$ 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.
Dodaj konfigurację Firebase
- W konsoli Firebase wybierz Przegląd projektu w lewym panelu nawigacyjnym. Kliknij przycisk Android , aby wybrać platformę. Po wyświetleniu monitu o nazwę pakietu użyj
com.google.firebase.example.fireeats
- Kliknij Zarejestruj aplikację i postępuj zgodnie z instrukcjami, aby pobrać plik
google-services.json
i przenieść go do folderuapp/
właśnie pobranego kodu. Następnie kliknij Dalej .
Importuj projekt
Otwórz Studio Androida. Kliknij Plik > Nowy > Importuj projekt i wybierz folder friendlyeats-android .
4. Skonfiguruj emulatory Firebase
Podczas tego ćwiczenia z programowania będziesz używać pakietu Firebase Emulator Suite do lokalnego emulowania Cloud Firestore i innych usług Firebase. Zapewnia to bezpieczne, szybkie i bezpłatne lokalne środowisko programistyczne do tworzenia aplikacji.
Zainstaluj Firebase CLI
Najpierw musisz zainstalować Firebase CLI . Jeśli używasz systemu macOS lub Linux, możesz uruchomić następujące polecenie cURL:
curl -sL https://firebase.tools | bash
Jeśli korzystasz z systemu Windows, przeczytaj instrukcje instalacji, aby uzyskać samodzielny plik binarny lub zainstalować przez npm
.
Po zainstalowaniu interfejsu CLI uruchomienie firebase --version
powinno zgłosić wersję 9.0.0
lub wyższą:
$ firebase --version 9.0.0
Zaloguj sie
Uruchom firebase login
, aby połączyć CLI z kontem 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.
Połącz swój projekt
Z poziomu folderu friendlyeats-android
uruchom firebase use --add
, aby połączyć swój lokalny projekt z projektem Firebase. Postępuj zgodnie z monitami, aby wybrać wcześniej utworzony projekt, a jeśli zostaniesz poproszony o wybranie aliasu, wprowadź default
.
5. Uruchom aplikację
Teraz nadszedł czas, aby po raz pierwszy uruchomić Firebase Emulator Suite i aplikację FriendlyEats na Androida.
Uruchom emulatory
W swoim terminalu z katalogu friendlyeats-android
uruchom firebase emulators:start
uruchamiać emulatory Firebase. 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 kompletne 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 łączymy się z emulatorami tylko wtedy, gdy nasza aplikacja działa w trybie debug
. Kiedy kompilujemy aplikację w trybie release
, ten warunek będzie fałszywy.
Teraz spójrz na getFirestore()
:
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 używa metody useEmulator(host, port)
do połączenia pakietu Firebase SDK z lokalnym emulatorem Firestore. W całej aplikacji będziemy używać funkcji FirebaseUtil.getFirestore()
, aby uzyskać dostęp do tego wystąpienia FirebaseFirestore
, dzięki czemu mamy pewność, że zawsze łączymy się z emulatorem Firestore, gdy działamy w trybie debug
.
Uruchom aplikację
Jeśli poprawnie dodałeś plik google-services.json
, projekt powinien się teraz skompilować. W Android Studio kliknij Build > Rebuild Project i upewnij się, że nie ma pozostałych błędów.
W Android Studio Uruchom aplikację na emulatorze Androida. 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 interfejs użytkownika emulatorów, przechodząc do http://localhost:4000 w przeglądarce internetowej. Następnie kliknij kartę Uwierzytelnianie i powinieneś zobaczyć konto, które właśnie utworzyłeś:
Po zakończeniu procesu logowania powinieneś zobaczyć ekran główny aplikacji:
Wkrótce dodamy trochę danych, aby wypełnić ekran główny.
6. Zapisz dane do Firestore
W tej sekcji napiszemy trochę danych do Firestore, aby wypełnić pusty ekran główny.
Głównym obiektem modelowym w naszej aplikacji jest restauracja (zobacz model/Restaurant.java
). Dane Firestore są podzielone na dokumenty, kolekcje i podkolekcje. Każda restauracja będzie przechowywana jako dokument w zbiorze najwyższego poziomu o nazwie "restaurants"
. Aby dowiedzieć się więcej o modelu danych Firestore, przeczytaj o dokumentach i kolekcjach 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 zamień zawartość w onAddItemsClicked()
na:
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 od nawiązania do kolekcji
"restaurants"
. 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 (Plain Old Java Object), których używamy do tworzenia każdego dokumentu restauracji.
- Metoda
add()
dodaje dokument do kolekcji z automatycznie wygenerowanym identyfikatorem, więc nie musieliśmy określać unikalnego identyfikatora dla każdej restauracji.
Teraz ponownie uruchom aplikację i kliknij przycisk „Dodaj losowe elementy” w rozszerzonym menu (w prawym górnym rogu), aby wywołać właśnie napisany kod:
Teraz otwórz interfejs użytkownika emulatorów, przechodząc do http://localhost:4000 w przeglądarce internetowej. Następnie kliknij kartę Firestore i powinieneś zobaczyć dane, które właśnie dodałeś:
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.
7. Wyświetl dane z Firestore
W tym kroku dowiemy się, jak pobierać dane z Firestore i wyświetlać je w naszej aplikacji. Pierwszym krokiem do odczytania danych z Firestore jest utworzenie Query
. Otwórz plik MainActivity.java
i dodaj następujący kod na początku metody onCreate()
:
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ż naszym ostatecznym celem jest powiązanie tych danych z RecyclerView
, musimy utworzyć klasę RecyclerView.Adapter
do nasłuchiwania danych.
Otwórz klasę FirestoreAdapter
, która została już częściowo zaimplementowana. Najpierw sprawmy, aby adapter zaimplementował EventListener
i zdefiniował funkcję onEvent
, aby mógł otrzymywać aktualizacje zapytania 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();
}
// ...
}
Przy początkowym ładowaniu słuchacz otrzyma jedno zdarzenie ADDED
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. Najpierw dodaj trzy nowe metody: onDocumentAdded
, onDocumentModified
i 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 wywołaj te nowe metody 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();
}
Na koniec zaimplementuj startListening()
, aby dołączyć odbiornik:
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 dodane w poprzednim kroku:
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!
8. Sortuj i filtruj dane
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:
Zmodyfikujmy metodę onFilter()
z MainActivity.java
. Ta metoda akceptuje obiekt Filters
, który jest obiektem pomocniczym, który utworzyliśmy do przechwytywania danych wyjściowych okna dialogowego filtrów. Zmienimy tę metodę, aby skonstruować zapytanie z filtrów:
@Override
public void onFilter(Filters filters) {
// Construct 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);
}
We fragmencie powyżej budujemy obiekt Query
, dołączając klauzule where
i orderBy
, aby dopasować podane filtry.
Uruchom aplikację ponownie i wybierz następujący filtr, aby wyświetlić najpopularniejsze restauracje o niskich cenach:
Powinieneś teraz zobaczyć przefiltrowaną listę restauracji zawierającą tylko opcje o niskich cenach:
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 dodamy recenzje restauracji i dodamy zasady bezpieczeństwa do aplikacji.
9. Uporządkuj dane w podkolekcjach
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 użytkownik ocenia restaurację, chcemy dodać do restauracji nowy obiekt Rating
. 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 z ocenami. Kolekcje podrzędne pomagają w porządkowaniu danych bez nadmiernego rozrostu naszych dokumentów lub konieczności składania złożonych zapytań.
Aby uzyskać dostęp do podkolekcji, wywołaj .collection()
w dokumencie nadrzędnym:
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. Więcej informacji o modelu danych Firestore znajdziesz tutaj .
Zapisywanie danych w transakcji
Dodanie Rating
do odpowiedniej podkolekcji wymaga jedynie wywołania funkcji .add()
, ale musimy również zaktualizować średnią ocenę i liczbę ocen obiektu Restaurant
, aby odzwierciedlić nowe dane. 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
Otwórz RestaurantDetailActivity.java
i zaimplementuj funkcję addRating
:
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;
}
});
}
Funkcja addRating()
zwraca Task
reprezentujący całą transakcję. W funkcji onRating()
do zadania dodawane są detektory, które odpowiadają na wynik transakcji.
Teraz ponownie uruchom aplikację i kliknij jedną z restauracji, co powinno wywołać ekran szczegółów restauracji. Kliknij przycisk + , aby rozpocząć dodawanie opinii. Dodaj opinię, wybierając liczbę gwiazdek i wpisując tekst.
Kliknięcie Prześlij rozpocznie transakcję. Po zakończeniu transakcji zobaczysz swoją recenzję poniżej oraz aktualizację liczby recenzji restauracji:
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.
10. Zabezpiecz swoje dane
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? Bazy danych Firestore są zabezpieczone plikiem konfiguracyjnym o nazwie Security Rules .
Otwórz plik firestore.rules
, powinieneś zobaczyć następujące informacje:
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 te reguły, aby zapobiec niepożądanemu dostępowi do danych lub zmianom, otwórz plik firestore.rules
i zastąp zawartość następującą:
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 o regułach bezpieczeństwa, odwiedź dokumentację .
11. Wniosek
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 laboratorium została oparta na przykładowej aplikacji „Przyjazne jedzenie”. Tutaj możesz przeglądać kod źródłowy tej aplikacji .
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.
12. (Opcjonalnie) Wdróż swoją aplikację
Jak dotąd 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 konsoli Firebase przejdź do sekcji Uwierzytelnianie i kliknij Rozpocznij . Przejdź do karty Metoda logowania i wybierz opcję E-mail/hasło u dostawców natywnych .
Włącz metodę logowania przez e-mail/hasło i kliknij Zapisz .
Firestore
Utwórz bazę danych
Przejdź do sekcji Baza danych Firestore w konsoli i kliknij Utwórz bazę danych :
- Po wyświetleniu monitu o reguły zabezpieczeń wybierz uruchomienie w trybie produkcyjnym , wkrótce zaktualizujemy te reguły.
- Wybierz lokalizację bazy danych, której chcesz używać dla swojej aplikacji. Pamiętaj, że wybór lokalizacji bazy danych jest decyzją stałą i aby ją zmienić, będziesz musiał utworzyć nowy projekt. Więcej informacji na temat wyboru lokalizacji projektu można znaleźć w dokumentacji .
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
Spowoduje to wdrożenie zawartości firestore.rules
do Twojego projektu, co możesz potwierdzić, przechodząc do zakładki Reguły w konsoli.
Wdróż indeksy
Aplikacja FriendlyEats ma złożone sortowanie i filtrowanie, które wymaga szeregu niestandardowych indeksów złożonych. Można je utworzyć ręcznie w konsoli Firebase, ale łatwiej jest zapisać ich definicje w pliku firestore.indexes.json
i wdrożyć je za pomocą interfejsu wiersza polecenia Firebase.
Jeśli otworzysz plik firestore.indexes.json
, zobaczysz, ż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 klasie FirebaseUtil
skonfigurowaliśmy Firebase SDK do łączenia się z emulatorami 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:
- Zbuduj aplikację w trybie wydania i uruchom ją na urządzeniu.
- Tymczasowo zmień
sUseEmulators
nafalse
i ponownie uruchom aplikację.
Pamiętaj, że może być konieczne wylogowanie się z aplikacji i ponowne zalogowanie, aby prawidłowo połączyć się z produkcją.