Codelab Android Cloud Firestore

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

1. Ikhtisar

Sasaran

Dalam codelab ini Anda akan membangun aplikasi rekomendasi restoran di Android yang didukung oleh Cloud Firestore. Anda akan belajar cara:

  • Membaca dan menulis data ke Firestore dari aplikasi Android
  • Dengarkan perubahan data Firestore secara realtime
  • Gunakan Firebase Authentication dan aturan keamanan untuk mengamankan data Firestore
  • Tulis kueri Firestore yang kompleks

Prasyarat

Sebelum memulai codelab ini, pastikan Anda memiliki:

  • Android Studio 4.0 atau lebih tinggi
  • Emulator Android dengan API 19 atau lebih tinggi
  • Node.js versi 10 atau lebih tinggi
  • Java versi 8 atau lebih tinggi

2. Buat proyek Firebase

  1. Masuk ke konsol Firebase dengan akun Google Anda.
  2. Di konsol Firebase , klik Tambahkan proyek .
  3. Seperti yang ditunjukkan pada tangkapan layar di bawah, masukkan nama untuk proyek Firebase Anda (misalnya, "Makan Ramah"), dan klik Lanjutkan .

9d2f625aebcab6af.png

  1. Anda mungkin diminta untuk mengaktifkan Google Analytics, untuk tujuan codelab ini, pilihan Anda tidak masalah.
  2. Setelah sekitar satu menit, proyek Firebase Anda akan siap. Klik Lanjutkan .

3. Siapkan proyek sampel

Unduh kodenya

Jalankan perintah berikut untuk mengkloning kode sampel untuk codelab ini. Ini akan membuat folder bernama friendlyeats-android di mesin Anda:

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

Jika Anda tidak memiliki git di mesin Anda, Anda juga dapat mengunduh kodenya langsung dari GitHub.

Tambahkan konfigurasi Firebase

  1. Di Firebase console , pilih Ikhtisar Proyek di navigasi kiri. Klik tombol Android untuk memilih platform. Saat diminta untuk nama paket, gunakan com.google.firebase.example.fireeats

73d151ed16016421.png

  1. Klik Daftar Aplikasi dan ikuti petunjuk untuk mengunduh file google-services.json , dan pindahkan ke folder app/ dari kode yang baru saja Anda unduh. Kemudian klik Berikutnya .

Impor proyek

Buka AndroidStudio. Klik File > New > Import Project dan pilih folder friendlyeats-android .

4. Siapkan Emulator Firebase

Dalam codelab ini, Anda akan menggunakan Firebase Emulator Suite untuk secara lokal mengemulasi Cloud Firestore dan layanan Firebase lainnya. Ini menyediakan lingkungan pengembangan lokal yang aman, cepat, dan tanpa biaya untuk membangun aplikasi Anda.

Instal Firebase CLI

Pertama, Anda perlu menginstal Firebase CLI . Jika Anda menggunakan macOS atau Linux, Anda dapat menjalankan perintah cURL berikut:

curl -sL https://firebase.tools | bash

Jika Anda menggunakan Windows, baca petunjuk penginstalan untuk mendapatkan biner mandiri atau untuk menginstal melalui npm .

Setelah Anda menginstal CLI, menjalankan firebase --version akan melaporkan versi 9.0.0 atau lebih tinggi:

$ firebase --version
9.0.0

Gabung

Jalankan firebase login untuk menghubungkan CLI ke akun Google Anda. Ini akan membuka jendela browser baru untuk menyelesaikan proses login. Pastikan untuk memilih akun yang sama dengan yang Anda gunakan saat membuat proyek Firebase sebelumnya.

Dari dalam folder friendlyeats-android jalankan firebase use --add untuk menghubungkan proyek lokal Anda ke proyek Firebase Anda. Ikuti petunjuk untuk memilih proyek yang Anda buat sebelumnya dan jika diminta untuk memilih alias, masukkan default .

5. Jalankan aplikasi

Sekarang saatnya menjalankan Firebase Emulator Suite dan aplikasi Android FriendlyEats untuk pertama kalinya.

Jalankan emulator

Di terminal Anda dari dalam direktori friendlyeats-android , jalankan firebase emulators:start to start up Firebase Emulators. Anda akan melihat log seperti ini:

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

