Cloud Firestore Android Codelab

מטרות

במערכת קוד קוד זו תבנה אפליקציית המלצות למסעדות באנדרואיד המגובה על ידי Cloud Firestore. תלמד כיצד:

  • קרא וכתוב נתונים ל- Firestore מאפליקציית Android
  • האזן לשינויים בנתוני Firestore בזמן אמת
  • השתמש בכללי אימות ואבטחה של Firebase כדי לאבטח את נתוני Firestore
  • כתוב שאילתות Firestore מורכבות

תנאים מוקדמים

לפני שתתחיל קוד קוד זה וודא שיש לך:

  • Android Studio 4.0 ומעלה
  • אמולטור אנדרואיד
  • Node.js גרסה 10 ומעלה
  • גרסת Java 8 ומעלה
  1. היכנס למסוף Firebase באמצעות חשבון Google שלך.
  2. במסוף Firebase , לחץ על הוסף פרויקט .
  3. כפי שמוצג בתצלום המסך שלמטה, הזן שם לפרויקט Firebase שלך ​​(למשל, "Eat Friendly") ולחץ על המשך .

9d2f625aebcab6af.png

  1. יתכן שתתבקש להפעיל את Google Analytics, למטרות קוד קוד זה אין חשיבות לבחירתך.
  2. לאחר דקה לערך, פרויקט Firebase שלך ​​יהיה מוכן. לחץ על המשך .

הורד את הקוד

הפעל את הפקודה הבאה כדי לשכפל את קוד הדוגמה עבור קוד קוד זה. פעולה זו תיצור תיקיה הנקראת friendlyeats-android במחשב שלך:

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

אם אין לך git במחשב שלך, אתה יכול גם להוריד את הקוד ישירות מ- GitHub.

ייבא את הפרויקט ל- Android Studio. סביר להניח שתראה שגיאות אוסף או אולי אזהרה לגבי קובץ google-services.json חסר. נתקן זאת בחלק הבא.

הוסף תצורת Firebase

  1. במסוף Firebase בחר סקירה כללית על פרויקט בחלונית הימנית. לחץ על כפתור Android כדי לבחור את הפלטפורמה. כשתתבקש לשם חבילה השתמש ב- com.google.firebase.example.fireeats

73d151ed16016421.png

  1. לחץ על רשום יישום ופעל לפי ההוראות להורדת קובץ google-services.json , והעבר אותו app/ תיקיה של קוד הדוגמה. לאחר מכן לחץ על הבא .

במפתח קוד זה תשתמשו בחבילת האימולטור של Firebase לחיקוי מקומי של Cloud Firestore ושירותי Firebase אחרים. זה מספק סביבת פיתוח מקומית בטוחה, מהירה וחינמית לבניית האפליקציה שלך.

התקן את ה- CLI של Firebase

ראשית יהיה עליך להתקין את ה- Firebase CLI . הדרך הקלה ביותר לעשות זאת היא להשתמש ב- npm :

npm install -g firebase-tools

אם אין לך npm או שאתה נתקל בשגיאה, קרא את הוראות ההתקנה כדי לקבל בינארי עצמאי לפלטפורמה שלך.

לאחר התקנת ה- CLI, הפעלת firebase --version צריכה לדווח על גרסה של 9.0.0 ומעלה:

$ firebase --version
9.0.0

התחברות

הפעל firebase login כדי לחבר את ה- CLI לחשבון Google שלך. פעולה זו תפתח חלון דפדפן חדש להשלמת תהליך הכניסה. הקפד לבחור באותו חשבון שבו השתמשת בעת יצירת פרויקט Firebase שלך ​​קודם לכן.

מתוך התיקיה friendlyeats-android הפעל את firebase use --add Firebase - הוסף לחיבור הפרויקט המקומי שלך לפרויקט Firebase שלך. עקוב אחר ההנחיות לבחירת הפרויקט שיצרת קודם לכן ואם תתבקש לבחור כינוי, הזן את default .

עכשיו הגיע הזמן להפעיל לראשונה את חבילת האמולטור של Firebase ואת אפליקציית האנדרואיד FriendlyEats.

הפעל את האמולטורים

