Firebase Android Codelab - สร้างการแชทที่เป็นมิตร

1. ภาพรวม

ภาพหน้าจอ

รูปภาพ: แอพ Working Friendly Chat

ยินดีต้อนรับสู่ Codelab แชทที่เป็นมิตร ใน Codelab นี้ คุณจะได้เรียนรู้วิธีใช้แพลตฟอร์ม Firebase เพื่อสร้างแอปแชทบน Android

สิ่งที่คุณจะได้เรียนรู้

  • วิธีใช้ Firebase Authentication เพื่อให้ผู้ใช้สามารถลงชื่อเข้าใช้ได้
  • วิธีซิงค์ข้อมูลโดยใช้ฐานข้อมูล Firebase Realtime
  • วิธีจัดเก็บไฟล์ไบนารีใน Cloud Storage สำหรับ Firebase
  • วิธีใช้ Firebase Local Emulator Suite เพื่อพัฒนาแอป Android ด้วย Firebase

สิ่งที่คุณต้องการ

  • เวอร์ชัน Android Studio ล่าสุด
  • โปรแกรมจำลอง Android พร้อม Android 5.0+
  • Node.js เวอร์ชัน 10 ขึ้นไป (เพื่อใช้ Emulator Suite)
  • จาวา 8 หรือสูงกว่า ในการติดตั้ง Java ให้ใช้ คำแนะนำ เหล่านี้ เพื่อตรวจสอบเวอร์ชันของคุณ ให้รัน java -version
  • คุ้นเคยกับภาษาโปรแกรม Kotlin

2. รับโค้ดตัวอย่าง

โคลนพื้นที่เก็บข้อมูล

โคลนที่เก็บ GitHub จากบรรทัดคำสั่ง:

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

นำเข้าสู่ Android Studio

ใน Android Studio เลือก File > Open จากนั้นเลือกไดเร็กทอรี build-android-start ( android_studio_folder ) จากไดเร็กทอรีที่คุณดาวน์โหลดโค้ดตัวอย่าง

ตอนนี้คุณควรเปิดโปรเจ็กต์ build-android-start ใน Android Studio แล้ว หากคุณเห็นคำเตือนเกี่ยวกับไฟล์ google-services.json หายไป ไม่ต้องกังวล มันจะถูกเพิ่มในขั้นตอนต่อไป

ตรวจสอบการขึ้นต่อกัน

ใน Codelab นี้ เราได้เพิ่มการขึ้นต่อกันทั้งหมดที่จำเป็นสำหรับคุณแล้ว แต่สิ่งสำคัญคือต้องเข้าใจวิธีเพิ่ม Firebase SDK ลงในแอปของคุณ:

build.gradle.kts

plugins {
    id("com.android.application") version "8.0.0" apply false
    id("com.android.library") version "8.0.0" apply false
    id("org.jetbrains.kotlin.android") version "1.8.20" apply false

    // The google-services plugin is required to parse the google-services.json file
    id("com.google.gms.google-services") version "4.3.15" apply false
}

แอป/build.gradle.kts

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("com.google.gms.google-services")
}

android {
    // ...
}

dependencies {
    // ...

    // Google Sign In SDK
    implementation("com.google.android.gms:play-services-auth:20.5.0")

    // Firebase SDK
    implementation(platform("com.google.firebase:firebase-bom:32.0.0"))
    implementation("com.google.firebase:firebase-database-ktx")
    implementation("com.google.firebase:firebase-storage-ktx")
    implementation("com.google.firebase:firebase-auth-ktx")

    // Firebase UI Library
    implementation("com.firebaseui:firebase-ui-auth:8.0.2")
    implementation("com.firebaseui:firebase-ui-database:8.0.2")
}

3. ติดตั้ง Firebase CLI

ใน Codelab นี้ คุณจะใช้ Firebase Emulator Suite เพื่อจำลอง Firebase Auth, Realtime Database และ Cloud Storage ในเครื่อง สิ่งนี้มอบสภาพแวดล้อมการพัฒนาท้องถิ่นที่ปลอดภัย รวดเร็ว และไม่มีค่าใช้จ่ายในการสร้างแอปของคุณ

ติดตั้ง Firebase CLI

ก่อนอื่นคุณจะต้องติดตั้ง Firebase CLI หากคุณใช้ macOS หรือ Linux คุณสามารถรันคำสั่ง cURL ต่อไปนี้:

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

หากคุณใช้ Windows โปรดอ่าน คำแนะนำในการติดตั้ง เพื่อรับไบนารีแบบสแตนด์อโลนหรือติดตั้งผ่าน npm

เมื่อคุณติดตั้ง CLI แล้ว การรัน firebase --version ควรรายงานเวอร์ชัน 9.0.0 หรือสูงกว่า:

$ firebase --version
9.0.0

เข้าสู่ระบบ

