Codelab Android Cloud Firestore

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

1. Tinjauan

Sasaran

Dalam codelab ini, Anda akan mem-build aplikasi rekomendasi restoran di Android yang didukung oleh Cloud Firestore. Anda akan belajar bagaimana:

  • 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 Firebase console 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, "Makanan Ramah"), dan klik Lanjutkan .

9d2f625aebcab6af.png

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

3. Siapkan proyek sampel

Unduh kodenya

Jalankan perintah berikut untuk menggandakan kode contoh 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 kode langsung dari GitHub.

Tambahkan konfigurasi Firebase

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

73d151ed16016421.png

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

Impor proyek

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

4. Siapkan Emulator Firebase

Dalam codelab ini, Anda akan menggunakan Firebase Emulator Suite untuk mengemulasi Cloud Firestore secara lokal dan layanan Firebase lainnya. Ini memberikan 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 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 project 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 untuk memulai Emulator Firebase. 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 sisa codelab, 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 komputer Anda, saat aplikasi dimulai.

Pada metode create() 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 mengompilasi aplikasi dalam mode release , kondisi ini akan salah.

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

Jalankan aplikasi

Jika Anda telah menambahkan file google-services.json dengan benar, proyek seharusnya sekarang dapat 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:

Emulator Autentikasi Firebase

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

Pada bagian ini kita akan menulis beberapa data ke Firestore sehingga kita dapat mengisi home screen yang saat ini kosong.

Objek model utama di aplikasi kita 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 saat kami mengeklik tombol "Tambah Item Acak" di menu luapan. Buka file MainFragment.kt dan ganti konten dalam 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 "Add Random Items" di menu overflow (di pojok 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:

Emulator Autentikasi Firebase

Data ini 100% lokal untuk mesin Anda. Faktanya, proyek Anda yang sebenarnya bahkan belum berisi database Firestore! Artinya 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 mempelajari 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 waktu nyata. Karena tujuan akhir kita adalah mengikat data ini ke RecyclerView , kita perlu membuat kelas RecyclerView.Adapter untuk mendengarkan data.

Buka kelas FirestoreAdapter , yang telah diimplementasikan sebagian. Pertama, mari buat adaptor mengimplementasikan EventListener dan tentukan 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 kejadian ADDED untuk setiap dokumen baru. Karena kumpulan hasil kueri berubah dari waktu ke waktu, pendengar akan menerima lebih banyak peristiwa yang berisi perubahan tersebut. Sekarang mari 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()
    }

Akhirnya implementasikan metode startListening() untuk melampirkan pendengar:

    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 secara instan!

8. Mengurutkan dan memfilter data

Aplikasi saat ini menampilkan restoran dengan peringkat teratas di seluruh koleksi, tetapi di aplikasi restoran nyata, pengguna ingin menyortir 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 menampilkan dialog filter. Di bagian ini kita akan menggunakan kueri Firestore untuk membuat dialog ini berfungsi:

67898572a35672a5.png

Mari kita edit metode onFilter() dari MainFragment.kt . Metode ini menerima objek Filters yang merupakan objek pembantu yang kami 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
    }

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

Jalankan aplikasi lagi dan pilih filter berikut untuk menampilkan restoran harga murah paling populer:

7a67a8a400c80c50.png

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

a670188398c3c59.png

Jika Anda sudah sampai sejauh ini, Anda sekarang telah membuat aplikasi melihat rekomendasi restoran yang berfungsi penuh di Firestore! Sekarang Anda 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) mereka.

Koleksi dan subkoleksi

Sejauh ini kami telah menyimpan semua data restoran dalam koleksi tingkat atas yang disebut "restoran". Saat pengguna menilai sebuah restoran, kami ingin menambahkan objek Rating baru ke restoran tersebut. Untuk tugas ini kita akan menggunakan subkoleksi. Anda dapat menganggap subkoleksi sebagai koleksi yang dilampirkan ke dokumen. Jadi setiap dokumen restoran akan memiliki subkoleksi peringkat yang penuh dengan dokumen peringkat. Subkoleksi membantu mengatur data tanpa membebani dokumen kami 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 menanyakan subkoleksi seperti pada koleksi tingkat atas, tidak ada batasan ukuran atau perubahan kinerja. Anda dapat membaca selengkapnya tentang model data Firestore di sini .

Menulis data dalam transaksi

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

Untuk memastikan 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 terapkan 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. Saat transaksi selesai, Anda akan melihat ulasan Anda ditampilkan di bawah ini dan pembaruan untuk jumlah ulasan restoran:

f9e670f40bd615b0.png

Selamat! Anda sekarang memiliki aplikasi ulasan restoran sosial, lokal, seluler yang dibuat di Cloud Firestore. Saya dengar 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 yang benar? Basis data Firestore diamankan dengan file konfigurasi yang disebut Security Rules .

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 ubah aturan ini untuk mencegah akses atau perubahan data yang tidak diinginkan, buka file firestore.rules dan ganti isinya 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 dokumen restoran hanya dapat mengubah peringkat, bukan nama atau data lain yang tidak dapat diubah. Peringkat hanya dapat dibuat jika ID pengguna cocok dengan pengguna yang masuk, yang mencegah spoofing.

Untuk membaca lebih lanjut tentang Aturan Keamanan, kunjungi dokumentasi .

11. Kesimpulan

Anda sekarang telah membuat aplikasi berfitur lengkap di atas Firestore. Anda 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 beberapa tempat bagus untuk memulai:

Aplikasi restoran dalam codelab ini didasarkan pada contoh aplikasi "Makanan Ramah". Anda dapat menelusuri kode sumber untuk aplikasi tersebut 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 nyata, lanjutkan ke langkah berikutnya.

12. (Opsional) Terapkan aplikasi Anda

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

Otentikasi Firebase

Di konsol Firebase, buka bagian Otentikasi dan klik Mulai . Arahkan ke tab Metode masuk dan pilih opsi Email/Kata Sandi dari penyedia Asli .

Aktifkan metode masuk Email/Sandi dan klik Simpan .

penyedia masuk.png

Firestore

Buat basis data

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

  1. Saat diminta 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 pemilihan lokasi proyek, lihat dokumentasi .

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

Terapkan Indeks

Aplikasi FriendlyEats memiliki penyortiran dan pemfilteran kompleks 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 men-deploy-nya 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 progresnya di konsol Firebase.

Konfigurasikan aplikasi

Di file util/FirestoreInitializer.kt dan util/AuthInitializer.kt kami mengonfigurasi Firebase SDK 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 untuk terhubung ke produksi dengan benar.