Firebase Android Codelab – פיתוח Friendly Chat

1. סקירה כללית

צילום מסך

תמונה: אפליקציית Friendly Chat פועלת.

ברוכים הבאים לסדנת הקוד Friendly Chat. ב-codelab הזה נסביר איך להשתמש בפלטפורמת Firebase כדי ליצור אפליקציית צ'אט ב-Android.

מה תלמדו

  • איך משתמשים באימות ב-Firebase כדי לאפשר למשתמשים להיכנס לחשבון.
  • איך מסנכרנים נתונים באמצעות Firebase Realtime Database.
  • איך מאחסנים קבצים בינאריים ב-Cloud Storage for Firebase.
  • איך משתמשים בכלים לאמולטור מקומי ב-Firebase כדי לפתח אפליקציה ל-Android עם Firebase.

מה צריך להכין

  • הגרסה האחרונה של Android Studio.
  • אמולטור Android עם Android מגרסה 5.0 ואילך.
  • ‫Node.js גרסה 10 ואילך (כדי להשתמש ב-Emulator Suite).
  • ‫Java 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
}

app/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 כדי להפעיל אמולציה מקומית של 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:

דף הבית של ממשק המשתמש של כלים לאמולטור

משאירים את הפקודה emulators:start פועלת למשך שאר ה-codelab.

קישור האפליקציה

ב-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 ואפליקציית Android אמיתית ב-Firebase, כדי שתוכלו להחליף את קובץ ה-JSON המדומה הזה בהגדרה משלכם.

הפעלת האפליקציה

אחרי שייבאתם את הפרויקט ל-Android Studio והוספתם קובץ JSON של הגדרות Firebase, אתם יכולים להריץ את האפליקציה בפעם הראשונה.

  1. מפעילים את Android Emulator.
  2. ב-Android Studio, לוחצים על Run (הפעלה) ( להריץ) בסרגל הכלים.

האפליקציה אמורה להיפתח ב-Android Emulator. בשלב הזה, רשימת ההודעות אמורה להיות ריקה, ולא תהיה אפשרות לשלוח ולקבל הודעות. בשלב הבא של ה-codelab הזה, תאמתו משתמשים כדי שיוכלו להשתמש ב-Friendly Chat.

6. הפעלת אימות

האפליקציה הזו תשתמש ב-Firebase Realtime Database כדי לאחסן את כל ההודעות בצ'אט. לפני שנוסיף נתונים, נבדוק שהאפליקציה מאובטחת ורק משתמשים מאומתים יכולים לפרסם הודעות. בשלב הזה נפעיל את Firebase Authentication ונגדיר את כללי האבטחה של Realtime Database.

הוספת פונקציונליות בסיסית של כניסה לחשבון

בשלב הבא נוסיף לאפליקציה קוד בסיסי של Firebase Authentication כדי לזהות משתמשים ולהטמיע מסך כניסה.

בדיקה של המשתמש הנוכחי

קודם מוסיפים את משתנה המופע הבא למחלקה 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() method כדי לטפל בלחצן היציאה:

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

לאחר מכן, עורכים את ה-method‏ 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. תועברו באופן מיידי למסך הכניסה. מקישים על הלחצן כניסה באמצעות אימייל ויוצרים חשבון. אם הכל הוטמע בצורה נכונה, תועברו למסך ההודעות.

אחרי שנכנסים לחשבון, פותחים את ממשק המשתמש של Firebase Emulator Suite בדפדפן ולוחצים על הכרטיסייה אימות כדי לראות את חשבון המשתמש הראשון שנכנס.

7. קריאת ההודעות

בשלב הזה, נוסיף פונקציונליות לקריאה ולהצגה של הודעות שמאוחסנות ב-Realtime Database.

ייבוא הודעות לדוגמה

  1. בממשק המשתמש של Firebase Emulator Suite, בוחרים בכרטיסייה מסד נתונים בזמן אמת.
  2. גוררים את הקובץ initial_messages.json מהעותק המקומי של מאגר ה-codelab אל כלי הצגת הנתונים.

עכשיו אמורות להופיע כמה הודעות בצומת messages של מסד הנתונים.

קריאת נתונים