เรียกใช้ firebase login เพื่อเชื่อมต่อ CLI กับบัญชี Google ของคุณ นี่จะเป็นการเปิดหน้าต่างเบราว์เซอร์ใหม่เพื่อเสร็จสิ้นกระบวนการเข้าสู่ระบบ ตรวจสอบให้แน่ใจว่าได้เลือกบัญชีเดียวกับที่คุณใช้เมื่อสร้างโครงการ Firebase ของคุณก่อนหน้านี้

4. เชื่อมต่อกับ Firebase Emulator Suite

เริ่มโปรแกรมจำลอง

ในเทอร์มินัลของคุณ ให้รันคำสั่งต่อไปนี้จากรูทของไดเร็กทอรี codelab-friendlychat-android ในเครื่องของคุณ:

firebase emulators:start --project=demo-friendlychat-android

คุณควรเห็นบันทึกบางอย่างเช่นนี้ ค่าพอร์ตถูกกำหนดไว้ในไฟล์ firebase.json ซึ่งรวมอยู่ในโค้ดตัวอย่างที่คัดลอกมา

$ firebase emulators:start --project=demo-friendlychat-android
i  emulators: Starting emulators: auth, database, storage
i  emulators: Detected demo project ID "demo-friendlychat-android", emulated services will use a demo configuration and attempts to access non-emulated services for this project will fail.
i  database: Database Emulator logging to database-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     │
├────────────────┼────────────────┼────────────────────────────────┤
│ Database       │ localhost:9000 │ http://localhost:4000/database │
├────────────────┼────────────────┼────────────────────────────────┤
│ Storage        │ localhost:9199 │ http://localhost:4000/storage  │
└────────────────┴────────────────┴────────────────────────────────┘
  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.

ไปที่ http://localhost:4000 ในเว็บเบราว์เซอร์ของคุณเพื่อดู Firebase Emulator Suite UI:

หน้าแรกของ Emulator Suite UI

ปล่อยให้ emulators:start ทำงานสำหรับโค้ดแล็บที่เหลือ

เชื่อมต่อแอปของคุณ

ใน Android Studio ให้เปิด MainActivity.kt จากนั้นเพิ่มโค้ดต่อไปนี้ภายในเมธอด onCreate :

// When running in debug mode, connect to the Firebase Emulator Suite.
// "10.0.2.2" is a special IP address which allows the Android Emulator
// to connect to "localhost" on the host computer. The port values (9xxx)
// must match the values defined in the firebase.json file.
if (BuildConfig.DEBUG) {
    Firebase.database.useEmulator("10.0.2.2", 9000)
    Firebase.auth.useEmulator("10.0.2.2", 9099)
    Firebase.storage.useEmulator("10.0.2.2", 9199)
}

5. เรียกใช้แอปเริ่มต้น

เพิ่ม google-services.json

เพื่อให้แอป Android ของคุณเชื่อมต่อกับ Firebase คุณต้องเพิ่มไฟล์ google-services.json ลงในโฟลเดอร์ app ของโปรเจ็กต์ Android ของคุณ เพื่อวัตถุประสงค์ของ Codelab นี้ เราได้จัดเตรียมไฟล์ JSON จำลองซึ่งจะช่วยให้คุณสามารถเชื่อมต่อกับ Firebase Emulator Suite ได้

คัดลอกไฟล์ mock-google-services.json ลงในโฟลเดอร์ build-android-start/app เป็น google-services.json :

cp mock-google-services.json build-android-start/app/google-services.json

ในขั้นตอนสุดท้ายของ Codelab นี้ คุณจะได้เรียนรู้วิธีสร้างโปรเจ็กต์ Firebase จริงและแอป Firebase Android เพื่อให้คุณแทนที่ไฟล์ JSON จำลองนี้ด้วยการกำหนดค่าของคุณเองได้

เรียกใช้แอป

เมื่อคุณได้นำเข้าโปรเจ็กต์ลงใน Android Studio และเพิ่มไฟล์ JSON การกำหนดค่า Firebase แล้ว คุณก็พร้อมที่จะเรียกใช้แอปเป็นครั้งแรก

  1. เริ่มโปรแกรมจำลอง Android ของคุณ
  2. ใน Android Studio คลิก เรียกใช้ ( ดำเนินการ ) ในแถบเครื่องมือ

แอปควรเปิดบน Android Emulator ของคุณ ณ จุดนี้ คุณควรเห็นรายการข้อความว่างเปล่า และการส่งและรับข้อความจะไม่ทำงาน ในขั้นตอนถัดไปของ Codelab นี้ คุณจะต้องตรวจสอบสิทธิ์ผู้ใช้เพื่อให้พวกเขาใช้ Friendly Chat ได้

6. เปิดใช้งานการรับรองความถูกต้อง

แอปนี้จะใช้ฐานข้อมูล Firebase Realtime เพื่อจัดเก็บข้อความแชททั้งหมด ก่อนที่เราจะเพิ่มข้อมูล เราควรตรวจสอบให้แน่ใจว่าแอปนั้นปลอดภัยและมีเพียงผู้ใช้ที่ได้รับการรับรองความถูกต้องเท่านั้นที่สามารถโพสต์ข้อความได้ ในขั้นตอนนี้ เราจะเปิดใช้งาน Firebase Authentication และกำหนดค่ากฎความปลอดภัยของฐานข้อมูลแบบเรียลไทม์

