Firebase Android Codelab – פיתוח Friendly Chat

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

צילום מסך

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

ברוכים הבאים ל-codelab של Friendly Chat. בקודלאב הזה תלמדו איך להשתמש בפלטפורמת 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 חסר, אין מה לדאוג. הוא יתווסף בשלב מאוחר יותר.

בדיקת יחסי התלות

בקודלאב הזה כבר הוספנו בשבילכם את כל יחסי התלות הנדרשים, אבל חשוב להבין איך מוסיפים את 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. התקנת ה-CLI של Firebase

בקודלאב הזה נעשה שימוש ב-Firebase Emulator Suite כדי לדמות באופן מקומי את Firebase Auth, את Realtime Database ואת Cloud Storage. כך תוכלו ליצור סביבה מקומית לפיתוח מהירה, בטוחה וללא עלות, שבה תוכלו לפתח את האפליקציה.

התקנת ה-CLI של Firebase

קודם כול צריך להתקין את 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:

דף הבית של ממשק המשתמש של Emulator Suite

משאירים את הפקודה 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. לצורך הקודלאב הזה, סיפקנו קובץ 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

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

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

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

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

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

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

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

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

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

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

קודם מוסיפים את משתנה המכונה הבא לכיתה MainActivity.kt:

MainActivity.kt

// Firebase instance variables
private lateinit var auth: FirebaseAuth

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

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

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

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

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

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

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

קריאת נתונים

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

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

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

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("")
}

הטמעת שליחת הודעות תמונה

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

  • בחירת תמונה
  • טיפול בבחירת התמונות
  • כתיבת הודעת תמונה זמנית ב-Realtime Database
  • תחילת העלאת התמונה שנבחרה
  • מעדכנים את כתובת ה-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 של המהדר ומקישים על לחצן השליחה. ההודעה החדשה אמורה להופיע בממשק המשתמש של האפליקציה ובממשק המשתמש של Firebase Emulator Suite.
  3. במהדורת Android של המהדר, מקישים על התמונה עם הסימן '+' כדי לבחור תמונה מהמכשיר. ההודעה החדשה אמורה להופיע קודם עם תמונה זמנית, ואז עם התמונה שנבחרה אחרי השלמת העלאת התמונה. ההודעה החדשה אמורה להופיע גם בממשק המשתמש של 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 אמיתי ואפליקציית Firebase ל-Android לשימוש בקודלאב הזה. תוסיפו גם את ההגדרות הספציפיות לאפליקציה שלכם ב-Firebase. ולבסוף, תגדירו משאבי Firebase אמיתיים לשימוש באפליקציה.

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

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

שדרוג של תוכנית התמחור ב-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, בוחרים באפשרות קובץ > סנכרון הפרויקט עם קובצי Gradle. יכול להיות שתצטרכו גם להריץ את הפקודות Build/Clean Project ו-Build/Rebuild Project כדי שהשינויים בהגדרות ייכנסו לתוקף.

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

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

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

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

הגדרת Realtime Database

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

  1. בחלונית הימנית של מסוף Firebase, מרחיבים את Build ובוחרים באפשרות Realtime Database.
  2. לוחצים על Create database.
  3. בוחרים מיקום למסד הנתונים ולוחצים על הבא.
    באפליקציה אמיתית, כדאי לבחור מיקום קרוב למשתמשים.
  4. לוחצים על התחלה במצב בדיקה. קוראים את כתב הוויתור לגבי כללי האבטחה.
    בשלב הבא של סדנת הקוד הזו, תוסיפו כללי אבטחה כדי לאבטח את הנתונים. אסור להפיץ או לחשוף אפליקציה באופן ציבורי בלי להוסיף כללי אבטחה למסד הנתונים.
  5. לוחצים על יצירה.
  6. אחרי שיוצרים את מכונה של מסד הנתונים, בוחרים בכרטיסייה Rules ומעדכנים את הגדרת הכללים כך:
     {
       "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. לוחצים על התחלה במצב בדיקה. קוראים את כתב הוויתור לגבי כללי האבטחה.
    בהמשך הסדנה תוסיפו כללי אבטחה כדי לאבטח את הנתונים. אין להפיץ או לחשוף אפליקציה באופן ציבורי בלי להוסיף כללי אבטחה לקטגוריית האחסון.
  5. לוחצים על יצירה.

חיבור למשאבים של Firebase

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