Anda sekarang memiliki lingkungan pengembangan lokal lengkap yang berjalan di mesin Anda! Pastikan untuk membiarkan perintah ini berjalan selama codelab lainnya, aplikasi Android Anda harus terhubung ke emulator.

Hubungkan aplikasi ke Emulator

Buka file util/FirestoreInitializer.kt dan util/AuthInitializer.kt di Android Studio. File-file ini berisi logika untuk menghubungkan Firebase SDK ke emulator lokal yang berjalan di mesin Anda, saat aplikasi dimulai.

Pada metode create() dari kelas FirestoreInitializer , periksa potongan kode ini:

    // Use emulators only in debug builds
    if (BuildConfig.DEBUG) {
        firestore.useEmulator(FIRESTORE_EMULATOR_HOST, FIRESTORE_EMULATOR_PORT)
    }

Kami menggunakan BuildConfig untuk memastikan kami hanya terhubung ke emulator saat aplikasi kami berjalan dalam mode debug . Saat kami mengkompilasi aplikasi dalam mode release , kondisi ini akan salah.

Kita dapat melihat bahwa ia menggunakan metode useEmulator(host, port) untuk menghubungkan Firebase SDK ke emulator Firestore lokal. Di seluruh aplikasi, kami akan menggunakan FirebaseUtil.getFirestore() untuk mengakses instance FirebaseFirestore ini sehingga kami yakin bahwa kami selalu terhubung ke emulator Firestore saat berjalan dalam mode debug .

Jalankan aplikasinya

Jika Anda telah menambahkan file google-services.json dengan benar, proyek sekarang harus dikompilasi. Di Android Studio klik Build > Rebuild Project dan pastikan tidak ada kesalahan yang tersisa.

Di Android Studio Jalankan aplikasi di emulator Android Anda. Pada awalnya Anda akan disajikan dengan layar "Masuk". Anda dapat menggunakan email dan kata sandi apa pun untuk masuk ke aplikasi. Proses masuk ini terhubung ke emulator Firebase Authentication, jadi tidak ada kredensial nyata yang dikirimkan.

Sekarang buka UI Emulator dengan menavigasi ke http://localhost:4000 di browser web Anda. Kemudian klik pada tab Otentikasi dan Anda akan melihat akun yang baru saja Anda buat:

Firebase Auth Emulator

Setelah Anda menyelesaikan proses masuk, Anda akan melihat layar beranda aplikasi:

de06424023ffb4b9.png

Segera kami akan menambahkan beberapa data untuk mengisi layar beranda.

6. Tulis data ke Firestore

Di bagian ini kita akan menulis beberapa data ke Firestore sehingga kita dapat mengisi layar beranda yang saat ini kosong.

Objek model utama di aplikasi kami adalah restoran (lihat model/Restaurant.kt ). Data Firestore dibagi menjadi dokumen, koleksi, dan subkoleksi. Kami akan menyimpan setiap restoran sebagai dokumen dalam koleksi tingkat atas yang disebut "restaurants" . Untuk mempelajari lebih lanjut tentang model data Firestore, baca tentang dokumen dan koleksi di dokumentasi .

Untuk tujuan demonstrasi, kami akan menambahkan fungsionalitas di aplikasi untuk membuat sepuluh restoran acak ketika kami mengklik tombol "Tambahkan Item Acak" di menu luapan. Buka file MainFragment.kt dan ganti konten di metode onAddItemsClicked() dengan:

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

Ada beberapa hal penting yang perlu diperhatikan tentang kode di atas:

  • Kami mulai dengan mendapatkan referensi ke koleksi "restaurants" . Koleksi dibuat secara implisit saat dokumen ditambahkan, jadi tidak perlu membuat koleksi sebelum menulis data.
  • Dokumen dapat dibuat menggunakan kelas data Kotlin, yang kami gunakan untuk membuat setiap dokumen Restoran.
  • Metode add() menambahkan dokumen ke koleksi dengan ID yang dibuat secara otomatis, jadi kita tidak perlu menentukan ID unik untuk setiap Restoran.

Sekarang jalankan aplikasi lagi dan klik tombol "Tambahkan Item Acak" di menu luapan (di sudut kanan atas) untuk menjalankan kode yang baru saja Anda tulis:

95691e9b71ba55e3.png

Sekarang buka UI Emulator dengan menavigasi ke http://localhost:4000 di browser web Anda. Kemudian klik pada tab Firestore dan Anda akan melihat data yang baru saja Anda tambahkan:

Firebase Auth Emulator

Data ini 100% lokal untuk mesin Anda. Faktanya, proyek Anda yang sebenarnya bahkan belum memiliki database Firestore! Ini berarti aman untuk bereksperimen dengan memodifikasi dan menghapus data ini tanpa konsekuensi.

Selamat, Anda baru saja menulis data ke Firestore! Pada langkah selanjutnya kita akan mempelajari cara menampilkan data ini di aplikasi.

7. Menampilkan data dari Firestore

Pada langkah ini kita akan belajar cara mengambil data dari Firestore dan menampilkannya di aplikasi kita. Langkah pertama untuk membaca data dari Firestore adalah membuat Query . Buka file MainFragment.kt dan tambahkan kode berikut ke awal metode onViewCreated() :

        // Firestore
        firestore = Firebase.firestore

        // Get the 50 highest rated restaurants
        query = firestore.collection("restaurants")
            .orderBy("avgRating", Query.Direction.DESCENDING)
            .limit(LIMIT.toLong())

Sekarang kami ingin mendengarkan kueri, sehingga kami mendapatkan semua dokumen yang cocok dan diberi tahu tentang pembaruan di masa mendatang secara real time. Karena tujuan akhir kita adalah untuk mengikat data ini ke RecyclerView , kita perlu membuat kelas RecyclerView.Adapter untuk mendengarkan data.

Buka kelas FirestoreAdapter , yang telah diimplementasikan sebagian. Pertama, buat adaptor yang mengimplementasikan EventListener dan mendefinisikan fungsi onEvent sehingga dapat menerima pembaruan untuk kueri Firestore:

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()
    }
    
    // ...
}

Pada pemuatan awal, pendengar akan menerima satu acara ADDED untuk setiap dokumen baru. Karena kumpulan hasil kueri berubah seiring waktu, pendengar akan menerima lebih banyak acara yang berisi perubahan. Sekarang mari kita selesaikan implementasi listener. Pertama tambahkan tiga metode baru: onDocumentAdded , onDocumentModified , dan 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)
    }

Kemudian panggil metode baru ini dari onEvent :

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

Terakhir implementasikan metode startListening() untuk melampirkan listener:

    fun startListening() {
        if (registration == null) {
            registration = query.addSnapshotListener(this)
        }
    }

Sekarang aplikasi sepenuhnya dikonfigurasi untuk membaca data dari Firestore. Jalankan aplikasi lagi dan Anda akan melihat restoran yang Anda tambahkan di langkah sebelumnya:

9e45f40faefce5d0.png

Sekarang kembali ke UI Emulator di browser Anda dan edit salah satu nama restoran. Anda akan melihatnya berubah di aplikasi hampir seketika!

8. Urutkan dan filter data

Aplikasi saat ini menampilkan restoran berperingkat teratas di seluruh koleksi, tetapi di aplikasi restoran nyata, pengguna ingin mengurutkan dan memfilter data. Misalnya aplikasi harus dapat menampilkan "Restoran makanan laut terbaik di Philadelphia" atau "Pizza paling murah".

Mengklik bilah putih di bagian atas aplikasi akan menampilkan dialog filter. Di bagian ini kita akan menggunakan kueri Firestore untuk membuat dialog ini berfungsi:

67898572a35672a5.png

Mari edit metode onFilter() dari MainFragment.kt . Metode ini menerima objek Filters yang merupakan objek pembantu yang kita buat untuk menangkap output dari dialog filter. Kami akan mengubah metode ini untuk membuat kueri dari filter:

    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
    }

Dalam cuplikan di atas kita membangun objek Query dengan melampirkan klausa where dan orderBy agar sesuai dengan filter yang diberikan.

Jalankan aplikasi lagi dan pilih filter berikut untuk menampilkan restoran murah terpopuler:

7a67a8a400c80c50.png

Anda sekarang akan melihat daftar restoran yang difilter yang hanya berisi opsi harga rendah:

a670188398c3c59.png

Jika Anda telah sampai sejauh ini, Anda sekarang telah membangun aplikasi melihat rekomendasi restoran yang berfungsi penuh di Firestore! Anda sekarang dapat mengurutkan dan memfilter restoran secara real time. Di beberapa bagian berikutnya kami akan menambahkan ulasan ke restoran dan menambahkan aturan keamanan ke aplikasi.

9. Atur data dalam subkoleksi

Di bagian ini kami akan menambahkan peringkat ke aplikasi sehingga pengguna dapat meninjau restoran favorit (atau paling tidak favorit).

Koleksi dan subkoleksi

Sejauh ini kami telah menyimpan semua data restoran dalam koleksi tingkat atas yang disebut "restoran". Saat pengguna menilai restoran, kami ingin menambahkan objek Rating baru ke restoran. Untuk tugas ini kita akan menggunakan subkoleksi. Anda dapat menganggap subkoleksi sebagai koleksi yang dilampirkan ke dokumen. Jadi setiap dokumen restoran akan memiliki subkoleksi rating yang penuh dengan dokumen rating. Subkoleksi membantu mengatur data tanpa membuat dokumen kita membengkak atau memerlukan kueri yang rumit.

Untuk mengakses subkoleksi, panggil .collection() pada dokumen induk:

val subRef = firestore.collection("restaurants")
        .document("abc123")
        .collection("ratings")

Anda dapat mengakses dan mengkueri subkoleksi seperti halnya dengan koleksi tingkat atas, tidak ada batasan ukuran atau perubahan kinerja. Anda dapat membaca lebih lanjut tentang model data Firestore di sini .

Menulis data dalam sebuah transaksi

Menambahkan Rating ke subkoleksi yang tepat hanya memerlukan pemanggilan .add() , tetapi kita juga perlu memperbarui rating rata-rata objek Restaurant dan jumlah rating untuk mencerminkan data baru. Jika kami menggunakan operasi terpisah untuk membuat dua perubahan ini, ada sejumlah kondisi balapan yang dapat mengakibatkan data basi atau salah.

Untuk memastikan bahwa peringkat ditambahkan dengan benar, kami akan menggunakan transaksi untuk menambahkan peringkat ke restoran. Transaksi ini akan melakukan beberapa tindakan:

  • Baca peringkat restoran saat ini dan hitung yang baru
  • Tambahkan peringkat ke subkoleksi
  • Perbarui peringkat rata-rata restoran dan jumlah peringkat

Buka RestaurantDetailFragment.kt dan implementasikan fungsi 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
        }
    }

Fungsi addRating() mengembalikan Task yang mewakili seluruh transaksi. Dalam fungsi onRating() , pendengar ditambahkan ke tugas untuk merespons hasil transaksi.

Sekarang Jalankan aplikasi lagi dan klik salah satu restoran, yang akan memunculkan layar detail restoran. Klik tombol + untuk mulai menambahkan ulasan. Tambahkan ulasan dengan memilih sejumlah bintang dan memasukkan beberapa teks.

78fa16cdf8ef435a.png

Menekan Kirim akan memulai transaksi. Ketika transaksi selesai, Anda akan melihat ulasan Anda ditampilkan di bawah dan pembaruan jumlah ulasan restoran:

f9e670f40bd615b0.png

Selamat! Anda sekarang memiliki aplikasi ulasan restoran seluler, lokal, sosial yang dibangun di Cloud Firestore. Kudengar itu sangat populer akhir-akhir ini.

10. Amankan data Anda

Sejauh ini kami belum mempertimbangkan keamanan aplikasi ini. Bagaimana kita tahu bahwa pengguna hanya dapat membaca dan menulis data sendiri yang benar? Basis data Firestore diamankan dengan file konfigurasi yang disebut Aturan Keamanan .

Buka file firestore.rules , Anda akan melihat yang berikut:

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

Mari kita ubah aturan ini untuk mencegah akses atau perubahan data yang tidak diinginkan, buka file firestore.rules dan ganti kontennya dengan yang berikut:

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

Aturan ini membatasi akses untuk memastikan bahwa klien hanya membuat perubahan yang aman. Misalnya pembaruan pada dokumen restoran hanya dapat mengubah peringkat, bukan nama atau data abadi lainnya. Peringkat hanya dapat dibuat jika ID pengguna cocok dengan pengguna yang masuk, yang mencegah spoofing.