במסוף שלך מתוך המדריך friendlyeats-android הפעל firebase emulators:start להפעיל את האמולטורים של Firebase. אתה אמור לראות יומנים כאלה:

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

כעת יש לך סביבת פיתוח מקומית מלאה המופעלת במחשב שלך! הקפד להשאיר פקודה זו פועלת למשך שאר קוד הקוד, אפליקציית Android שלך תצטרך להתחבר לאמולטורים.

חבר את האפליקציה לאמולטורים

פתח את הקובץ FirebaseUtil.java ב- Android Studio. קובץ זה מכיל את ההיגיון לחיבור ה- SDK של Firebase לאמולטורים המקומיים הפועלים במחשב שלך.

בחלק העליון של הקובץ, בחן את השורה הזו:

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

אנו משתמשים ב- BuildConfig כדי לוודא שאנחנו מתחברים BuildConfig רק כשהאפליקציה שלנו פועלת במצב debug . כאשר אנו מרכיבים את האפליקציה במצב release מצב זה יהיה שקר.

עכשיו תסתכל על שיטת 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;
    }

אנו רואים שהוא משתמש בשיטת useEmulator(host, port) כדי לחבר את ה- SDK של Firebase לאמולטור Firestore המקומי. לאורך האפליקציה נשתמש ב- FirebaseUtil.getFirestore() כדי לגשת למופע זה של FirebaseFirestore כך שאנחנו בטוחים שאנחנו תמיד מתחברים לאמולטור Firestore כאשר אנו פועלים במצב debug .

הפעל את האפליקציה

אם הוספת את קובץ google-services.json כראוי, כעת הפרויקט אמור להיערך. באנדרואיד סטודיו לחץ על בנה > בנה מחדש את הפרויקט וודא שלא נשארו שגיאות.

ב- Android Studio הפעל את האפליקציה באמולטור Android שלך. בהתחלה יוצג בפניך מסך "כניסה". אתה יכול להשתמש בכל דוא"ל וסיסמה כדי להיכנס לאפליקציה. תהליך כניסה זה מתחבר לאמולטור האימות של Firebase, ולכן לא מועברים אישורים אמיתיים.

כעת פתח את ממשק המשתמש Emulators על ידי ניווט אל http: // localhost: 4000 בדפדפן האינטרנט שלך. לאחר מכן לחץ על כרטיסיית האימות ואתה אמור לראות את החשבון שיצרת זה עתה:

אמולטור האימות של Firebase

לאחר שתסיים את תהליך הכניסה אתה אמור לראות את מסך הבית של האפליקציה:

de06424023ffb4b9.png

בקרוב נוסיף כמה נתונים שיאכלסו את מסך הבית.

בחלק זה נכתוב כמה נתונים ל- Firestore כדי שנוכל לאכלס את מסך הבית הריק כרגע.

אובייקט המודל העיקרי באפליקציה שלנו הוא מסעדה (ראה model/Restaurant.java ). נתוני Firestore מפוצלים למסמכים, אוספים ואוספי משנה. אנו נאחסן כל מסעדה כמסמך באוסף ברמה העליונה המכונה "restaurants" . למידע נוסף על מודל הנתונים של Firestore, קרא על מסמכים ואוספים בתיעוד .

למטרות הדגמה, נוסיף פונקציונליות באפליקציה ליצירת עשר מסעדות אקראיות כאשר נלחץ על כפתור "הוסף פריטים אקראיים" בתפריט הצפה. פתח את הקובץ MainActivity.java ומלא את השיטה onAddItemsClicked() :

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

יש כמה דברים שחשוב לציין לגבי הקוד לעיל:

  • התחלנו בקבלת התייחסות לאוסף "restaurants" . אוספים נוצרים באופן מרומז בעת הוספת מסמכים, כך שלא היה צורך ליצור את האוסף לפני כתיבת הנתונים.
  • ניתן ליצור מסמכים באמצעות POJOs, בהם אנו משתמשים כדי ליצור כל מסמך במסעדה.
  • השיטה add() מוסיפה מסמך לאוסף עם מזהה שנוצר אוטומטית, כך שלא היינו צריכים לציין מזהה ייחודי לכל מסעדה.

כעת הפעל את האפליקציה שוב ולחץ על כפתור "הוסף פריטים אקראיים" בתפריט הגלישה כדי להפעיל את הקוד שכתבת זה עתה:

95691e9b71ba55e3.png

כעת פתח את ממשק המשתמש Emulators על ידי ניווט אל http: // localhost: 4000 בדפדפן האינטרנט שלך. לאחר מכן לחץ על הכרטיסייה Firestore ואתה אמור לראות את הנתונים שהוספת זה עתה:

אמולטור האימות של Firebase

נתונים אלה הם 100% מקומיים למכונה שלך. למעשה, הפרויקט האמיתי שלך אפילו לא מכיל אפילו מסד נתונים של Firestore! המשמעות היא שבטוח להתנסות בשינוי ומחיקת נתונים אלה ללא תוצאה.

מזל טוב, אתה פשוט כתבת נתונים לפירסטור! בשלב הבא נלמד כיצד להציג נתונים אלה באפליקציה.

בשלב זה נלמד כיצד לאחזר נתונים מפיירסטור ולהציג אותם באפליקציה שלנו. הצעד הראשון לקריאת נתונים מ- Firestore הוא יצירת Query . שנה את שיטת onCreate() :

        mFirestore = FirebaseUtil.getFirestore();

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

כעת אנו רוצים להקשיב לשאילתה, כך שנקבל את כל המסמכים התואמים ונקבל הודעה על עדכונים עתידיים בזמן אמת. מכיוון שהמטרה הסופית שלנו היא לאגד נתונים אלה ל- RecyclerView , עלינו ליצור מחלקה RecyclerView.Adapter כדי להאזין לנתונים.

פתח את מחלקת FirestoreAdapter , שהוטמעה כבר באופן חלקי. ראשית, בואו נגרום למתאם ליישם את EventListener ולהגדיר את פונקציית onEvent כך שהוא יוכל לקבל עדכונים לשאילתת 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();
    }

  // ...
}

בעומס הראשוני המאזין יקבל אירוע ADDED אחד עבור כל מסמך חדש. כאשר מערך התוצאות של השאילתה משתנה עם הזמן המאזין יקבל אירועים נוספים המכילים את השינויים. עכשיו בואו נסיים ליישם את המאזין. ראשית הוסף שלוש שיטות חדשות: onDocumentAdded , onDocumentModified ו- 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());
    }

ואז התקשר לשיטות חדשות אלה מ- 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();
    }

לבסוף יישם את שיטת startListening() לצירוף המאזין:

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

כעת האפליקציה מוגדרת לחלוטין לקריאת נתונים מ- Firestore. הפעל את האפליקציה שוב ועליך לראות את המסעדות שהוספת בשלב הקודם:

9e45f40faefce5d0.png

כעת חזור לממשק המשתמש של אמולטור בדפדפן שלך וערוך את אחד משמות המסעדות. אתה אמור לראות את זה משתנה באפליקציה כמעט באופן מיידי!

האפליקציה מציגה כיום את המסעדות המדורגות את הדירוג הגבוה ביותר בכל האוסף, אך באפליקציית מסעדות אמיתית המשתמש היה רוצה למיין ולסנן את הנתונים. לדוגמא האפליקציה אמורה להיות מסוגלת להציג את "מסעדות מאכלי ים מובילות בפילדלפיה" או "פיצה הכי יקרה".

לחיצה על פס לבן בחלק העליון של האפליקציה מעלה תיבת דו-שיח של פילטרים. בחלק זה נשתמש בשאילתות Firestore כדי לגרום לדיאלוג זה לעבוד:

67898572a35672a5.png

בואו onFilter() את שיטת onFilter() של MainActivity.java . שיטה זו מקבלת אובייקט Filters שהוא אובייקט עוזר שיצרנו כדי ללכוד את הפלט של תיבת הדו-שיח פילטרים. נשנה שיטה זו כדי לבנות שאילתה מהפילטרים:

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

בקטע הקוד שלמעלה אנו בונים אובייקט Query ידי צירוף סעיפי where ו- orderBy כדי להתאים למסננים הנתונים.

הפעל את האפליקציה שוב ובחר את המסנן הבא כדי להציג את המסעדות הפופולריות במחירים נמוכים:

7a67a8a400c80c50.png