סנכרון הודעות

בקטע הזה אנחנו מוסיפים קוד שמסנכרן הודעות שנוספו לאחרונה לממשק המשתמש של האפליקציה, באמצעות:

  • הפעלה ראשונית של מסד הנתונים בזמן אמת ב-Firebase והוספה של מאזין לטיפול בשינויים שבוצעו בנתונים.
  • עדכון המתאם של RecyclerView כדי שההודעות החדשות יוצגו.
  • מוסיפים את משתני מופע מסד הנתונים עם משתני מופע Firebase האחרים ב-MainActivity class:

MainActivity.kt

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

משנים את השיטה onCreate() של MainActivity מתחת להערה // Initialize Realtime Database and FirebaseRecyclerAdapter באמצעות הקוד שמוגדר בהמשך. הקוד הזה מוסיף את כל ההודעות הקיימות מ-Realtime Database ואז מאזין לרשומות צאצא חדשות בנתיב messages ב-Firebase Realtime Database. לכל הודעה מתווסף רכיב חדש לממשק המשתמש:

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, חוזרים לכרטיסייה Realtime Database ומוסיפים ידנית הודעה חדשה. מוודאים שההודעה מופיעה באפליקציית Android:

חדשות טובות – הוספתם לאפליקציה שלכם מסד נתונים בזמן אמת!

8. שליחת הודעות

הטמעה של שליחת הודעות טקסט

בקטע הזה מוסיפים למשתמשי האפליקציה את האפשרות לשלוח הודעות טקסט. קטע הקוד שבהמשך מאזין לאירועי לחיצה על לחצן השליחה, יוצר אובייקט FriendlyMessage חדש עם התוכן של שדה ההודעה ומעביר את ההודעה למסד הנתונים. השיטה push() מוסיפה מזהה שנוצר באופן אוטומטי לנתיב של האובייקט שנדחף. המזהים האלה הם עוקבים, ולכן ההודעות החדשות יתווספו לסוף הרשימה.

מעדכנים את מאזין הקליקים של לחצן השליחה בשיטה 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 של הודעת התמונה לכתובת של התמונה שהועלתה

בחירת תמונה

בשיעור הזה משתמשים ב-Cloud Storage for Firebase כדי להוסיף תמונות. ‫Cloud Storage הוא מקום טוב לאחסון הנתונים הבינאריים של האפליקציה.

בחירת תמונה לכינוי וכתיבת הודעה זמנית

אחרי שהמשתמש בוחר תמונה, נפתח הכלי לבחירת תמונות Intent. ההגדרה הזו כבר מיושמת בקוד בסוף השיטה onCreate(). בסיום, הפונקציה קוראת ל-method‏ 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, לוחצים על הלחצן להריץRun (הפעלה).
  2. ב-Android Emulator, כותבים את ההודעה ומקישים על לחצן השליחה. ההודעה החדשה אמורה להיות גלויה בממשק המשתמש של האפליקציה ובממשק המשתמש של Firebase Emulator Suite.
  3. ב-Android Emulator, מקישים על התמונה עם הסימן '+' כדי לבחור תמונה מהמכשיר. ההודעה החדשה אמורה להופיע ראשונה עם תמונה של placeholder, ואז עם התמונה שנבחרה אחרי שההעלאה של התמונה תושלם. ההודעה החדשה אמורה להופיע גם בממשק המשתמש של Emulator Suite, באופן ספציפי כאובייקט בכרטיסייה Realtime Database וכ-blob בכרטיסייה Storage.

9. כל הכבוד!

הרגע יצרתם אפליקציית צ'אט בזמן אמת באמצעות Firebase!

מה למדתם

  • אימות ב-Firebase
  • מסד נתונים בזמן אמת ב-Firebase
  • Cloud Storage for Firebase

אחרי כן, נסו להשתמש במה שלמדתם ב-codelab הזה כדי להוסיף את Firebase לאפליקציית Android משלכם. מידע נוסף על Firebase זמין בכתובת firebase.google.com.

אם אתם רוצים ללמוד איך להגדיר פרויקט Firebase אמיתי ולהשתמש במשאבי Firebase אמיתיים (במקום בפרויקט הדגמה ובמשאבים מדומיים בלבד), המשיכו לשלב הבא.

