1. Übersicht
Ziele
In diesem Codelab erstellen Sie eine Android-App für Restaurantempfehlungen, die auf Cloud Firestore basiert. Nach Abschluss können Sie:
- Daten aus einer Android-App in Firestore lesen und schreiben
- Änderungen an Firestore-Daten in Echtzeit überwachen
- Firebase Authentication und Sicherheitsregeln zum Schutz von Firestore-Daten verwenden
- Komplexe Firestore-Abfragen schreiben
Vorbereitung
Bevor Sie mit diesem Codelab beginnen, müssen Sie Folgendes tun:
- Android Studio Flamingo oder höher
- Einen Android-Emulator mit API 19 oder höher
- Node.js-Version 16 oder höher
- Java-Version 17 oder höher
2. Firebase-Projekt erstellen
- Melden Sie sich mit Ihrem Google-Konto in der Firebase Console an.
- Klicken Sie in der Firebase Console auf Projekt hinzufügen.
- Geben Sie wie im Screenshot unten einen Namen für Ihr Firebase-Projekt ein (z. B. „Friendly Eats“) und klicken Sie auf Weiter.
- Möglicherweise werden Sie aufgefordert, Google Analytics zu aktivieren. Für dieses Codelab spielt Ihre Auswahl keine Rolle.
- Nach etwa einer Minute ist Ihr Firebase-Projekt einsatzbereit. Klicken Sie auf Weiter.
3. Beispielprojekt einrichten
Code herunterladen
Führen Sie den folgenden Befehl aus, um den Beispielcode für dieses Codelab zu klonen. Dadurch wird auf Ihrem Computer ein Ordner mit dem Namen friendlyeats-android
erstellt:
$ git clone https://github.com/firebase/friendlyeats-android
Wenn Sie Git nicht auf Ihrem Computer haben, können Sie den Code auch direkt von GitHub herunterladen.
Firebase-Konfiguration hinzufügen
- Wählen Sie in der Firebase Console im linken Navigationsbereich Projektübersicht aus. Klicken Sie auf die Schaltfläche Android, um die Plattform auszuwählen. Geben Sie bei der Aufforderung nach einem Paketnamen
com.google.firebase.example.fireeats
ein.
- Klicken Sie auf App registrieren und folgen Sie der Anleitung, um die Datei
google-services.json
herunterzuladen und in den Ordnerapp/
des gerade heruntergeladenen Codes zu verschieben. Klicken Sie anschließend auf Weiter.
Projekt importieren
Öffnen Sie Android Studio. Klicken Sie auf File > New > Import Project (Datei > Neu > Projekt importieren) und wählen Sie den Ordner friendlyeats-android aus.
4. Firebase Emulators einrichten
In diesem Codelab verwenden Sie die Firebase Emulator Suite, um Cloud Firestore und andere Firebase-Dienste lokal zu emulieren. So erhalten Sie eine sichere, schnelle und kostenlose lokale Entwicklungsumgebung für die Erstellung Ihrer App.
Firebase CLI installieren
Sie müssen zuerst die Firebase CLI installieren. Wenn Sie macOS oder Linux verwenden, können Sie den folgenden cURL-Befehl ausführen:
curl -sL https://firebase.tools | bash
Wenn Sie Windows verwenden, lesen Sie die Installationsanleitung, um ein eigenständiges Binärprogramm zu erhalten oder die Installation über npm
durchzuführen.
Nachdem Sie die Befehlszeile installiert haben, sollte beim Ausführen von firebase --version
die Version 9.0.0
oder höher angezeigt werden:
$ firebase --version 9.0.0
Anmelden
Führen Sie firebase login
aus, um die Befehlszeile mit Ihrem Google-Konto zu verbinden. Dadurch wird ein neues Browserfenster geöffnet, um den Anmeldevorgang abzuschließen. Wählen Sie dasselbe Konto aus, das Sie beim Erstellen Ihres Firebase-Projekts verwendet haben.
Projekt verknüpfen
Führen Sie im Ordner friendlyeats-android
firebase use --add
aus, um Ihr lokales Projekt mit Ihrem Firebase-Projekt zu verbinden. Folgen Sie der Anleitung, um das zuvor erstellte Projekt auszuwählen. Wenn Sie aufgefordert werden, einen Alias auszuwählen, geben Sie default
ein.
5. Anwendung ausführen
Jetzt ist es an der Zeit, die Firebase Emulator Suite und die Android-App von FriendlyEats zum ersten Mal auszuführen.
Emulatoren ausführen
Führen Sie im Terminal im Verzeichnis friendlyeats-android
den Befehl firebase emulators:start
aus, um die Firebase-Emulatoren zu starten. Sie sollten Protokolle wie diese sehen:
$ 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.
Sie haben jetzt eine vollständige lokale Entwicklungsumgebung auf Ihrem Computer. Lassen Sie diesen Befehl für den Rest des Codelabs laufen, da Ihre Android-App eine Verbindung zu den Emulatoren herstellen muss.
App mit den Emulatoren verbinden
Öffnen Sie die Dateien util/FirestoreInitializer.kt
und util/AuthInitializer.kt
in Android Studio. Diese Dateien enthalten die Logik, mit der die Firebase SDKs beim Start der Anwendung mit den lokalen Emulatoren auf Ihrem Computer verbunden werden.
Sehen Sie sich in der create()
-Methode der Klasse FirestoreInitializer
diesen Code an:
// Use emulators only in debug builds
if (BuildConfig.DEBUG) {
firestore.useEmulator(FIRESTORE_EMULATOR_HOST, FIRESTORE_EMULATOR_PORT)
}
Wir verwenden BuildConfig
, um dafür zu sorgen, dass nur eine Verbindung zu den Emulatoren hergestellt wird, wenn unsere App im debug
-Modus ausgeführt wird. Wenn wir die App im release
-Modus kompilieren, ist diese Bedingung falsch.
Wir sehen, dass die useEmulator(host, port)
-Methode verwendet wird, um das Firebase SDK mit dem lokalen Firestore-Emulator zu verbinden. In der gesamten App verwenden wir FirebaseUtil.getFirestore()
, um auf diese Instanz von FirebaseFirestore
zuzugreifen. So können wir sicher sein, dass immer eine Verbindung zum Firestore-Emulator hergestellt wird, wenn die App im debug
-Modus ausgeführt wird.
Anwendung ausführen
Wenn Sie die google-services.json
-Datei richtig hinzugefügt haben, sollte das Projekt jetzt kompiliert werden. Klicken Sie in Android Studio auf Build > Rebuild Project (Erstellen > Projekt neu erstellen) und prüfen Sie, ob keine Fehler mehr vorhanden sind.
Führen Sie die App in Android Studio auf Ihrem Android-Emulator aus. Zuerst wird der Bildschirm „Anmelden“ angezeigt. Sie können sich mit einer beliebigen E-Mail-Adresse und einem beliebigen Passwort in der App anmelden. Bei dieser Anmeldung wird eine Verbindung zum Firebase Authentication-Emulator hergestellt, sodass keine echten Anmeldedaten übertragen werden.
Öffnen Sie jetzt die Benutzeroberfläche der Emulatoren, indem Sie in Ihrem Webbrowser http://localhost:4000 aufrufen. Klicken Sie dann auf den Tab Authentifizierung. Das Konto, das Sie gerade erstellt haben, sollte angezeigt werden:
Nach der Anmeldung sollte der Startbildschirm der App angezeigt werden:
Bald werden wir dem Startbildschirm einige Daten hinzufügen.
6. Daten in Firestore schreiben
In diesem Abschnitt schreiben wir einige Daten in Firestore, damit wir den derzeit leeren Startbildschirm befüllen können.
Das Hauptmodellobjekt in unserer App ist ein Restaurant (siehe model/Restaurant.kt
). Firestore-Daten werden in Dokumente, Sammlungen und untergeordnete Sammlungen aufgeteilt. Wir speichern jedes Restaurant als Dokument in einer Sammlung auf oberster Ebene namens "restaurants"
. Weitere Informationen zum Firestore-Datenmodell finden Sie in den Dokumenten und Sammlungen der Dokumentation.
Zu Demonstrationszwecken fügen wir der App eine Funktion hinzu, mit der zehn zufällige Restaurants erstellt werden, wenn wir im Dreipunkt-Menü auf die Schaltfläche „Zufällige Elemente hinzufügen“ klicken. Öffnen Sie die Datei MainFragment.kt
und ersetzen Sie den Inhalt in der Methode onAddItemsClicked()
durch Folgendes:
private fun onAddItemsClicked() {
val restaurantsRef = firestore.collection("restaurants")
for (i in 0..9) {
// Create random restaurant / ratings
val randomRestaurant = RestaurantUtil.getRandom(requireContext())
// Add restaurant
restaurantsRef.add(randomRestaurant)
}
}
Im Code oben gibt es einige wichtige Dinge zu beachten:
- Zuerst haben wir eine Referenz auf die Sammlung
"restaurants"
abgerufen. Sammlungen werden implizit erstellt, wenn Dokumente hinzugefügt werden. Daher musste die Sammlung nicht vor dem Schreiben von Daten erstellt werden. - Dokumente können mit Kotlin-Datenklassen erstellt werden, mit denen wir jedes Restaurantdokument erstellen.
- Mit der Methode
add()
wird einer Sammlung ein Dokument mit einer automatisch generierten ID hinzugefügt. Daher mussten wir für jedes Restaurant keine eindeutige ID angeben.
Führen Sie die App jetzt noch einmal aus und klicken Sie im Dreipunkt-Menü oben rechts auf die Schaltfläche „Zufällige Elemente hinzufügen“, um den Code auszuführen, den Sie gerade geschrieben haben:
Öffnen Sie jetzt die Benutzeroberfläche der Emulatoren, indem Sie in Ihrem Webbrowser http://localhost:4000 aufrufen. Klicken Sie dann auf den Tab Firestore. Die Daten, die Sie gerade hinzugefügt haben, sollten dort angezeigt werden:
Diese Daten befinden sich zu 100% lokal auf Ihrem Computer. Tatsächlich enthält Ihr echtes Projekt noch keine Firestore-Datenbank. Sie können diese Daten also ohne Konsequenzen ändern und löschen.
Sie haben gerade Daten in Firestore geschrieben. Im nächsten Schritt erfahren Sie, wie Sie diese Daten in der App anzeigen.
7. Daten aus Firestore anzeigen
In diesem Schritt erfahren Sie, wie Sie Daten aus Firestore abrufen und in Ihrer App anzeigen. Der erste Schritt zum Lesen von Daten aus Firestore besteht darin, eine Query
zu erstellen. Öffnen Sie die Datei MainFragment.kt
und fügen Sie den folgenden Code an den Anfang der Methode onViewCreated()
ein:
// Firestore
firestore = Firebase.firestore
// Get the 50 highest rated restaurants
query = firestore.collection("restaurants")
.orderBy("avgRating", Query.Direction.DESCENDING)
.limit(LIMIT.toLong())
Jetzt möchten wir die Abfrage beobachten, damit wir alle übereinstimmenden Dokumente erhalten und in Echtzeit über zukünftige Aktualisierungen informiert werden. Da wir diese Daten letztendlich an eine RecyclerView
binden möchten, müssen wir eine RecyclerView.Adapter
-Klasse erstellen, um die Daten zu überwachen.
Öffnen Sie die Klasse FirestoreAdapter
, die bereits teilweise implementiert wurde. Implementieren wir zuerst EventListener
im Adapter und definieren die Funktion onEvent
so, dass sie Aktualisierungen für eine Firestore-Abfrage empfangen kann:
abstract class FirestoreAdapter<VH : RecyclerView.ViewHolder>(private var query: Query?) :
RecyclerView.Adapter<VH>(),
EventListener<QuerySnapshot> { // Add this implements
// ...
// Add this method
override fun onEvent(documentSnapshots: QuerySnapshot?, e: FirebaseFirestoreException?) {
// Handle errors
if (e != null) {
Log.w(TAG, "onEvent:error", e)
return
}
// Dispatch the event
if (documentSnapshots != null) {
for (change in documentSnapshots.documentChanges) {
// snapshot of the changed document
when (change.type) {
DocumentChange.Type.ADDED -> {
// TODO: handle document added
}
DocumentChange.Type.MODIFIED -> {
// TODO: handle document changed
}
DocumentChange.Type.REMOVED -> {
// TODO: handle document removed
}
}
}
}
onDataChanged()
}
// ...
}
Beim ersten Laden erhält der Listener für jedes neue Dokument ein ADDED
-Ereignis. Wenn sich die Ergebnismenge der Abfrage im Laufe der Zeit ändert, erhält der Listener weitere Ereignisse mit den Änderungen. Jetzt können wir den Listener fertig implementieren. Fügen Sie zuerst drei neue Methoden hinzu: onDocumentAdded
, onDocumentModified
und onDocumentRemoved
:
private fun onDocumentAdded(change: DocumentChange) {
snapshots.add(change.newIndex, change.document)
notifyItemInserted(change.newIndex)
}
private fun onDocumentModified(change: DocumentChange) {
if (change.oldIndex == change.newIndex) {
// Item changed but remained in same position
snapshots[change.oldIndex] = change.document
notifyItemChanged(change.oldIndex)
} else {
// Item changed and changed position
snapshots.removeAt(change.oldIndex)
snapshots.add(change.newIndex, change.document)
notifyItemMoved(change.oldIndex, change.newIndex)
}
}
private fun onDocumentRemoved(change: DocumentChange) {
snapshots.removeAt(change.oldIndex)
notifyItemRemoved(change.oldIndex)
}
Rufen Sie diese neuen Methoden dann über onEvent
auf:
override fun onEvent(documentSnapshots: QuerySnapshot?, e: FirebaseFirestoreException?) {
// Handle errors
if (e != null) {
Log.w(TAG, "onEvent:error", e)
return
}
// Dispatch the event
if (documentSnapshots != null) {
for (change in documentSnapshots.documentChanges) {
// snapshot of the changed document
when (change.type) {
DocumentChange.Type.ADDED -> {
onDocumentAdded(change) // Add this line
}
DocumentChange.Type.MODIFIED -> {
onDocumentModified(change) // Add this line
}
DocumentChange.Type.REMOVED -> {
onDocumentRemoved(change) // Add this line
}
}
}
}
onDataChanged()
}
Implementiere abschließend die Methode startListening()
, um den Listener anzuhängen:
fun startListening() {
if (registration == null) {
registration = query.addSnapshotListener(this)
}
}
Jetzt ist die App vollständig für das Lesen von Daten aus Firestore konfiguriert. Führen Sie die App noch einmal aus. Sie sollten die im vorherigen Schritt hinzugefügten Restaurants sehen:
Kehren Sie jetzt in Ihrem Browser zur Emulator-Benutzeroberfläche zurück und bearbeiten Sie einen der Restaurantnamen. Die Änderung sollte fast sofort in der App zu sehen sein.
8. Daten sortieren und filtern
Derzeit werden in der App die bestbewerteten Restaurants der gesamten Sammlung angezeigt. In einer echten Restaurant-App möchte der Nutzer jedoch die Daten sortieren und filtern können. Die App sollte beispielsweise „Top-Meeresfrüchterestaurants in Philadelphia“ oder „Die günstigste Pizza“ anzeigen können.
Wenn du oben in der App auf die weiße Leiste klickst, wird ein Filterdialogfeld geöffnet. In diesem Abschnitt verwenden wir Firestore-Abfragen, um diesen Dialog zu ermöglichen:
Bearbeiten wir die onFilter()
-Methode von MainFragment.kt
. Diese Methode akzeptiert ein Filters
-Objekt, ein Hilfsobjekt, das wir zum Erfassen der Ausgabe des Dialogfelds „Filter“ erstellt haben. Wir ändern diese Methode, um eine Abfrage aus den Filtern zu erstellen:
override fun onFilter(filters: Filters) {
// Construct query basic query
var query: Query = firestore.collection("restaurants")
// Category (equality filter)
if (filters.hasCategory()) {
query = query.whereEqualTo(Restaurant.FIELD_CATEGORY, filters.category)
}
// City (equality filter)
if (filters.hasCity()) {
query = query.whereEqualTo(Restaurant.FIELD_CITY, filters.city)
}
// Price (equality filter)
if (filters.hasPrice()) {
query = query.whereEqualTo(Restaurant.FIELD_PRICE, filters.price)
}
// Sort by (orderBy with direction)
if (filters.hasSortBy()) {
query = query.orderBy(filters.sortBy.toString(), filters.sortDirection)
}
// Limit items
query = query.limit(LIMIT.toLong())
// Update the query
adapter.setQuery(query)
// Set header
binding.textCurrentSearch.text = HtmlCompat.fromHtml(
filters.getSearchDescription(requireContext()),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
binding.textCurrentSortBy.text = filters.getOrderDescription(requireContext())
// Save filters
viewModel.filters = filters
}
Im Snippet oben erstellen wir ein Query
-Objekt, indem wir where
- und orderBy
-Klauseln anhängen, die den angegebenen Filtern entsprechen.
Starten Sie die App noch einmal und wählen Sie den folgenden Filter aus, um die beliebtesten preiswerten Restaurants zu sehen:
Sie sollten jetzt eine gefilterte Liste von Restaurants sehen, die nur preisgünstige Optionen enthalten:
Wenn Sie es bis hierher geschafft haben, haben Sie jetzt eine voll funktionsfähige App für Restaurantempfehlungen in Firestore erstellt. Sie können Restaurants jetzt in Echtzeit sortieren und filtern. In den nächsten Abschnitten fügen wir den Restaurants Rezensionen und der App Sicherheitsregeln hinzu.
9. Daten in untergeordneten Sammlungen organisieren
In diesem Abschnitt fügen wir der App Bewertungen hinzu, damit Nutzer ihre Lieblings- (oder unbeliebtesten) Restaurants bewerten können.
Sammlungen und Untersammlungen
Bisher haben wir alle Restaurantdaten in einer Sammlung auf oberster Ebene namens „restaurants“ gespeichert. Wenn ein Nutzer ein Restaurant bewertet, möchten wir den Restaurants ein neues Rating
-Objekt hinzufügen. Für diese Aufgabe verwenden wir eine Untersammlung. Eine untergeordnete Sammlung ist eine Sammlung, die an ein Dokument angehängt ist. Jedes Restaurantdokument hat also eine untergeordnete Sammlung mit Bewertungsdokumenten. Untersammlungen helfen, Daten zu organisieren, ohne die Dokumente zu vergrößern oder komplexe Abfragen zu erfordern.
Wenn Sie auf eine untergeordnete Sammlung zugreifen möchten, rufen Sie .collection()
im übergeordneten Dokument auf:
val subRef = firestore.collection("restaurants")
.document("abc123")
.collection("ratings")
Sie können auf eine untergeordnete Sammlung genauso zugreifen und sie abfragen wie auf eine Sammlung der obersten Ebene. Es gibt keine Größenbeschränkungen oder Leistungsänderungen. Weitere Informationen zum Firestore-Datenmodell
Daten in einer Transaktion schreiben
Um der entsprechenden Untersammlung eine Rating
hinzuzufügen, müssen wir nur .add()
aufrufen. Außerdem müssen wir die durchschnittliche Bewertung und die Anzahl der Bewertungen des Restaurant
-Objekts aktualisieren, um die neuen Daten widerzuspiegeln. Wenn wir diese beiden Änderungen mit separaten Vorgängen vornehmen, kann es zu einer Reihe von Race-Bedingungen kommen, die zu veralteten oder falschen Daten führen können.
Damit Bewertungen korrekt hinzugefügt werden, verwenden wir eine Transaktion, um einem Restaurant Bewertungen hinzuzufügen. Bei dieser Transaktion werden einige Aktionen ausgeführt:
- Aktuelle Bewertung des Restaurants lesen und neue Bewertung berechnen
- Bewertung der Untersammlung hinzufügen
- Durchschnittliche Bewertung und Anzahl der Bewertungen des Restaurants aktualisieren
Öffnen Sie RestaurantDetailFragment.kt
und implementieren Sie die Funktion addRating
:
private fun addRating(restaurantRef: DocumentReference, rating: Rating): Task<Void> {
// Create reference for new rating, for use inside the transaction
val ratingRef = restaurantRef.collection("ratings").document()
// In a transaction, add the new rating and update the aggregate totals
return firestore.runTransaction { transaction ->
val restaurant = transaction.get(restaurantRef).toObject<Restaurant>()
?: throw Exception("Restaurant not found at ${restaurantRef.path}")
// Compute new number of ratings
val newNumRatings = restaurant.numRatings + 1
// Compute new average rating
val oldRatingTotal = restaurant.avgRating * restaurant.numRatings
val newAvgRating = (oldRatingTotal + rating.rating) / newNumRatings
// Set new restaurant info
restaurant.numRatings = newNumRatings
restaurant.avgRating = newAvgRating
// Commit to Firestore
transaction.set(restaurantRef, restaurant)
transaction.set(ratingRef, rating)
null
}
}
Die Funktion addRating()
gibt einen Task
zurück, der die gesamte Transaktion darstellt. In der onRating()
-Funktion werden der Aufgabe Listener hinzugefügt, um auf das Ergebnis der Transaktion zu reagieren.
Führen Sie die App jetzt noch einmal aus und klicken Sie auf eines der Restaurants. Daraufhin sollte der Detailbildschirm des Restaurants angezeigt werden. Klicken Sie auf die Schaltfläche +, um eine Rezension hinzuzufügen. Fügen Sie eine Rezension hinzu, indem Sie eine Anzahl von Sternen auswählen und Text eingeben.
Wenn du auf Senden klickst, wird die Transaktion gestartet. Sobald die Transaktion abgeschlossen ist, wird Ihre Rezension unten angezeigt und die Anzahl der Rezensionen für das Restaurant wird aktualisiert:
Glückwunsch! Sie haben jetzt eine soziale, lokale, mobile App für Restaurantbewertungen, die auf Cloud Firestore basiert. Ich habe gehört, dass sie heutzutage sehr beliebt sind.
10. Daten schützen
Bisher haben wir die Sicherheit dieser Anwendung nicht berücksichtigt. Woher wissen wir, dass Nutzer nur die richtigen eigenen Daten lesen und schreiben können? Firestore-Datenbanken werden durch eine Konfigurationsdatei namens Sicherheitsregeln geschützt.
Öffnen Sie die Datei firestore.rules
und ersetzen Sie den Inhalt durch Folgendes:
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;
}
}
}
}
Diese Regeln schränken den Zugriff ein, damit Kunden nur sichere Änderungen vornehmen. Bei Aktualisierungen eines Restaurantdokuments können beispielsweise nur die Bewertungen geändert werden, nicht der Name oder andere unveränderliche Daten. Bewertungen können nur erstellt werden, wenn die User-ID mit dem angemeldeten Nutzer übereinstimmt. So wird Spoofing verhindert.
Weitere Informationen zu Sicherheitsregeln finden Sie in der Dokumentation.
11. Fazit
Sie haben jetzt eine voll funktionsfähige App auf Firestore erstellt. Sie haben die wichtigsten Firestore-Funktionen kennengelernt, darunter:
- Dokumente und Sammlungen
- Daten lesen und schreiben
- Mit Abfragen sortieren und filtern
- Untergeordnete Sammlungen
- Transaktionen
Weitere Informationen
Hier finden Sie weitere Informationen zu Firestore:
Die Restaurant-App in diesem Codelab basiert auf der Beispielanwendung „Friendly Eats“. Den Quellcode für diese App finden Sie hier.
Optional: Für Produktion bereitstellen
Bisher wurde für diese App nur die Firebase Emulator Suite verwendet. Wenn Sie wissen möchten, wie Sie diese App in einem echten Firebase-Projekt bereitstellen, fahren Sie mit dem nächsten Schritt fort.
12. (Optional) Anwendung bereitstellen
Bisher war diese App vollständig lokal und alle Daten befinden sich in der Firebase Emulator Suite. In diesem Abschnitt erfahren Sie, wie Sie Ihr Firebase-Projekt so konfigurieren, dass diese App in der Produktion funktioniert.
Firebase Authentication
Klicken Sie in der Firebase Console im Bereich Authentifizierung auf Jetzt starten. Rufen Sie den Tab Anmeldemethode auf und wählen Sie unter Native Anbieter die Option E-Mail/Passwort aus.
Aktiviere die Anmeldemethode E-Mail-Adresse/Passwort und klicke auf Speichern.
Firestore
Datenbank erstellen
Klicken Sie in der Console im Bereich Firestore-Datenbank auf Datenbank erstellen:
- Wenn Sie bei der Frage zu Sicherheitsregeln den Produktionsmodus auswählen, aktualisieren wir diese Regeln bald.
- Wählen Sie den Speicherort der Datenbank aus, den Sie für Ihre App verwenden möchten. Die Auswahl eines Speicherorts für die Datenbank ist dauerhaft. Wenn Sie ihn ändern möchten, müssen Sie ein neues Projekt erstellen. Weitere Informationen zur Auswahl eines Projektstandorts finden Sie in der Dokumentation.
Bereitstellungsregeln
Führen Sie den folgenden Befehl im Codelab-Verzeichnis aus, um die zuvor erstellten Sicherheitsregeln bereitzustellen:
$ firebase deploy --only firestore:rules
Dadurch werden die Inhalte von firestore.rules
in Ihrem Projekt bereitgestellt. Sie können dies in der Konsole auf dem Tab Regeln prüfen.
Indexe bereitstellen
Die FriendlyEats-App bietet eine komplexe Sortierung und Filterung, für die eine Reihe benutzerdefinierter zusammengesetzter Indexe erforderlich ist. Sie können sie manuell in der Firebase Console erstellen. Es ist jedoch einfacher, ihre Definitionen in der Datei firestore.indexes.json
zu schreiben und sie mit der Firebase CLI bereitzustellen.
Wenn Sie die Datei firestore.indexes.json
öffnen, sehen Sie, dass die erforderlichen Indexe bereits bereitgestellt wurden:
{
"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": []
}
Führen Sie den folgenden Befehl aus, um diese Indexe bereitzustellen:
$ firebase deploy --only firestore:indexes
Das Erstellen des Index dauert einige Zeit. Sie können den Fortschritt in der Firebase Console verfolgen.
App konfigurieren
In den Dateien util/FirestoreInitializer.kt
und util/AuthInitializer.kt
haben wir das Firebase SDK so konfiguriert, dass es im Debug-Modus eine Verbindung zu den Emulatoren herstellt:
override fun create(context: Context): FirebaseFirestore {
val firestore = Firebase.firestore
// Use emulators only in debug builds
if (BuildConfig.DEBUG) {
firestore.useEmulator(FIRESTORE_EMULATOR_HOST, FIRESTORE_EMULATOR_PORT)
}
return firestore
}
Wenn Sie Ihre App mit Ihrem echten Firebase-Projekt testen möchten, haben Sie folgende Möglichkeiten:
- Erstellen Sie die App im Release-Modus und führen Sie sie auf einem Gerät aus.
- Ersetzen Sie
BuildConfig.DEBUG
vorübergehend durchfalse
und führen Sie die App noch einmal aus.
Möglicherweise müssen Sie sich von der App abmelden und wieder anmelden, um eine ordnungsgemäße Verbindung zur Produktionsversion herzustellen.