เพิ่มฟังก์ชันการลงชื่อเข้าใช้ขั้นพื้นฐาน

ต่อไป เราจะเพิ่มโค้ดการตรวจสอบสิทธิ์ Firebase พื้นฐานให้กับแอปเพื่อตรวจจับผู้ใช้และใช้หน้าจอลงชื่อเข้าใช้

ตรวจสอบผู้ใช้ปัจจุบัน

ขั้นแรกให้เพิ่มตัวแปรอินสแตนซ์ต่อไปนี้ให้กับคลาส MainActivity.kt :

MainActivity.kt

// Firebase instance variables
private lateinit var auth: FirebaseAuth

ตอนนี้เรามาแก้ไข MainActivity เพื่อส่งผู้ใช้ไปยังหน้าจอลงชื่อเข้าใช้ทุกครั้งที่พวกเขาเปิดแอปและไม่ได้รับการตรวจสอบสิทธิ์ เพิ่มสิ่งต่อไปนี้ให้กับเมธอด onCreate() หลังจากที่ binding เข้ากับมุมมองแล้ว:

MainActivity.kt

// Initialize Firebase Auth and check if the user is signed in
auth = Firebase.auth
if (auth.currentUser == null) {
    // Not signed in, launch the Sign In activity
    startActivity(Intent(this, SignInActivity::class.java))
    finish()
    return
}

เราต้องการตรวจสอบว่าผู้ใช้ลงชื่อเข้าใช้ระหว่าง onStart() :

MainActivity.kt

public override fun onStart() {
    super.onStart()
    // Check if user is signed in.
    if (auth.currentUser == null) {
        // Not signed in, launch the Sign In activity
        startActivity(Intent(this, SignInActivity::class.java))
        finish()
        return
    }
}

จากนั้นใช้เมธอด getUserPhotoUrl() และ getUserName() เพื่อส่งคืนข้อมูลที่เหมาะสมเกี่ยวกับผู้ใช้ Firebase ที่ได้รับการรับรองความถูกต้องในปัจจุบัน:

MainActivity.kt

private fun getPhotoUrl(): String? {
    val user = auth.currentUser
    return user?.photoUrl?.toString()
}

private fun getUserName(): String? {
    val user = auth.currentUser
    return if (user != null) {
        user.displayName
    } else ANONYMOUS
}

จากนั้นใช้เมธอด signOut() เพื่อจัดการปุ่มออกจากระบบ:

MainActivity.kt

private fun signOut() {
    AuthUI.getInstance().signOut()
    startActivity(Intent(this, SignInActivity::class.java))
    finish()
}

ตอนนี้เรามีตรรกะทั้งหมดพร้อมในการส่งผู้ใช้ไปยังหน้าจอลงชื่อเข้าใช้เมื่อจำเป็น ต่อไปเราจำเป็นต้องติดตั้งหน้าจอลงชื่อเข้าใช้เพื่อตรวจสอบสิทธิ์ผู้ใช้อย่างถูกต้อง

ใช้หน้าจอลงชื่อเข้าใช้

เปิดไฟล์ SignInActivity.kt ต่อไปนี้เป็นปุ่มลงชื่อเข้าใช้อย่างง่ายเพื่อเริ่มการตรวจสอบสิทธิ์ ในส่วนนี้ คุณจะใช้ FirebaseUI เพื่อใช้ตรรกะในการลงชื่อเข้าใช้

เพิ่มตัวแปรอินสแตนซ์ Auth ในคลาส SignInActivity ใต้ความคิดเห็น // Firebase instance variables :

SignInActivity.kt

// Firebase instance variables
private lateinit var auth: FirebaseAuth

จากนั้น แก้ไขเมธอด onCreate() เพื่อเริ่มต้น Firebase ในลักษณะเดียวกับที่คุณทำใน MainActivity :

SignInActivity.kt

// Initialize FirebaseAuth
auth = Firebase.auth

เพิ่มฟิลด์ ActivityResultLauncher ไปที่ SignInActivity :

SignInActivity.kt

// ADD THIS
private val signIn: ActivityResultLauncher<Intent> =
        registerForActivityResult(FirebaseAuthUIActivityResultContract(), this::onSignInResult)

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
}

จากนั้น แก้ไขเมธอด onStart() เพื่อเริ่มต้นขั้นตอนการลงชื่อเข้าใช้ FirebaseUI:

SignInActivity.kt

public override fun onStart() {
    super.onStart()

    // If there is no signed in user, launch FirebaseUI
    // Otherwise head to MainActivity
    if (Firebase.auth.currentUser == null) {
        // Sign in with FirebaseUI, see docs for more details:
        // https://firebase.google.com/docs/auth/android/firebaseui
        val signInIntent = AuthUI.getInstance()
                .createSignInIntentBuilder()
                .setLogo(R.mipmap.ic_launcher)
                .setAvailableProviders(listOf(
                        AuthUI.IdpConfig.EmailBuilder().build(),
                        AuthUI.IdpConfig.GoogleBuilder().build(),
                ))
                .build()

        signIn.launch(signInIntent)
    } else {
        goToMainActivity()
    }
}

