Lab Kode Android Cloud Firestore

1. Ikhtisar

Sasaran

Dalam codelab ini Anda akan membuat 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 Flamingo atau lebih baru
  • Emulator Android dengan API 19 atau lebih tinggi
  • Node.js versi 16 atau lebih tinggi
  • Java versi 17 atau lebih tinggi

2. Buat proyek Firebase

  1. Masuk ke Firebase console dengan akun Google Anda.
  2. Di Firebase console , 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 mengkloning 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 kodenya langsung dari GitHub.

Tambahkan konfigurasi Firebase

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

73d151ed16016421.png

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

Impor proyek

Buka Android Studio. Klik File > Baru > Impor Proyek dan pilih folder Friendlyeats-android .

4. Siapkan Emulator Firebase

Dalam codelab ini Anda akan menggunakan Firebase Emulator Suite untuk mengemulasikan Cloud Firestore dan layanan Firebase lainnya secara lokal. Hal 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 instalasi 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 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 aplikasinya

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 Firebase Emulator. 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 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 mesin 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 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 dijalankan dalam mode debug .

Jalankan aplikasi

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 error 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, sehingga 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 Firebase Auth

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

de06424023ffb4b9.png

Kami akan segera 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 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 model data Firestore, baca tentang dokumen dan koleksi di dokumentasi .

Untuk tujuan demonstrasi, kami akan menambahkan fungsionalitas dalam aplikasi untuk membuat sepuluh restoran acak ketika kami mengklik tombol "Tambahkan Item Acak" 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 mulai dengan mendapatkan referensi ke koleksi "restaurants" . Koleksi dibuat secara implisit ketika dokumen ditambahkan, sehingga 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, sehingga kita tidak perlu menentukan ID unik untuk setiap Restoran.

Sekarang jalankan kembali aplikasinya dan klik tombol "Tambahkan Item Acak" di menu tambahan (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 Firebase Auth

Data ini 100% lokal untuk mesin Anda. Faktanya, proyek Anda yang sebenarnya belum berisi database Firestore! Artinya aman untuk bereksperimen dengan mengubah 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 diberitahu tentang pembaruan di masa mendatang secara real time. Karena tujuan akhir kita adalah mengikat data ini ke RecyclerView , kita perlu membuat kelas RecyclerView.Adapter untuk memproses data.

Buka kelas FirestoreAdapter , yang telah diimplementasikan sebagian. Pertama, mari kita buat adaptor mengimplementasikan EventListener dan menentukan fungsi onEvent sehingga dapat menerima pembaruan pada 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 peristiwa ADDED untuk setiap dokumen baru. Saat kumpulan hasil kueri berubah seiring waktu, pendengar akan menerima lebih banyak peristiwa yang berisi perubahan tersebut. Sekarang mari kita selesaikan penerapan pendengar. 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 pendengar:

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

Sekarang aplikasi telah dikonfigurasi sepenuhnya untuk membaca data dari Firestore. Jalankan kembali aplikasinya dan Anda akan melihat restoran yang Anda tambahkan pada 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. Menyortir dan memfilter data

Aplikasi saat ini menampilkan restoran dengan peringkat teratas di seluruh koleksi, namun dalam aplikasi restoran sebenarnya, 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 agar dialog ini berfungsi:

67898572a35672a5.png

Mari kita edit metode onFilter() pada MainFragment.kt . Metode ini menerima objek Filters yang merupakan objek pembantu yang kita buat untuk menangkap keluaran 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 membuat objek Query dengan melampirkan klausa where dan orderBy untuk mencocokkan filter yang diberikan.

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

7a67a8a400c80c50.png

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

a670188398c3c59.png

Jika Anda sudah sampai sejauh ini, kini Anda telah membuat 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 mengulas restoran favorit mereka (atau yang paling tidak favorit).

Koleksi dan subkoleksi

Sejauh ini kami telah menyimpan semua data restoran di 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 pada dokumen. Jadi setiap dokumen restoran akan memiliki subkoleksi rating yang penuh dengan dokumen rating. Subkoleksi membantu mengatur data tanpa membuat dokumen kami 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 menanyakan subkoleksi seperti halnya koleksi tingkat atas, tidak ada batasan ukuran atau perubahan kinerja. Anda dapat membaca selengkapnya tentang model data Firestore di sini .

Menulis data dalam suatu transaksi

Menambahkan Rating ke subkoleksi yang tepat hanya memerlukan pemanggilan .add() , namun kita juga perlu memperbarui rating rata-rata objek Restaurant dan jumlah rating untuk mencerminkan data baru. Jika kita menggunakan operasi terpisah untuk melakukan kedua 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 sebuah restoran. Transaksi ini akan melakukan beberapa tindakan:

  • Baca peringkat restoran saat ini dan hitung peringkat 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 keseluruhan transaksi. Dalam fungsi onRating() pendengar ditambahkan ke tugas untuk merespons hasil transaksi.

Sekarang Jalankan aplikasinya 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 kini memiliki aplikasi ulasan restoran seluler lokal dan sosial yang dibangun 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 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 melakukan perubahan yang aman. Misalnya pembaruan pada dokumen restoran hanya dapat mengubah peringkat, bukan nama atau data lainnya yang tidak dapat diubah. Peringkat hanya dapat dibuat jika ID pengguna cocok dengan pengguna yang login, sehingga 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-fitur Firestore yang paling penting, termasuk:

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

Belajarlah lagi

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

Aplikasi restoran dalam codelab ini didasarkan pada contoh aplikasi "Makanan Ramah". Anda dapat menelusuri kode sumber untuk aplikasi itu di sini .

Opsional: Penerapan ke produksi

Sejauh ini aplikasi ini hanya menggunakan Firebase Emulator Suite. Jika Anda ingin mempelajari cara men-deploy 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 terdapat di Firebase Emulator Suite. Di bagian ini Anda akan mempelajari cara mengonfigurasi proyek Firebase Anda agar aplikasi ini dapat berfungsi dalam produksi.

Otentikasi Firebase

Di Firebase console, buka bagian Autentikasi 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 pemadam kebakaran

Buat basis data

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

Aturan Penerapan

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 konfirmasi dengan membuka tab Aturan di konsol.

Terapkan Indeks

Aplikasi FriendlyEats memiliki penyortiran dan pemfilteran rumit yang memerlukan sejumlah indeks gabungan khusus. Ini dapat dibuat secara manual di Firebase console, 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 terjadi secara instan, Anda dapat memantau kemajuannya di Firebase console.

Konfigurasikan aplikasi

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