Codelab Android Cloud Firestore

1. Ringkasan

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
  • Memproses perubahan data Firestore secara real-time
  • Menggunakan aturan keamanan dan Firebase Authentication untuk mengamankan data Firestore
  • Menulis kueri Firestore yang kompleks

Prasyarat

Sebelum memulai codelab ini, pastikan Anda memiliki:

  • Android Studio Flamingo atau yang lebih baru
  • Emulator Android dengan API 19 atau yang lebih tinggi
  • Node.js versi 16 atau yang lebih baru
  • Java versi 17 atau yang lebih baru

2. Membuat project Firebase

  1. Login ke Firebase console dengan Akun Google Anda.
  2. Di Firebase console, klik Add project.
  3. Seperti yang ditunjukkan pada screenshot di bawah, masukkan nama untuk project Firebase Anda (misalnya, "Friendly Eats"), lalu klik Continue.

9d2f625aebcab6af.png

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

3. Menyiapkan project contoh

Mendownload kode

Jalankan perintah berikut untuk meng-clone kode contoh untuk codelab ini. Tindakan ini akan membuat folder dengan nama friendlyeats-android di komputer Anda:

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

Jika tidak memiliki git di komputer, Anda juga dapat mendownload kodenya langsung dari GitHub.

Menambahkan konfigurasi Firebase

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

73d151ed16016421.png

  1. Klik Register App dan ikuti petunjuk untuk mendownload file google-services.json, lalu pindahkan ke folder app/ dari kode yang baru saja Anda download. Kemudian klik Berikutnya.

Mengimpor project

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

4. Menyiapkan Emulator Firebase

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

Menginstal Firebase CLI

Pertama-tama, Anda harus menginstal Firebase CLI. Jika 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 harus melaporkan versi 9.0.0 atau yang lebih tinggi:

$ firebase --version
9.0.0

Masuk

Jalankan firebase login untuk menghubungkan CLI ke Akun Google Anda. Tindakan 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 project lokal ke project Firebase Anda. Ikuti petunjuk untuk memilih project yang Anda buat sebelumnya dan jika diminta untuk memilih alias, masukkan default.

5. Menjalankan aplikasi

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

Menjalankan 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 perintah ini tetap berjalan selama codelab lainnya, aplikasi Android Anda harus terhubung ke emulator.

Menghubungkan aplikasi ke Emulator

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

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

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

Kita menggunakan BuildConfig untuk memastikan kita hanya terhubung ke emulator saat aplikasi berjalan dalam mode debug. Saat kita mengompilasi aplikasi dalam mode release, kondisi ini akan bernilai salah (false).

Kita dapat melihat bahwa ini menggunakan metode useEmulator(host, port) untuk menghubungkan Firebase SDK ke emulator Firestore lokal. Di seluruh 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.

Menjalankan aplikasi

Jika Anda telah menambahkan file google-services.json dengan benar, project kini seharusnya dikompilasi. Di Android Studio, klik Build > Rebuild Project dan pastikan tidak ada error yang tersisa.

Di Android Studio, Run aplikasi di emulator Android Anda. Pada awalnya Anda akan melihat layar "Login". Anda dapat menggunakan email dan sandi apa pun untuk login ke aplikasi. Proses login ini terhubung ke emulator Firebase Authentication, sehingga tidak ada kredensial sungguhan yang dikirim.

Sekarang buka UI Emulator dengan membuka http://localhost:4000 di browser web Anda. Kemudian, klik tab Authentication dan Anda akan melihat akun yang baru saja dibuat:

Emulator Firebase Auth

Setelah menyelesaikan proses login, Anda akan melihat layar utama aplikasi:

de06424023ffb4b9.png

Kami akan segera menambahkan beberapa data untuk mengisi layar utama.

6. Menulis data ke Firestore

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

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

Untuk tujuan demonstrasi, kita akan menambahkan fungsi di aplikasi untuk membuat sepuluh restoran acak saat mengklik tombol "Add Random Items" di menu tambahan. 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 memulai dengan mendapatkan referensi ke koleksi "restaurants". Koleksi dibuat secara implisit ketika dokumen ditambahkan, jadi Anda tidak perlu membuat koleksi sebelum menulis data.
  • Dokumen dapat dibuat menggunakan class data Kotlin, yang kita 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 kembali aplikasi dan klik tombol "Add Random Items" di menu tambahan (di pojok kanan atas) untuk memanggil kode yang baru saja Anda tulis:

95691e9b71ba55e3.png

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

Emulator Firebase Auth

Data ini 100% lokal untuk komputer Anda. Bahkan, project Anda yang sebenarnya belum berisi database Firestore. Artinya, Anda dapat bereksperimen dengan mengubah dan menghapus data ini tanpa konsekuensi.

Selamat, Anda baru saja menulis data ke Firestore. Pada langkah berikutnya, 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. 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 kita ingin memproses kueri, sehingga kita mendapatkan semua dokumen yang cocok dan diberi tahu tentang pembaruan mendatang secara real time. Karena sasaran akhir kita adalah mengikat data ini ke RecyclerView, kita perlu membuat class RecyclerView.Adapter untuk memproses data.

Buka class FirestoreAdapter, yang sudah diterapkan sebagian. Pertama, mari kita buat adaptor mengimplementasikan EventListener dan tentukan fungsi onEvent agar dapat menerima update 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()
    }
    
    // ...
}

Saat pemuatan awal, pemroses akan menerima satu peristiwa ADDED untuk setiap dokumen baru. Sebagai hasil perubahan kumpulan kueri dari waktu ke waktu, pemroses akan menerima lebih banyak peristiwa yang berisi perubahan tersebut. Sekarang, mari selesaikan penerapan pemroses. 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)
    }