จากนั้น ใช้เมธอด onSignInResult เพื่อจัดการผลลัพธ์การลงชื่อเข้าใช้ หากการลงชื่อเข้าใช้สำเร็จ ให้ไปที่ MainActivity :

SignInActivity.kt

private fun onSignInResult(result: FirebaseAuthUIAuthenticationResult) {
    if (result.resultCode == RESULT_OK) {
        Log.d(TAG, "Sign in successful!")
        goToMainActivity()
    } else {
        Toast.makeText(
                this,
                "There was an error signing in",
                Toast.LENGTH_LONG).show()

        val response = result.idpResponse
        if (response == null) {
            Log.w(TAG, "Sign in canceled")
        } else {
            Log.w(TAG, "Sign in error", response.error)
        }
    }
}

แค่นั้นแหละ! คุณได้ใช้การรับรองความถูกต้องกับ FirebaseUI ในการเรียกใช้เมธอดเพียงไม่กี่ครั้ง และไม่จำเป็นต้องจัดการการกำหนดค่าฝั่งเซิร์ฟเวอร์

ทดสอบงานของคุณ

เรียกใช้แอปบน Android Emulator ของคุณ คุณควรจะถูกส่งไปยังหน้าจอลงชื่อเข้าใช้ทันที แตะปุ่ม ลงชื่อเข้าใช้ด้วยอีเมล จากนั้นสร้างบัญชี หากทุกอย่างถูกต้อง คุณควรจะถูกส่งไปยังหน้าจอข้อความ

หลังจากลงชื่อเข้าใช้แล้ว ให้เปิด Firebase Emulator Suite UI ในเบราว์เซอร์ของคุณ จากนั้นคลิกแท็บ การตรวจสอบสิทธิ์ เพื่อดูบัญชีผู้ใช้ที่ลงชื่อเข้าใช้บัญชีแรกนี้

7. อ่านข้อความ

ในขั้นตอนนี้ เราจะเพิ่มฟังก์ชันในการอ่านและแสดงข้อความที่จัดเก็บไว้ในฐานข้อมูลเรียลไทม์

นำเข้าข้อความตัวอย่าง

  1. ใน Firebase Emulator Suite UI ให้เลือกแท็บ ฐานข้อมูลเรียลไทม์
  2. ลากและวางไฟล์ initial_messages.json จากสำเนาในพื้นที่เก็บข้อมูล Codelab ในเครื่องของคุณลงในโปรแกรมดูข้อมูล

ขณะนี้คุณควรมีข้อความบางส่วนภายใต้โหนด messages ของฐานข้อมูล

อ่านข้อมูล

ประสานข้อความ

ในส่วนนี้เราจะเพิ่มโค้ดที่ซิงโครไนซ์ข้อความที่เพิ่มใหม่ไปยัง UI ของแอปโดย:

  • การเริ่มต้นฐานข้อมูล Firebase Realtime และเพิ่ม Listener เพื่อจัดการกับการเปลี่ยนแปลงที่เกิดขึ้นกับข้อมูล
  • การอัปเดตอะแดปเตอร์ RecyclerView เพื่อให้ข้อความใหม่ปรากฏขึ้น
  • การเพิ่มตัวแปรอินสแตนซ์ฐานข้อมูลพร้อมกับตัวแปรอินสแตนซ์ Firebase อื่นๆ ของคุณในคลาส MainActivity :

MainActivity.kt

// Firebase instance variables
// ...
private lateinit var db: FirebaseDatabase
private lateinit var adapter: FriendlyMessageAdapter

แก้ไขเมธอด onCreate() ของ MainActivity ใต้ความคิดเห็น // Initialize Realtime Database and FirebaseRecyclerAdapter ด้วยโค้ดที่กำหนดไว้ด้านล่าง รหัสนี้จะเพิ่มข้อความที่มีอยู่ทั้งหมดจากฐานข้อมูลเรียลไทม์ จากนั้นรับฟังรายการลูกใหม่ภายใต้เส้นทาง messages ในฐานข้อมูลเรียลไทม์ Firebase ของคุณ โดยจะเพิ่มองค์ประกอบใหม่ให้กับ UI สำหรับแต่ละข้อความ:

MainActivity.kt

// Initialize Realtime Database
db = Firebase.database
val messagesRef = db.reference.child(MESSAGES_CHILD)

// The FirebaseRecyclerAdapter class and options come from the FirebaseUI library
// See: https://github.com/firebase/FirebaseUI-Android
val options = FirebaseRecyclerOptions.Builder<FriendlyMessage>()
    .setQuery(messagesRef, FriendlyMessage::class.java)
    .build()
