درس تطبيقي حول ترميز Firebase لنظام التشغيل Android - إنشاء محادثة بسيطة

تجربة Firebase Android Codelab - إنشاء تطبيق Friendly Chat

لمحة عن هذا الدرس التطبيقي حول الترميز

subjectتاريخ التعديل الأخير: سبتمبر 15, 2025
account_circleتأليف: arthurthompson

1. نظرة عامة

لقطة شاشة

صورة: تطبيق Friendly Chat يعمل.

مرحبًا بك في برنامج Friendly Chat التعليمي. في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية استخدام منصة Firebase لإنشاء تطبيق دردشة على Android.

أهداف الدورة التعليمية

  • كيفية استخدام خدمة "مصادقة Firebase" للسماح للمستخدمين بتسجيل الدخول
  • كيفية مزامنة البيانات باستخدام "قاعدة بيانات Firebase في الوقت الفعلي"
  • كيفية تخزين الملفات الثنائية في "مساحة تخزين سحابية لـ Firebase"
  • كيفية استخدام "مجموعة أدوات المحاكاة المحلية لمنصة Firebase" لتطوير تطبيق Android باستخدام Firebase

المتطلبات

  • أحدث إصدار من استوديو Android
  • Android Emulator يعمل بالإصدار 5.0 من نظام التشغيل Android أو إصدار أحدث
  • الإصدار 10 من Node.js أو إصدار أحدث (لاستخدام Emulator Suite)
  • الإصدار 8 من Java أو إصدار أحدث لتثبيت Java، اتّبِع هذه التعليمات، وللتحقّق من إصدارك، شغِّل java -version.
  • الإلمام بلغة البرمجة Kotlin

2. الحصول على الرمز النموذجي

إنشاء نسخة طبق الأصل من المستودع

استنسِخ مستودع GitHub من سطر الأوامر:

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

الاستيراد إلى "استوديو Android"

في "استوديو Android"، انقر على ملف > فتح، ثم اختَر دليل build-android-start ( android_studio_folder) من الدليل الذي نزّلت منه نموذج الرمز.

من المفترض أن يكون مشروع build-android-start مفتوحًا الآن في "استوديو Android". إذا ظهر لك تحذير بشأن عدم توفّر ملف google-services.json، لا داعي للقلق. سيتم إضافته في خطوة لاحقة.

التحقّق من التبعيات

في هذا الدرس العملي، تمت إضافة جميع التبعيات التي ستحتاج إليها، ولكن من المهم معرفة كيفية إضافة حزمة تطوير البرامج (SDK) لبرنامج Firebase إلى تطبيقك:

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

في هذا الدرس العملي، ستستخدم مجموعة أدوات المحاكاة المحلية لـ Firebase لمحاكاة Firebase Auth وRealtime Database وCloud Storage محليًا. يوفّر ذلك بيئة تطوير محلية آمنة وسريعة وبدون تكلفة لإنشاء تطبيقك.

تثبيت Firebase CLI

عليك أولاً تثبيت واجهة سطر الأوامر في Firebase. إذا كنت تستخدم نظام التشغيل macOS أو Linux، يمكنك تنفيذ أمر cURL التالي:

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

إذا كنت تستخدم نظام التشغيل Windows، يُرجى قراءة تعليمات التثبيت للحصول على ملف ثنائي مستقل أو للتثبيت من خلال npm.

بعد تثبيت واجهة سطر الأوامر، يجب أن يؤدي تنفيذ الأمر firebase --version إلى عرض الإصدار 9.0.0 أو إصدار أحدث:

$ firebase --version
9.0.0

تسجيل الدخول

نفِّذ الأمر firebase login لربط واجهة سطر الأوامر بحسابك على Google. سيؤدي ذلك إلى فتح نافذة متصفّح جديدة لإكمال عملية تسجيل الدخول. احرص على اختيار الحساب نفسه الذي استخدمته عند إنشاء مشروعك على Firebase في وقت سابق.

4. الاتصال بمجموعة أدوات محاكي Firebase

بدء المحاكيات

في الوحدة الطرفية، شغِّل الأمر التالي من جذر دليل 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 قيد التشغيل لبقية الدرس العملي.

ربط تطبيقك

في "استوديو Android"، افتح 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".

انسخ الملف mock-google-services.json إلى المجلد build-android-start/app باسم google-services.json:

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

في الخطوة الأخيرة من هذا الدرس العملي، ستتعلّم كيفية إنشاء مشروع حقيقي على Firebase وتطبيق Android على Firebase حتى تتمكّن من استبدال ملف JSON التجريبي هذا بإعداداتك الخاصة.