Lalu, 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 pemroses:

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

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

9e45f40faefce5d0.pngS

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

8. Mengurutkan dan menyaring data.

Aplikasi saat ini menampilkan restoran dengan rating tertinggi di seluruh koleksi, tetapi dalam aplikasi restoran yang sebenarnya, pengguna ingin mengurutkan dan memfilter data. Misalnya, aplikasi harus dapat menampilkan "Restoran seafood terpopuler di Palembang" atau "Piza paling murah".

Mengeklik 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 kita edit metode onFilter() dari MainFragment.kt. Metode ini menerima objek Filters yang merupakan objek bantuan yang kita buat untuk merekam output dialog filter. Kita 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 mem-build objek Query dengan melampirkan klausa where dan orderBy agar cocok dengan filter yang diberikan.

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

7a67a8a400c80c50.png

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

a670188398c3c59.png

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

9. Mengatur data dalam subkoleksi

Di bagian ini, kita akan menambahkan rating ke aplikasi sehingga pengguna dapat mengulas restoran favorit mereka (atau yang paling tidak disukai).

Koleksi dan subkoleksi

Sejauh ini kita telah menyimpan semua data restoran di koleksi tingkat atas yang disebut "restaurants". Saat pengguna memberi rating restoran, kita 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 membuat dokumen tampak membengkak atau memerlukan kueri yang kompleks.

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

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

Anda dapat mengakses dan membuat kueri subkoleksi seperti pada koleksi level teratas, tanpa batasan ukuran atau perubahan performa. Anda dapat membaca lebih lanjut tentang model data Firestore di sini.

Menulis data dalam transaksi

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

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

  • Baca rating restoran saat ini dan hitung rating baru
  • Menambahkan rating ke subkoleksi
  • Memperbarui rating rata-rata dan jumlah rating restoran

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() menampilkan Task yang mewakili seluruh transaksi. Dalam fungsi onRating(), pemroses 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 jumlah bintang dan memasukkan teks.

78fa16cdf8ef435a.png

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

f9e670f40bd615b0.png

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

10. Melindungi data

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

Buka file firestore.rules, yang akan terlihat seperti 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 konten dengan berikut ini:

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 rating, bukan nama atau data yang tidak dapat diubah lainnya. Rating hanya dapat dibuat jika ID pengguna cocok dengan pengguna yang login, sehingga mencegah spoofing.

Untuk membaca Aturan Keamanan lebih lanjut, buka dokumentasi.

11. Kesimpulan

Anda kini telah membuat aplikasi berfitur lengkap selain Firestore. Anda telah mempelajari fitur-fitur paling penting Firestore, termasuk:

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

Pelajari Lebih Lanjut

Untuk terus mempelajari Firestore, berikut beberapa tempat yang bagus untuk memulai:

Aplikasi restoran dalam codelab ini didasarkan pada aplikasi contoh "Friendly Eats". Anda dapat menjelajahi kode sumber untuk aplikasi tersebut di sini.

Opsional: Men-deploy ke produksi

Sejauh ini aplikasi ini hanya menggunakan Firebase Emulator Suite. Jika Anda ingin mempelajari cara men-deploy aplikasi ini ke project Firebase sungguhan, lanjutkan ke langkah berikutnya.

12. (Opsional) Men-deploy aplikasi Anda

Sejauh ini aplikasi ini sepenuhnya bersifat lokal, semua data dimuat di Firebase Emulator Suite. Di bagian ini, Anda akan mempelajari cara mengonfigurasi project Firebase sehingga aplikasi ini akan berfungsi dalam tahap produksi.

Firebase Authentication

Di Firebase console, buka bagian Authentication, lalu klik Get started. Buka tab Sign-in method dan pilih opsi Email/Password dari Native providers.

Aktifkan metode login Email/Sandi dan klik Simpan.

penyedia-login.png

Firestore

Buat database

Buka bagian Firestore Database pada konsol dan klik Create Database:

  1. Saat diminta memilih Aturan Keamanan untuk memulai dalam Mode Produksi, kami akan segera memperbarui aturan tersebut.
  2. Pilih lokasi database yang ingin digunakan untuk aplikasi Anda. Perhatikan bahwa memilih lokasi database adalah keputusan permanen dan untuk mengubahnya, Anda harus membuat project baru. Untuk informasi selengkapnya tentang cara memilih lokasi project, lihat dokumentasi.

Men-deploy Aturan

Untuk men-deploy Aturan Keamanan yang Anda tulis sebelumnya, jalankan perintah berikut di direktori codelab:

$ firebase deploy --only firestore:rules

Tindakan ini akan men-deploy konten firestore.rules ke project Anda, yang dapat dikonfirmasi dengan membuka tab Rules di konsol.

Indeks Deployment

Aplikasi FriendlyEats memiliki penyortiran dan pemfilteran kompleks yang memerlukan sejumlah indeks senyawa khusus. Library ini dapat dibuat secara manual di Firebase console, tetapi lebih mudah untuk menulis definisinya di file firestore.indexes.json dan men-deploy-nya menggunakan Firebase CLI.

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

{
  "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 men-deploy indeks ini, jalankan perintah berikut:

$ firebase deploy --only firestore:indexes

Perhatikan bahwa pembuatan indeks tidak seketika. Anda dapat memantau progresnya di Firebase console.

Mengonfigurasi aplikasi

Dalam file util/FirestoreInitializer.kt dan util/AuthInitializer.kt, kita 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 ingin menguji aplikasi dengan project Firebase sungguhan, Anda dapat:

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

Perhatikan bahwa Anda mungkin perlu Logout dari aplikasi dan login lagi untuk terhubung ke produksi dengan benar.