adapter = FriendlyMessageAdapter(options, getUserName())
binding.progressBar.visibility = ProgressBar.INVISIBLE
manager = LinearLayoutManager(this)
manager.stackFromEnd = true
binding.messageRecyclerView.layoutManager = manager
binding.messageRecyclerView.adapter = adapter

// Scroll down when a new message arrives
// See MyScrollToBottomObserver for details
adapter.registerAdapterDataObserver(
    MyScrollToBottomObserver(binding.messageRecyclerView, adapter, manager)
)

ถัดไปในคลาส FriendlyMessageAdapter.kt ใช้วิธี bind() ภายในคลาสภายใน MessageViewHolder() :

FriendlyMessageAdapter.kt

inner class MessageViewHolder(private val binding: MessageBinding) : ViewHolder(binding.root) {
    fun bind(item: FriendlyMessage) {
        binding.messageTextView.text = item.text
        setTextColor(item.name, binding.messageTextView)

        binding.messengerTextView.text = if (item.name == null) ANONYMOUS else item.name
        if (item.photoUrl != null) {
            loadImageIntoView(binding.messengerImageView, item.photoUrl!!)
        } else {
            binding.messengerImageView.setImageResource(R.drawable.ic_account_circle_black_36dp)
        }
    }
    ...
}

นอกจากนี้เรายังจำเป็นต้องแสดงข้อความที่เป็นรูปภาพด้วย ดังนั้นจึงใช้เมธอด bind() ภายในคลาสภายใน ImageMessageViewHolder() :

FriendlyMessageAdapter.kt

inner class ImageMessageViewHolder(private val binding: ImageMessageBinding) :
    ViewHolder(binding.root) {
    fun bind(item: FriendlyMessage) {
        loadImageIntoView(binding.messageImageView, item.imageUrl!!)

        binding.messengerTextView.text = if (item.name == null) ANONYMOUS else item.name
        if (item.photoUrl != null) {
            loadImageIntoView(binding.messengerImageView, item.photoUrl!!)
        } else {
            binding.messengerImageView.setImageResource(R.drawable.ic_account_circle_black_36dp)
        }
    }
}

สุดท้าย กลับมาที่ MainActivity เริ่มและหยุดฟังการอัปเดตจาก Firebase Realtime Database อัพเดตเมธอด onPause() และ onResume() ใน MainActivity ดังที่แสดงด้านล่าง:

MainActivity.kt

public override fun onPause() {
    adapter.stopListening()
    super.onPause()
}

public override fun onResume() {
    super.onResume()
    adapter.startListening()
}

ทดสอบการซิงค์ข้อความ

  1. คลิก เรียกใช้ ( ดำเนินการ ).
  2. ใน Emulator Suite UI ให้กลับไปที่แท็บ Realtime Database จากนั้นเพิ่มข้อความใหม่ด้วยตนเอง ยืนยันว่าข้อความปรากฏในแอป Android ของคุณ:

ยินดีด้วย คุณเพิ่งเพิ่มฐานข้อมูลเรียลไทม์ให้กับแอปของคุณ!

8. ส่งข้อความ

ดำเนินการส่งข้อความ

ในส่วนนี้ คุณจะเพิ่มความสามารถสำหรับผู้ใช้แอปในการส่งข้อความ ข้อมูลโค้ดด้านล่างจะรับฟังเหตุการณ์การคลิกบนปุ่มส่ง สร้างออบเจ็กต์ FriendlyMessage ใหม่พร้อมเนื้อหาของฟิลด์ข้อความ และส่งข้อความไปยังฐานข้อมูล วิธีการ push() จะเพิ่ม ID ที่สร้างขึ้นโดยอัตโนมัติให้กับเส้นทางของวัตถุที่ถูกผลัก รหัสเหล่านี้เป็นไปตามลำดับเพื่อให้แน่ใจว่าข้อความใหม่จะถูกเพิ่มที่ส่วนท้ายของรายการ

อัปเดตตัวฟังการคลิกของปุ่มส่งในเมธอด onCreate() ในคลาส MainActivity โค้ดนี้อยู่ที่ด้านล่างของเมธอด onCreate() อยู่แล้ว อัปเดตเนื้อหา onClick() ให้ตรงกับโค้ดด้านล่าง:

MainActivity.kt

// Disable the send button when there's no text in the input field
// See MyButtonObserver for details
binding.messageEditText.addTextChangedListener(MyButtonObserver(binding.sendButton))

// When the send button is clicked, send a text message
binding.sendButton.setOnClickListener {
    val friendlyMessage = FriendlyMessage(
        binding.messageEditText.text.toString(),
        getUserName(),
        getPhotoUrl(),
        null /* no image */
    )
    db.reference.child(MESSAGES_CHILD).push().setValue(friendlyMessage)
    binding.messageEditText.setText("")
}

ใช้การส่งข้อความรูปภาพ