הערה: גם אחרי שתגדירו פרויקט Firebase אמיתי, ובמיוחד כשמתחילים לפתח אפליקציה אמיתית, מומלץ להשתמש בחבילת הכלים לאמולטור מקומי ב-Firebase לצורך פיתוח ובדיקה.

10. אופציונלי: יצירה והגדרה של פרויקט Firebase

בשלב הזה תיצרו פרויקט אמיתי ב-Firebase ואפליקציית Android ב-Firebase לשימוש בסדנת התכנות הזו. בנוסף, תוסיפו לאפליקציה את ההגדרה של Firebase שספציפית לאפליקציה. ולבסוף, תגדירו משאבי Firebase אמיתיים לשימוש באפליקציה.

יצירת פרויקט Firebase

  1. נכנסים למסוף Firebase באמצעות חשבון Google.
  2. לוחצים על הלחצן כדי ליצור פרויקט חדש, ואז מזינים שם לפרויקט (לדוגמה, FriendlyChat).
  3. לוחצים על המשך.
  4. אם מוצגת בקשה לעשות זאת, קוראים ומאשרים את התנאים של Firebase, ואז לוחצים על המשך.
  5. (אופציונלי) מפעילים את העזרה מבוססת-AI במסוף Firebase (שנקראת Gemini ב-Firebase).
  6. ב-codelab הזה לא צריך להשתמש ב-Google Analytics, ולכן משביתים את האפשרות Google Analytics.
  7. לוחצים על יצירת פרויקט, מחכים שהפרויקט יוקצה ולוחצים על המשך.

שדרוג תוכנית התמחור של Firebase

כדי להשתמש ב-Cloud Storage for Firebase, הפרויקט ב-Firebase צריך להיות בתוכנית התמחור 'תשלום לפי שימוש' (Blaze), כלומר הוא צריך להיות מקושר לחשבון לחיוב ב-Cloud.

  • בחשבון לחיוב ב-Cloud צריך להגדיר אמצעי תשלום, כמו כרטיס אשראי.
  • אם אתם חדשים ב-Firebase וב-Google Cloud, כדאי לבדוק אם אתם עומדים בדרישות לקבלת קרדיט בסך 300$וחשבון לחיוב ב-Cloud עם תקופת ניסיון בחינם.
  • אם אתם משתתפים בסדנת קוד כחלק מאירוע, כדאי לשאול את מארגן האירוע אם יש קרדיטים ל-Cloud.

כדי לשדרג את הפרויקט לתוכנית Blaze, פועלים לפי השלבים הבאים:

  1. במסוף Firebase, בוחרים באפשרות שדרוג התוכנית.
  2. בוחרים בתוכנית Blaze. פועלים לפי ההוראות במסך כדי לקשר חשבון לחיוב ב-Cloud לפרויקט.
    אם הייתם צריכים ליצור חשבון לחיוב ב-Cloud כחלק מהשדרוג, יכול להיות שתצטרכו לחזור לתהליך השדרוג במסוף Firebase כדי להשלים את השדרוג.

הוספת Firebase לפרויקט Android

לפני שמתחילים בשלב הזה, צריך לקבל את גיבוב ה-SHA1 של האפליקציה. כדי לקבוע את ה-SHA1 של מפתח הניפוי באגים, מריצים את הפקודה הבאה מהספרייה המקומית build-android-start:

./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. לוחצים על Register App (רישום האפליקציה) ואז על Download google-services.json (הורדת קובץ google-services.json) כדי להוריד את קובץ ההגדרות של Firebase.
  4. מעתיקים את הקובץ google-services.json לספרייה app של פרויקט Android.
  5. מדלגים על השלבים הבאים שמוצגים בתהליך ההגדרה במסוף (הם כבר בוצעו בשבילכם בפרויקט build-android-start).
  6. כדי לוודא שכל התלויות זמינות לאפליקציה, מסנכרנים את הפרויקט עם קובצי Gradle. בסרגל הכלים של Android Studio, בוחרים באפשרות File (קובץ) > Sync Project with Gradle Files (סנכרון הפרויקט עם קובצי Gradle). יכול להיות שיהיה צורך להריץ גם את Build/Clean Project וגם את Build/Rebuild Project כדי שהשינויים בהגדרות ייכנסו לתוקף.