تشغيل التطبيق

بعد استيراد المشروع إلى "استوديو Android" وإضافة ملف JSON لإعدادات Firebase، ستكون جاهزًا لتشغيل التطبيق للمرة الأولى.

  1. ابدأ تشغيل "محاكي Android".
  2. في "استوديو Android"، انقر على تشغيل ( تنفيذ) في شريط الأدوات.

سيتم تشغيل التطبيق على "محاكي Android". في هذه المرحلة، من المفترض أن تظهر لك قائمة رسائل فارغة، ولن تتمكّن من إرسال الرسائل وتلقّيها. في الخطوة التالية من هذا الدرس العملي، ستصادق على المستخدمين ليتمكّنوا من استخدام تطبيق Friendly Chat.

6. تفعيل المصادقة

سيستخدم هذا التطبيق "قاعدة بيانات Firebase في الوقت الفعلي" لتخزين جميع رسائل المحادثة. قبل إضافة البيانات، يجب التأكّد من أنّ التطبيق آمن وأنّه يمكن للمستخدمين الذين تمّت المصادقة عليهم فقط نشر الرسائل. في هذه الخطوة، سنفعّل خدمة "مصادقة Firebase" ونضبط "قواعد الأمان" في "قاعدة البيانات الآنية الاستجابة".

إضافة وظيفة تسجيل الدخول الأساسية

بعد ذلك، سنضيف بعض رموز 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() للتعامل مع زر تسجيل الخروج:

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" في المتصفّح، ثم انقر على علامة التبويب المصادقة للاطّلاع على حساب المستخدم الذي سجّل الدخول أولاً.

7. قراءة الرسائل

في هذه الخطوة، سنضيف وظيفة لقراءة الرسائل المخزّنة في Realtime Database وعرضها.

استيراد نماذج الرسائل

  1. في واجهة مستخدم "مجموعة أدوات المحاكي في Firebase"، اختَر علامة التبويب 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 باستخدام الرمز المحدّد أدناه. يضيف هذا الرمز جميع الرسائل الحالية من "قاعدة البيانات في الوقت الفعلي"، ثم يستمع إلى إدخالات العناصر الفرعية الجديدة ضمن المسار 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 في الوقت الفعلي وأوقِف هذه العملية. عدِّل الطريقتَين 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 لرسالة الصورة إلى عنوان URL للصورة التي تم تحميلها، وذلك بعد اكتمال عملية التحميل

اختيار صورة

تستخدم ورشة العمل البرمجية هذه خدمة 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"، انقر على الزر تنفيذتشغيل.
  2. في "محاكي Android"، أدخِل رسالة، ثم انقر على زر الإرسال. يجب أن تظهر الرسالة الجديدة في واجهة مستخدم التطبيق وفي واجهة مستخدم "مجموعة المحاكي" في Firebase.
  3. في "محاكي Android"، انقر على صورة "+" لاختيار صورة من جهازك. يجب أن تظهر الرسالة الجديدة أولاً مع صورة عنصر نائب، ثم مع الصورة المحدّدة بعد اكتمال عملية تحميل الصورة. يجب أن تظهر الرسالة الجديدة أيضًا في واجهة مستخدم Emulator Suite، وتحديدًا كعنصر في علامة التبويب Realtime Database وككائن ثنائي كبير في علامة التبويب Storage.

9. تهانينا!

لقد أنشأت للتو تطبيق محادثة في الوقت الفعلي باستخدام Firebase.

ما تعلّمته

  • مصادقة Firebase
  • قاعدة بيانات Firebase في الوقت الفعلي
  • التخزين في السحابة الإلكترونية لبرنامج Firebase

بعد ذلك، جرِّب استخدام ما تعلّمته في هذا الدرس التطبيقي حول الترميز لإضافة 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. (اختياري) فعِّل ميزة "المساعدة المستندة إلى الذكاء الاصطناعي" في وحدة تحكّم Firebase (المعروفة باسم "Gemini في Firebase").
  6. في هذا الدرس العملي، لا تحتاج إلى "إحصاءات Google"، لذا أوقِف خيار "إحصاءات Google".
  7. انقر على إنشاء مشروع، وانتظِر إلى أن يتم توفير مشروعك، ثم انقر على متابعة.

ترقية خطة أسعار Firebase

لاستخدام Cloud Storage for Firebase، يجب أن يكون مشروعك على Firebase ضمن خطة التسعير "الدفع حسب الاستخدام" (Blaze)، ما يعني أنّه مرتبط بحساب فوترة Cloud.