ในส่วนนี้ คุณจะเพิ่มความสามารถสำหรับผู้ใช้แอปในการส่งข้อความรูปภาพ การสร้างข้อความรูปภาพทำได้ด้วยขั้นตอนเหล่านี้:

  • เลือกรูปภาพ
  • จัดการการเลือกรูปภาพ
  • เขียนข้อความรูปภาพชั่วคราวไปยังฐานข้อมูลเรียลไทม์
  • เริ่มอัปโหลดภาพที่เลือก
  • อัปเดต URL ข้อความรูปภาพเป็นรูปภาพที่อัปโหลด เมื่อการอัปโหลดเสร็จสิ้น

เลือกรูปภาพ

หากต้องการเพิ่มรูปภาพ Codelab นี้จะใช้ Cloud Storage for Firebase Cloud Storage เป็นสถานที่ที่ดีในการจัดเก็บข้อมูลไบนารีของแอปของคุณ

จัดการการเลือกรูปภาพและเขียนข้อความชั่วคราว

เมื่อผู้ใช้เลือกรูปภาพแล้ว Intent ในการเลือกรูปภาพจะเริ่มขึ้น สิ่งนี้ถูกนำไปใช้แล้วในโค้ดที่ส่วนท้ายของเมธอด onCreate() เมื่อเสร็จแล้วจะเรียกเมธอด onImageSelected() ของ MainActivity เมื่อใช้ข้อมูลโค้ดด้านล่างนี้ คุณจะเขียนข้อความพร้อม URL รูปภาพชั่วคราวไปยังฐานข้อมูลที่ระบุว่ารูปภาพกำลังถูกอัปโหลด

MainActivity.kt

private fun onImageSelected(uri: Uri) {
    Log.d(TAG, "Uri: $uri")
    val user = auth.currentUser
    val tempMessage = FriendlyMessage(null, getUserName(), getPhotoUrl(), LOADING_IMAGE_URL)
    db.reference
            .child(MESSAGES_CHILD)
            .push()
            .setValue(
                    tempMessage,
                    DatabaseReference.CompletionListener { databaseError, databaseReference ->
                        if (databaseError != null) {
                            Log.w(
                                    TAG, "Unable to write message to database.",
                                    databaseError.toException()
                            )
                            return@CompletionListener
                        }

                        // Build a StorageReference and then upload the file
                        val key = databaseReference.key
                        val storageReference = Firebase.storage
                                .getReference(user!!.uid)
                                .child(key!!)
                                .child(uri.lastPathSegment!!)
                        putImageInStorage(storageReference, uri, key)
                    })
}

อัปโหลดรูปภาพและอัปเดตข้อความ

เพิ่มเมธอด putImageInStorage() ให้กับ MainActivity มันถูกเรียกใน onImageSelected() เพื่อเริ่มต้นการอัพโหลดรูปภาพที่เลือก เมื่อการอัปโหลดเสร็จสิ้น คุณจะอัปเดตข้อความเพื่อใช้รูปภาพที่เหมาะสม

MainActivity.kt

private fun putImageInStorage(storageReference: StorageReference, uri: Uri, key: String?) {
    // First upload the image to Cloud Storage
    storageReference.putFile(uri)
        .addOnSuccessListener(
            this
        ) { taskSnapshot -> // After the image loads, get a public downloadUrl for the image
            // and add it to the message.
            taskSnapshot.metadata!!.reference!!.downloadUrl
                .addOnSuccessListener { uri ->
                    val friendlyMessage =
                        FriendlyMessage(null, getUserName(), getPhotoUrl(), uri.toString())
                    db.reference
                        .child(MESSAGES_CHILD)
                        .child(key!!)
                        .setValue(friendlyMessage)
                }
        }
        .addOnFailureListener(this) { e ->
            Log.w(
                TAG,
                "Image upload task was unsuccessful.",
                e
            )
        }
}

ทดสอบการส่งข้อความ

  1. ใน Android Studio ให้คลิกที่ ดำเนินการ ปุ่ม เรียกใช้
  2. ใน Android Emulator ให้ป้อนข้อความ จากนั้นแตะปุ่มส่ง ข้อความใหม่ควรปรากฏใน UI ของแอปและใน UI ของ Firebase Emulator Suite
  3. ใน Android Emulator ให้แตะรูปภาพ "+" เพื่อเลือกรูปภาพจากอุปกรณ์ของคุณ ข้อความใหม่ควรปรากฏให้เห็นก่อนด้วยรูปภาพตัวยึดตำแหน่ง จากนั้นจึงมองเห็นด้วยรูปภาพที่เลือกเมื่อการอัปโหลดรูปภาพเสร็จสมบูรณ์ ข้อความใหม่ควรมองเห็นได้ใน Emulator Suite UI โดยเฉพาะเป็นออบเจ็กต์ในแท็บ Realtime Database และเป็นหยดในแท็บ Storage

9. ขอแสดงความยินดี!

คุณเพิ่งสร้างแอปพลิเคชันแชทแบบเรียลไทม์โดยใช้ Firebase!