Untuk membaca selengkapnya tentang Aturan Keamanan, kunjungi dokumentasi .

11. Kesimpulan

Anda sekarang telah membuat aplikasi berfitur lengkap di atas Firestore. Anda telah mempelajari tentang fitur Firestore yang paling penting termasuk:

  • Dokumen dan koleksi
  • Membaca dan menulis data
  • Menyortir dan memfilter dengan kueri
  • Subkoleksi
  • Transaksi

Belajarlah lagi

Untuk terus belajar tentang Firestore, berikut adalah beberapa tempat yang bagus untuk memulai:

Aplikasi restoran di codelab ini didasarkan pada aplikasi contoh "Friendly Eats". Anda dapat menelusuri kode sumber untuk aplikasi itu di sini .

Opsional: Terapkan ke produksi

Sejauh ini aplikasi ini hanya menggunakan Firebase Emulator Suite. Jika Anda ingin mempelajari cara menerapkan aplikasi ini ke proyek Firebase yang sebenarnya, lanjutkan ke langkah berikutnya.

12. (Opsional) Terapkan aplikasi Anda

Sejauh ini aplikasi ini sepenuhnya bersifat lokal, semua datanya ada di Firebase Emulator Suite. Di bagian ini Anda akan mempelajari cara mengonfigurasi proyek Firebase Anda sehingga aplikasi ini akan berfungsi dalam produksi.

Otentikasi Firebase

Di konsol Firebase, buka bagian Otentikasi dan klik Mulai . Navigasikan ke tab Metode masuk dan pilih opsi Email/Kata Sandi dari Penyedia asli .

Aktifkan metode masuk Email/Kata Sandi dan klik Simpan .

penyedia masuk.png

toko api

Buat database

Arahkan ke bagian Firestore Database di konsol dan klik Create Database :

  1. Saat ditanya tentang Aturan Keamanan pilih untuk memulai dalam Mode Produksi , kami akan segera memperbarui aturan tersebut.
  2. Pilih lokasi database yang ingin Anda gunakan untuk aplikasi Anda. Perhatikan bahwa memilih lokasi database adalah keputusan permanen dan untuk mengubahnya Anda harus membuat proyek baru. Untuk informasi lebih lanjut tentang memilih lokasi proyek, lihat dokumentasi .

Menerapkan Aturan

Untuk menerapkan Aturan Keamanan yang Anda tulis sebelumnya, jalankan perintah berikut di direktori codelab:

$ firebase deploy --only firestore:rules

Ini akan menyebarkan konten firestore.rules ke proyek Anda, yang dapat Anda konfirmasikan dengan membuka tab Aturan di konsol.

Menyebarkan Indeks

Aplikasi FriendlyEats memiliki penyortiran dan pemfilteran yang rumit yang memerlukan sejumlah indeks gabungan khusus. Ini dapat dibuat dengan tangan di konsol Firebase tetapi lebih mudah untuk menulis definisinya di file firestore.indexes.json dan menerapkannya menggunakan Firebase CLI.

Jika Anda membuka file firestore.indexes.json Anda akan melihat bahwa indeks yang diperlukan telah disediakan:

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

Untuk menyebarkan indeks ini, jalankan perintah berikut:

$ firebase deploy --only firestore:indexes

Perhatikan bahwa pembuatan indeks tidak instan, Anda dapat memantau kemajuannya di konsol Firebase.

Konfigurasikan aplikasi

Dalam file util/FirestoreInitializer.kt dan util/AuthInitializer.kt kami mengonfigurasi SDK Firebase untuk terhubung ke emulator saat dalam mode debug:

    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
    }

Jika Anda ingin menguji aplikasi Anda dengan proyek Firebase yang sebenarnya, Anda dapat:

  1. Bangun aplikasi dalam mode rilis dan jalankan di perangkat.
  2. Ganti sementara BuildConfig.DEBUG dengan false dan jalankan aplikasi lagi.

Perhatikan bahwa Anda mungkin perlu Keluar dari aplikasi dan masuk lagi agar terhubung dengan benar ke produksi.