لترقية مشروعك إلى خطة Blaze، اتّبِع الخطوات التالية:

  1. في "وحدة تحكّم Firebase"، اختَر ترقية خطتك.
  2. اختَر خطة Blaze. اتّبِع التعليمات الظاهرة على الشاشة لربط حساب فوترة على Cloud بمشروعك.
    إذا احتجت إلى إنشاء حساب فوترة على Cloud كجزء من عملية الترقية هذه، قد تحتاج إلى الرجوع إلى مسار الترقية في وحدة تحكّم Firebase لإكمال عملية الترقية.

إضافة 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"، اختَر ملف (File) > مزامنة المشروع مع ملفات Gradle (Sync Project with Gradle Files). قد تحتاج أيضًا إلى تنفيذ إنشاء/تنظيف المشروع وإنشاء/إعادة إنشاء المشروع لتطبيق تغييرات الإعداد.

ضبط إعدادات خدمة "مصادقة Firebase"

قبل أن يتمكّن تطبيقك من الوصول إلى واجهات برمجة التطبيقات الخاصة بخدمة "المصادقة في Firebase" نيابةً عن المستخدمين، عليك تفعيل خدمة "المصادقة في Firebase" وموفّري خدمات تسجيل الدخول الذين تريد استخدامهم في تطبيقك.

  1. في وحدة تحكّم Firebase، اختَر المصادقة من لوحة التنقّل اليمنى.
  2. انقر على علامة التبويب طريقة تسجيل الدخول.
  3. انقر على البريد الإلكتروني/كلمة المرور، ثمّ فعِّل مفتاح التبديل (أزرق).
  4. انقر على Google، ثم فعِّل الخيار (أزرق) واضبط عنوان بريد إلكتروني مخصّصًا لدعم المشروع.

إذا ظهرت لك أخطاء لاحقًا في هذا الدرس العملي مع الرسالة "CONFIGURATION_NOT_FOUND"، ارجع إلى هذه الخطوة وتحقّق من عملك.

إعداد قاعدة بيانات الوقت الفعلي

يخزّن التطبيق في هذا الدرس النموذجي رسائل المحادثة في "قاعدة بيانات Firebase في الوقت الفعلي". في هذا القسم، سننشئ قاعدة بيانات ونضبط إعدادات الأمان الخاصة بها باستخدام لغة إعدادات JSON تُسمى "قواعد الأمان في Firebase".

  1. في اللوحة اليمنى من "وحدة تحكّم Firebase"، وسِّع إنشاء، ثم اختَر Realtime Database.
  2. انقر على إنشاء قاعدة بيانات.
  3. اختَر موقعًا لقاعدة البيانات، ثم انقر على التالي.
    بالنسبة إلى تطبيق حقيقي، عليك اختيار موقع جغرافي قريب من المستخدمين.
  4. انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
    في الخطوات التالية من هذا الدرس العملي، ستضيف قواعد الأمان لتأمين بياناتك. لا توزِّع تطبيقًا أو تعرضه بشكل علني بدون إضافة "قواعد الأمان" لقاعدة البيانات.
  5. انقر على إنشاء.
  6. بعد إنشاء مثيل قاعدة البيانات، اختَر علامة التبويب القواعد، ثم عدِّل إعدادات القواعد بما يلي:
     {
       
    "rules": {
         
    "messages": {
           
    ".read": "auth.uid != null",
           
    ".write": "auth.uid != null"
         
    }
       
    }
     
    }

لمزيد من المعلومات حول طريقة عمل "قواعد الأمان" (بما في ذلك المستندات حول المتغيّر "auth")، راجِع مستندات أمان Realtime Database.

إعداد "مساحة تخزين سحابية لـ Firebase"

  1. في اللوحة اليمنى من وحدة تحكّم Firebase، وسِّع إنشاء، ثم اختَر مساحة التخزين.
  2. انقر على البدء.
  3. اختَر موقعًا جغرافيًا لحزمة Storage التلقائية.
    يمكن للحِزم في US-WEST1 وUS-CENTRAL1 وUS-EAST1 الاستفادة من الفئة"دائمًا مجانية" في Google Cloud Storage. تخضع الحِزم في جميع المواقع الجغرافية الأخرى لأسعار واستخدام Google Cloud Storage.
  4. انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
    في وقت لاحق من هذا الدرس العملي، ستضيف قواعد أمان لحماية بياناتك. لا توزّع تطبيقًا أو تعرضه للجميع بدون إضافة "قواعد الأمان" لحزمة Cloud Storage.
  5. انقر على إنشاء.

الربط بموارد Firebase

في خطوة سابقة من هذا الدرس العملي، أضفت ما يلي إلى 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.