สิ่งที่คุณได้เรียนรู้

  • การรับรองความถูกต้องของ Firebase
  • ฐานข้อมูลเรียลไทม์ Firebase
  • ที่เก็บข้อมูลบนคลาวด์สำหรับ Firebase

ต่อไป ลองใช้สิ่งที่คุณเรียนรู้ใน Codelab นี้เพื่อเพิ่ม Firebase ลงในแอป Android ของคุณเอง หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ Firebase โปรดไปที่ firebase.google.com

หากคุณต้องการเรียนรู้วิธีตั้งค่าโปรเจ็กต์ Firebase จริง และใช้ทรัพยากร Firebase จริง (แทนที่จะเป็นโปรเจ็กต์สาธิตและ เฉพาะ ทรัพยากรที่จำลองเท่านั้น) ให้ทำตามขั้นตอนถัดไป

หมายเหตุ: แม้หลังจากที่คุณตั้งค่าโปรเจ็กต์ Firebase จริงแล้ว และ โดยเฉพาะอย่างยิ่ง เมื่อคุณเริ่มสร้างแอปจริง เราขอแนะนำให้ใช้ Firebase Local Emulator Suite สำหรับการพัฒนาและการทดสอบ

10. ไม่บังคับ: สร้างและตั้งค่าโปรเจ็กต์ Firebase

ในขั้นตอนนี้ คุณจะสร้างโปรเจ็กต์ Firebase จริงและแอป Firebase Android เพื่อใช้กับ Codelab นี้ นอกจากนี้คุณยังจะเพิ่มการกำหนดค่า Firebase เฉพาะแอปลงในแอปของคุณด้วย และสุดท้าย คุณจะต้องตั้งค่าทรัพยากร Firebase จริงเพื่อใช้กับแอปของคุณ

สร้างโปรเจ็กต์ Firebase

  1. ในเบราว์เซอร์ของคุณ ให้ไปที่ คอนโซล Firebase
  2. เลือก เพิ่มโครงการ
  3. เลือกหรือป้อนชื่อโครงการ คุณสามารถใช้ชื่อใดก็ได้ที่คุณต้องการ
  4. คุณไม่จำเป็นต้องใช้ Google Analytics สำหรับ Codelab นี้ คุณจึงสามารถข้ามการเปิดใช้งานสำหรับโปรเจ็กต์ของคุณได้
  5. คลิก สร้างโครงการ เมื่อโครงการของคุณพร้อม คลิก ดำเนินการต่อ

เพิ่ม Firebase ในโครงการ Android ของคุณ

ก่อนที่คุณจะเริ่มขั้นตอนนี้ ให้รับแฮช SHA1 ของแอปของคุณ เรียกใช้คำสั่งต่อไปนี้จากไดเรกทอรี build-android-start ในเครื่องของคุณเพื่อกำหนด SHA1 ของคีย์การแก้ไขข้อบกพร่องของคุณ:

./gradlew signingReport

Store: /Users/<username>/.android/debug.keystore
Alias: AndroidDebugKey
MD5: A5:88:41:04:8F:06:59:6A:AE:33:76:87:AA:AD:19:23
SHA1: A7:89:F5:06:A8:07:A1:22:EC:90:6A:A6:EA:C3:D4:8B:3A:30:AB:18
SHA-256: 05:A2:2A:35:EE:F2:51:23:72:4D:72:67:A5:6A:8A:58:22:2C:00:A6:AB:F6:45:D5:A1:82:D8:90:A4:69:C8:FE
Valid until: Wednesday, August 10, 2044

คุณควรเห็นผลลัพธ์บางอย่างเหมือนข้างต้น บรรทัดสำคัญคือแฮช SHA1 หากคุณไม่พบแฮช SHA1 ของคุณ โปรดดูข้อมูลเพิ่มเติม ในหน้านี้

กลับไปที่คอนโซล Firebase และทำตามขั้นตอนเหล่านี้เพื่อลงทะเบียนโปรเจ็กต์ Android ของคุณกับโปรเจ็กต์ Firebase ของคุณ:

  1. จากหน้าจอภาพรวมของโปรเจ็กต์ใหม่ของคุณ ให้คลิกไอคอน Android เพื่อเปิดเวิร์กโฟลว์การตั้งค่า: เพิ่มแอพ Android
  2. ในหน้าจอถัดไป ให้ป้อน com.google.firebase.codelab.friendlychat เป็นชื่อแพ็คเกจสำหรับแอปของคุณ
  3. คลิก ลงทะเบียนแอป จากนั้นคลิก ดาวน์โหลด google-services.json เพื่อดาวน์โหลดไฟล์การกำหนดค่า Firebase
  4. คัดลอกไฟล์ google-services.json ลงในไดเรกทอรี app ของโครงการ Android ของคุณ
  5. ข้าม ขั้นตอนถัดไปที่แสดงในเวิร์กโฟลว์การตั้งค่าของคอนโซล (ขั้นตอนเหล่านี้ได้ดำเนินการให้คุณแล้วในโปรเจ็กต์ build-android-start )
  6. ตรวจสอบให้แน่ใจว่าแอปของคุณมีการอ้างอิงทั้งหมดได้โดยการซิงค์โปรเจ็กต์ของคุณกับไฟล์ Gradle จากแถบเครื่องมือ Android Studio ให้เลือก ไฟล์ > ซิงค์โปรเจ็กต์ด้วยไฟล์ Gradle คุณอาจต้องรัน Build/Clean Project และ Build/Rebuild Project เพื่อให้การเปลี่ยนแปลงการกำหนดค่าเกิดขึ้น