כעת תראה רשימה מסוננת של מסעדות המכילה רק אפשרויות במחיר נמוך:

a670188398c3c59.png

אם הצלחתם להגיע עד כה, בניתם כעת אפליקציית צפייה בהמלצות למסעדות בתפקוד מלא בפיירסטור! כעת תוכלו למיין ולסנן מסעדות בזמן אמת. בחלקים הבאים אנו מפרסמים ביקורות ואבטחה לאפליקציה.

בחלק זה נוסיף דירוגים לאפליקציה כדי שמשתמשים יוכלו לבדוק את המסעדות המועדפות עליהם (או הכי פחות אהובים).

אוספים ואוספי משנה

עד כה אחסנו את כל נתוני המסעדה באוסף ברמה העליונה המכונה "מסעדות". כאשר משתמש מדרג מסעדה אנו רוצים להוסיף אובייקט Rating חדש למסעדות. למשימה זו נשתמש באוסף משנה. אתה יכול לחשוב על אוסף משנה כעל אוסף שמצורף למסמך. כך שלכל מסמך מסעדה תהיה אוסף משנה של רייטינג מלא במסמכי דירוג. אוספי משנה עוזרים לארגן נתונים מבלי לנפח את המסמכים שלנו או לדרוש שאילתות מורכבות.

כדי לגשת לאוסף משנה, התקשר ל- .collection() במסמך האב:

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

אתה יכול לגשת ולשאול על אוסף משנה בדיוק כמו עם אוסף ברמה העליונה, אין מגבלות גודל או שינויים בביצועים. תוכלו לקרוא עוד על מודל הנתונים של Firestore כאן .

כתיבת נתונים בעסקה

הוספת Rating ל subcollection נכונה רק דורש קורא .add() , אבל אנחנו גם צריכים לעדכן את Restaurant הדירוג הממוצע של האובייקט מספר הדירוגים כדי לשקף את הנתונים החדשים. אם אנו משתמשים בפעולות נפרדות לביצוע שני השינויים הללו ישנם מספר תנאי מירוץ שעלולים לגרום לנתונים מעופשים או שגויים.

כדי להבטיח כי הרייטינג יתווסף כראוי, נשתמש בעסקה כדי להוסיף דירוגים למסעדה. עסקה זו תבצע מספר פעולות:

  • קרא את הדירוג הנוכחי של המסעדה וחשב את הדירוג החדש
  • הוסף את הדירוג לאוסף המשנה
  • עדכן את הדירוג הממוצע של המסעדה ואת מספר הדירוגים

פתח את RestaurantDetailActivity.java addRating את פונקציית 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;
            }
        });
    }

addRating() מחזירה Task המייצגת את העסקה כולה. onRating() מאזינים מתווספים למשימה כדי להגיב לתוצאת העסקה.

כעת הפעל את האפליקציה שוב ולחץ על אחת המסעדות, שאמורה להעלות את מסך פרטי המסעדה. לחץ על כפתור + כדי להתחיל להוסיף ביקורת. הוסף ביקורת על ידי בחירת מספר כוכבים והזנת טקסט כלשהו.

78fa16cdf8ef435a.png

Hitting Submit יתחיל את העסקה. לאחר השלמת העסקה, תראה את הביקורת שלך למטה ועדכון לספירת הביקורות של המסעדה:

f9e670f40bd615b0.png

מזל טוב! כעת יש לך אפליקציית ביקורת על מסעדות חברתית, מקומית, בנויה ב- Cloud Firestore. אני שומע שאלה פופולריים מאוד בימינו.

עד כה לא שקלנו את האבטחה של יישום זה. איך נדע שמשתמשים יכולים לקרוא ולכתוב רק את הנתונים הנכונים שלהם? בסיסי הנתונים של Firestore מאובטחים על ידי קובץ תצורה הנקרא כללי אבטחה .

פתח את הקובץ firestore.rules , אתה אמור לראות את הדברים הבאים:

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

בואו ונשנה כללים אלה כדי למנוע כניסות או שינויים לא רצויים בנתונים, נפתח את הקובץ firestore.rules ונחליף את התוכן להלן:

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