הגדרת אימות ב-Firebase

כדי שהאפליקציה תוכל לגשת לממשקי ה-API של אימות ב-Firebase בשם המשתמשים, צריך להפעיל את האימות ב-Firebase ואת ספקי הכניסה שרוצים להשתמש בהם באפליקציה.

  1. במסוף Firebase, בוחרים באפשרות אימות בחלונית הניווט שמימין.
  2. בוחרים בכרטיסייה שיטת הכניסה.
  3. לוחצים על אימייל/סיסמה ומעבירים את המתג למצב מופעל (כחול).
  4. לוחצים על Google, מעבירים את המתג למצב מופעל (כחול) ומגדירים כתובת אימייל לתמיכה בפרויקט.

אם בהמשך תופיע שגיאה עם ההודעה CONFIGURATION_NOT_FOUND, צריך לחזור לשלב הזה ולבדוק שוב את העבודה.

הגדרה של מסד נתונים בזמן אמת

האפליקציה ב-codelab הזה מאחסנת הודעות צ'אט ב-Firebase Realtime Database. בקטע הזה ניצור מסד נתונים ונגדיר את האבטחה שלו באמצעות שפת הגדרות JSON שנקראת כללי אבטחה של Firebase.

  1. בחלונית הימנית במסוף Firebase, מרחיבים את Build ובוחרים באפשרות Realtime Database.
  2. לוחצים על יצירת מסד נתונים.
  3. בוחרים מיקום למסד הנתונים ולוחצים על הבא.
    באפליקציה אמיתית, כדאי לבחור מיקום שקרוב למשתמשים.
  4. לוחצים על התחלה במצב בדיקה. קוראים את כתב הוויתור לגבי כללי האבטחה.
    בשלבים הבאים של ה-codelab הזה, תוסיפו כללי אבטחה כדי לאבטח את הנתונים. אל תפיצו או תחשפו אפליקציה באופן ציבורי בלי להוסיף כללי אבטחה למסד הנתונים.
  5. לוחצים על יצירה.
  6. אחרי שיוצרים את מופע מסד הנתונים, בוחרים בכרטיסייה כללים ומעדכנים את הגדרות הכללים באופן הבא:
     {
       "rules": {
         "messages": {
           ".read": "auth.uid != null",
           ".write": "auth.uid != null"
         }
       }
     }
    

מידע נוסף על אופן הפעולה של כללי האבטחה (כולל תיעוד של המשתנה auth) זמין במסמכי האבטחה של Realtime Database.

הגדרת Cloud Storage for Firebase

  1. בחלונית הימנית במסוף Firebase, מרחיבים את Build (פיתוח) ובוחרים באפשרות Storage (אחסון).
  2. לוחצים על תחילת העבודה.
  3. בוחרים מיקום לקטגוריית האחסון שמוגדרת כברירת מחדל.
    קטגוריות ב-US-WEST1, ב-US-CENTRAL1 וב-US-EAST1 יכולות ליהנות מהמסלול תמיד בחינם של Google Cloud Storage. התמחור והשימוש בקטגוריות בכל המיקומים האחרים מפורטים בתמחור ובשימוש ב-Google Cloud Storage.
  4. לוחצים על התחלה במצב בדיקה. קוראים את כתב הוויתור בנוגע לכללי האבטחה.
    בהמשך ה-codelab, תוסיפו כללי אבטחה כדי לאבטח את הנתונים. אל תפיצו או תחשפו אפליקציה לציבור בלי להוסיף כללי אבטחה לדלי שלכם ב-Storage.
  5. לוחצים על יצירה.

קישור למשאבי Firebase

בשלב קודם ב-codelab הזה, הוספתם את הקוד הבא ל-MainActivity.kt. הבלוק המותנה הזה קישר את פרויקט Android לחבילת כלי האמולטור של Firebase.

// 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 שלו, אפשר להסיר את הבלוק הזה או להפעיל את האפליקציה במצב הפצה כדי ש-BuildConfig.DEBUG יהיה false.