กำหนดค่าการตรวจสอบสิทธิ์ Firebase

ก่อนที่แอปของคุณจะสามารถเข้าถึง Firebase Authentication API ในนามของผู้ใช้ได้ คุณต้องเปิดใช้งาน Firebase Authentication และผู้ให้บริการลงชื่อเข้าใช้ที่คุณต้องการใช้ในแอปของคุณก่อน

  1. ใน คอนโซล Firebase ให้เลือก การตรวจสอบสิทธิ์ จากแผงนำทางด้านซ้าย
  2. เลือกแท็บ วิธีการลงชื่อเข้า ใช้
  3. คลิก อีเมล/รหัสผ่าน จากนั้นสลับสวิตช์เป็นเปิดใช้งาน (สีน้ำเงิน)
  4. คลิก Google จากนั้นสลับสวิตช์เป็นเปิดใช้งาน (สีน้ำเงิน) และตั้งค่าอีเมลสนับสนุนโครงการ

หากคุณได้รับข้อผิดพลาดในภายหลังใน Codelab นี้โดยมีข้อความ "CONFIGURATION_NOT_FOUND" โปรดกลับมาที่ขั้นตอนนี้และตรวจสอบงานของคุณอีกครั้ง

กำหนดค่าฐานข้อมูลเรียลไทม์

แอปใน Codelab นี้จัดเก็บข้อความแชทในฐานข้อมูลเรียลไทม์ของ Firebase ในส่วนนี้ เราจะสร้างฐานข้อมูลและกำหนดค่าความปลอดภัยผ่านภาษาการกำหนดค่า JSON ที่เรียกว่ากฎความปลอดภัยของ Firebase

  1. ใน คอนโซล Firebase ให้เลือก ฐานข้อมูลเรียลไทม์ จากแผงนำทางด้านซ้าย
  2. คลิก สร้างฐานข้อมูล เพื่อสร้างอินสแตนซ์ฐานข้อมูลเรียลไทม์ใหม่ เมื่อได้รับแจ้ง ให้เลือกภูมิภาค us-central1 จากนั้นคลิก ถัดไป
  3. เมื่อได้รับแจ้งเกี่ยวกับกฎความปลอดภัย ให้เลือก โหมดล็อค จากนั้นคลิก เปิดใช้งาน
  4. เมื่อสร้างอินสแตนซ์ฐานข้อมูลแล้ว ให้เลือกแท็บ กฎ จากนั้นอัปเดตการกำหนดค่ากฎดังนี้:
     {
       "rules": {
         "messages": {
           ".read": "auth.uid != null",
           ".write": "auth.uid != null"
         }
       }
     }
    

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของกฎความปลอดภัย (รวมถึงเอกสารประกอบเกี่ยวกับตัวแปร "auth") โปรดดู เอกสารประกอบการรักษาความปลอดภัยของฐานข้อมูลเรียลไทม์

กำหนดค่า Cloud Storage สำหรับ Firebase

  1. ใน คอนโซล Firebase ให้เลือก ที่เก็บข้อมูล จากแผงการนำทางด้านซ้าย
  2. คลิก เริ่มต้น เพื่อเปิดใช้ Cloud Storage สำหรับโปรเจ็กต์ของคุณ
  3. ทำตามขั้นตอนในกล่องโต้ตอบเพื่อตั้งค่าที่เก็บข้อมูลโดยใช้ค่าเริ่มต้นที่แนะนำ

เชื่อมต่อกับทรัพยากร Firebase

ในขั้นตอนก่อนหน้าของ Codelab นี้ คุณได้เพิ่มสิ่งต่อไปนี้ใน MainActivity.kt บล็อกแบบมีเงื่อนไขนี้เชื่อมต่อโปรเจ็กต์ Android ของคุณกับ Firebase Emulator Suite

// REMOVE OR DISABLE THIS
if (BuildConfig.DEBUG) {
    Firebase.database.useEmulator("10.0.2.2", 9000)
    Firebase.auth.useEmulator("10.0.2.2", 9099)
    Firebase.storage.useEmulator("10.0.2.2", 9199)
}

หากคุณต้องการเชื่อมต่อแอปของคุณกับโปรเจ็กต์ Firebase จริง ใหม่และทรัพยากร Firebase จริง ของโปรเจ็กต์ คุณสามารถลบบล็อกนี้ออกหรือเรียกใช้แอปในโหมด Release เพื่อให้ BuildConfig.DEBUG เป็น false