כללים אלה מגבילים את הגישה כדי להבטיח שלקוחות יבצעו שינויים בטוחים בלבד. לדוגמא עדכונים למסמך מסעדה יכולים לשנות רק את הדירוגים, לא את השם או כל נתונים אחרים שאינם ניתנים לשינוי. ניתן ליצור דירוגים רק אם מזהה המשתמש תואם למשתמש המחובר, מה שמונע זיוף.

לקריאה נוספת על כללי אבטחה, בקר בתיעוד .

כעת יצרת אפליקציה בתכונות מלאות מעל Firestore. למדתם על התכונות החשובות ביותר של Firestore, כולל:

  • מסמכים ואוספים
  • קריאה וכתיבה של נתונים
  • מיון וסינון באמצעות שאילתות
  • אוספי משנה
  • עסקאות

למד עוד

כדי להמשיך ללמוד על Firestore, הנה כמה מקומות טובים להתחיל:

אפליקציית המסעדה בקוד קוד זה התבססה על יישום הדוגמא "ידידות אוכלת". תוכל לדפדף בקוד המקור של אותה אפליקציה כאן .

אופציונלי: פריסה לייצור

עד כה אפליקציה זו השתמשה רק בחבילת האמולטור של Firebase. אם ברצונך ללמוד כיצד לפרוס יישום זה לפרויקט Firebase אמיתי, המשך לשלב הבא.

עד כה האפליקציה הזו הייתה מקומית לחלוטין, כל הנתונים כלולים בסוויטת האמולטור של Firebase. בחלק זה תלמד כיצד להגדיר את פרויקט Firebase שלך ​​כך שאפליקציה זו תפעל בייצור.

אימות Firebase

בתכנית Firebase עברו למקטע אימות ונווטו לכרטיסיית ספקי הכניסה .

אפשר את שיטת הכניסה לדוא"ל:

334ef7f6ff4da4ce.png

Firestore

צור מסד נתונים

נווט לחלק Firestore של המסוף ולחץ על צור מסד נתונים :

  1. כשתתבקש לגבי כללי אבטחה בחר להתחיל במצב נעול , נעדכן את הכללים בקרוב.
  2. בחר את מיקום מסד הנתונים שבו תרצה להשתמש עבור האפליקציה שלך. שים לב שבחירת מיקום בסיס נתונים היא החלטה קבועה וכדי לשנות אותה יהיה עליך ליצור פרויקט חדש. למידע נוסף על בחירת מיקום פרויקט, עיין בתיעוד .

פריסת כללים

כדי לפרוס את כללי האבטחה שכתבת קודם לכן, הפעל את הפקודה הבאה בספריה codelab:

$ firebase deploy --only firestore:rules

פעולה זו תפרוס את התוכן של firestore.rules לפרויקט שלך, שאותו תוכל לאשר על ידי ניווט לכרטיסיה כללים במסוף.

פריסת אינדקסים

לאפליקציית FriendlyEats יש מיון וסינון מורכבים הדורשים מספר אינדקסים מורכבים בהתאמה אישית. אלה ניתנים ליצירה ידנית במסוף Firebase אך קל יותר לכתוב את ההגדרות שלהם בקובץ firestore.indexes.json ולפרוס אותן באמצעות ה- Firebase CLI.

אם תפתח את הקובץ firestore.indexes.json תראה שכבר סופקו האינדקסים הנדרשים:

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

כדי לפרוס אינדקסים אלה, הפעל את הפקודה הבאה:

$ firebase deploy --only firestore:indexes

שימו לב שיצירת אינדקס אינה מיידית, תוכלו לעקוב אחר ההתקדמות במסוף Firebase.

הגדר את האפליקציה

במחלקה FirebaseUtil הגדרנו את ה- SDK של Firebase להתחבר לאמולטורים במצב ניפוי באגים:

public class FirebaseUtil {

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

    // ...
}

אם תרצה לבדוק את האפליקציה שלך בפרויקט Firebase האמיתי שלך, תוכל:

  1. בנה את האפליקציה במצב שחרור והפעל אותה במכשיר.
  2. שנה זמנית את sUseEmulators ל- false והפעל את האפליקציה שוב.

שים לב כי ייתכן שיהיה עליך לצאת מהאפליקציה ולהיכנס שוב על מנת להתחבר כראוי לייצור.