أنشئ تطبيق Android باستخدام Firebase وJetpack Compose

1 المقدمة

آخر تحديث: 2022-11-16

إنشاء تطبيق Android باستخدام Firebase وJetpack Compose

في هذا الدرس التطبيقي حول البرمجة، ستقوم بإنشاء تطبيق Android يسمى Make It So . تم تصميم واجهة المستخدم لهذا التطبيق بالكامل باستخدام Jetpack Compose ، وهي مجموعة أدوات Android الحديثة لإنشاء واجهة مستخدم أصلية - إنها بديهية وتتطلب تعليمات برمجية أقل من كتابة ملفات .xml وربطها بالأنشطة أو الأجزاء أو طرق العرض.

الخطوة الأولى لفهم مدى جودة عمل Firebase وJetpack Compose معًا هي فهم بنية Android الحديثة. إن البنية الجيدة تجعل النظام سهل الفهم، وسهل التطوير، وسهل الصيانة، لأنه يوضح تمامًا كيفية تنظيم المكونات وتواصلها مع بعضها البعض. في عالم Android، يُطلق على البنية الموصى بها اسم Model - View - ViewModel . يمثل النموذج الطبقة التي تصل إلى البيانات في التطبيق. العرض هو طبقة واجهة المستخدم ويجب ألا يعرف شيئًا عن منطق العمل. و ViewModel هو المكان الذي يتم فيه تطبيق منطق الأعمال، والذي يتطلب أحيانًا من ViewModel استدعاء طبقة النموذج .

نوصي بشدة بقراءة هذه المقالة لفهم كيفية تطبيق Model - View - ViewModel على تطبيق Android الذي تم إنشاؤه باستخدام Jetpack Compose، لأنه سيجعل قاعدة التعليمات البرمجية أسهل في الفهم ويسهل إكمال الخطوات التالية.

ما سوف تبنيه

Make It So هو تطبيق قائمة مهام بسيط يسمح للمستخدم بإضافة المهام وتحريرها، وإضافة العلامات والأولويات وتواريخ الاستحقاق، ووضع علامة على المهام كمكتملة. توضح الصور أدناه الصفحتين الرئيسيتين لهذا التطبيق: صفحة إنشاء المهام والصفحة الرئيسية التي تحتوي على قائمة المهام التي تم إنشاؤها.

شاشة "اجعلها تضيف مهمة".اجعلها على الشاشة الرئيسية

ستضيف بعض الميزات المفقودة في هذا التطبيق:

  • مصادقة المستخدمين بالبريد الإلكتروني وكلمة المرور
  • أضف مستمعًا إلى مجموعة Firestore واجعل واجهة المستخدم تتفاعل مع التغييرات
  • أضف آثارًا مخصصة لمراقبة أداء تعليمات برمجية محددة في التطبيق
  • قم بإنشاء ميزة تبديل باستخدام Remote Config واستخدم الطرح المرحلي لتشغيله

ما ستتعلمه

  • كيفية استخدام مصادقة Firebase ومراقبة الأداء والتكوين عن بعد وCloud Firestore في تطبيق Android حديث
  • كيفية جعل واجهات برمجة تطبيقات Firebase تتلاءم مع بنية MVVM
  • كيفية عكس التغييرات التي تم إجراؤها باستخدام Firebase APIs في واجهة مستخدم الإنشاء

ماذا ستحتاج

2. احصل على نموذج التطبيق وقم بإعداد Firebase

احصل على رمز التطبيق النموذجي

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

git clone https://github.com/FirebaseExtended/make-it-so-android.git

قم بإعداد Firebase

أول ما عليك فعله هو الانتقال إلى وحدة تحكم Firebase وإنشاء مشروع Firebase بالنقر فوق الزر "+ إضافة مشروع"، كما ترون أدناه:

وحدة تحكم Firebase

اتبع الخطوات التي تظهر على الشاشة لإكمال إنشاء المشروع.

داخل كل مشروع من مشاريع Firebase، يمكنك إنشاء تطبيقات مختلفة: لأنظمة Android وiOS وWeb وFlutter وUnity. اختر خيار Android كما ترى هنا:

نظرة عامة على مشروع Firebase

ثم اتبع الخطوات التالية:

  1. أدخل com.example.makeitso كاسم الحزمة، واختياريًا، أدخل لقبًا. بالنسبة إلى الدرس التطبيقي حول التعليمات البرمجية هذا، لا تحتاج إلى إضافة شهادة توقيع تصحيح الأخطاء.
  2. انقر فوق "التالي" لتسجيل تطبيقك والوصول إلى ملف تكوين Firebase.
  3. انقر فوق تنزيل google-services.json لتنزيل ملف التكوين الخاص بك وحفظه في دليل make-it-so-android/app .
  4. انقر فوق {التالي . نظرًا لأن حزم Firebase SDK مضمنة بالفعل في ملف build.gradle في نموذج المشروع، انقر فوق "التالي" للانتقال إلى الخطوات التالية .
  5. انقر فوق متابعة وحدة التحكم للإنهاء.

لكي يعمل تطبيق Make it So بشكل صحيح، هناك شيئان يتعين عليك القيام بهما في وحدة التحكم قبل الانتقال إلى التعليمات البرمجية: تمكين موفري المصادقة وإنشاء قاعدة بيانات Firestore. أولاً، لنقم بتمكين المصادقة حتى يتمكن المستخدمون من تسجيل الدخول إلى التطبيق:

  1. من قائمة Build ، حدد Authentication ، ثم انقر فوق Get Started .
  2. من بطاقة طريقة تسجيل الدخول ، حدد البريد الإلكتروني/كلمة المرور ، وقم بتمكينه.
  3. بعد ذلك، انقر فوق "إضافة موفر جديد" وحدد "مجهول" وقم بتمكينه.

بعد ذلك، قم بإعداد Firestore. ستستخدم Firestore لتخزين مهام المستخدم الذي قام بتسجيل الدخول. سيحصل كل مستخدم على المستند الخاص به ضمن مجموعة من قاعدة البيانات.

  1. من قائمة "إنشاء" ، حدد Firestore ، ثم انقر فوق "إنشاء قاعدة بيانات" .
  2. أبقِ "البدء" في وضع الإنتاج ممكّنًا وانقر فوق "التالي" .
  3. عندما يُطلب منك ذلك، حدد الموقع الذي سيتم تخزين بيانات Cloud Firestore فيه. عند تطوير تطبيق إنتاج، ستحتاج إلى أن يكون هذا في منطقة قريبة من غالبية المستخدمين لديك وأن يكون مشتركًا مع خدمات Firebase الأخرى، مثل الوظائف. بالنسبة إلى الدرس التطبيقي حول التعليمات البرمجية هذا، يمكنك الاحتفاظ بالمنطقة الافتراضية أو تحديد المنطقة الأقرب إليك.
  4. انقر فوق "تمكين" لتوفير قاعدة بيانات Firestore الخاصة بك.

لنتوقف لحظة لبناء قواعد أمان قوية لقاعدة بيانات Firestore. افتح لوحة معلومات Firestore وانتقل إلى علامة التبويب "القواعد" . ثم قم بتحديث قواعد الأمان لتبدو كما يلي:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

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

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

أنت الآن جاهز لتشغيل التطبيق! افتح المجلد make-it-so-android/start في Android Studio وقم بتشغيل التطبيق (يمكن القيام بذلك باستخدام محاكي Android أو جهاز Android حقيقي).

3. مصادقة Firebase

ما الميزة التي ستضيفها؟

في الحالة الحالية لنموذج تطبيق Make It So ، يمكن للمستخدم بدء استخدام التطبيق دون الحاجة إلى تسجيل الدخول أولاً. ويستخدم المصادقة المجهولة لتحقيق ذلك. ومع ذلك، لا تسمح الحسابات المجهولة للمستخدم بالوصول إلى بياناته على الأجهزة الأخرى أو حتى في الجلسات المستقبلية. على الرغم من أن المصادقة المجهولة مفيدة لعملية الإعداد الدافئة، إلا أنه يجب عليك دائمًا توفير خيار للمستخدمين للتحويل إلى نموذج مختلف لتسجيل الدخول. مع أخذ ذلك في الاعتبار، في هذا الدرس التطبيقي حول التعليمات البرمجية، ستضيف مصادقة البريد الإلكتروني وكلمة المرور إلى تطبيق Make It So.

حان الوقت للترميز!

بمجرد قيام المستخدم بإنشاء حساب، من خلال كتابة بريد إلكتروني وكلمة مرور، يتعين عليك أن تطلب من Firebase Authentication API بيانات اعتماد البريد الإلكتروني، ثم ربط بيانات الاعتماد الجديدة بالحساب المجهول. افتح ملف AccountServiceImpl.kt في Android Studio وقم بتحديث وظيفة linkAccount بحيث تبدو كما يلي:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

افتح الآن SignUpViewModel.kt واتصل بوظيفة linkAccount الخاصة بالخدمة داخل كتلة launchCatching الخاصة بوظيفة onSignUpClick :

شاشات/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

يحاول أولاً المصادقة، وإذا نجحت المكالمة، فإنه ينتقل إلى الشاشة التالية ( SettingsScreen ). أثناء تنفيذ هذه الاستدعاءات داخل كتلة launchCatching ، إذا حدث خطأ في السطر الأول، فسيتم اكتشاف الاستثناء ومعالجته، ولن يتم الوصول إلى السطر الثاني على الإطلاق.

بمجرد فتح SettingsScreen مرة أخرى، ستحتاج إلى التأكد من اختفاء خيارات تسجيل الدخول وإنشاء الحساب ، لأنه الآن تمت مصادقة المستخدم بالفعل. للقيام بذلك، دعونا نجعل SettingsViewModel يستمع إلى حالة المستخدم الحالي (متوفر في AccountService.kt )، للتحقق مما إذا كان الحساب مجهولاً أم لا. للقيام بذلك، قم بتحديث uiState في SettingsViewModel.kt ليبدو كما يلي:

الشاشات/الإعدادات/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

آخر شيء عليك القيام به هو تحديث uiState في SettingsScreen.kt لتجميع الحالات المنبعثة من SettingsViewModel :

شاشات/إعدادات/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

الآن في كل مرة يقوم فيها المستخدم بالتغيير، ستعيد SettingsScreen نفسها لعرض الخيارات وفقًا لحالة المصادقة الجديدة للمستخدم.

الوقت للاختبار!

قم بتشغيل Make it So وانتقل إلى الإعدادات من خلال النقر على أيقونة الترس في الزاوية اليمنى العليا من الشاشة. ومن هناك، انقر فوق خيار إنشاء حساب:

شاشة إعدادات Make it Soاجعلها شاشة الاشتراك

اكتب بريدًا إلكترونيًا صالحًا وكلمة مرور قوية لإنشاء حسابك. من المفترض أن يعمل ويجب إعادة توجيهك إلى صفحة الإعدادات، حيث سترى خيارين جديدين: تسجيل الخروج وحذف حسابك. يمكنك التحقق من الحساب الجديد الذي تم إنشاؤه في لوحة معلومات المصادقة على وحدة تحكم Firebase من خلال النقر فوق علامة التبويب المستخدمون.

4. سحابة فايرستور

ما الميزة التي ستضيفها؟

بالنسبة إلى Cloud Firestore، ستضيف مستمعًا إلى مجموعة Firestore التي تخزن المستندات التي تمثل المهام المعروضة في Make it So . بمجرد إضافة هذا المستمع، سوف تتلقى كل تحديث يتم إجراؤه على هذه المجموعة.

حان الوقت للترميز!

قم بتحديث Flow المتوفر في StorageServiceImpl.kt ليبدو كما يلي:

model/service/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

يقوم هذا الرمز بإضافة مستمع إلى مجموعة المهام بناءً على user.id يتم تمثيل كل مهمة بواسطة مستند في مجموعة تسمى tasks ، ولكل واحدة منها حقل يسمى userId . يرجى ملاحظة أنه سيتم إصدار Flow جديد إذا تغيرت حالة currentUser (عن طريق تسجيل الخروج، على سبيل المثال).

أنت الآن بحاجة إلى جعل Flow في TasksViewModel.kt يعكس نفسه كما هو الحال في الخدمة:

شاشات/المهام/TasksViewModel.kt

val tasks = storageService.tasks

وآخر شيء هو جعل composable function في TasksScreens.kt ، والتي تمثل واجهة المستخدم، على دراية بهذا التدفق وجمعه كحالة. في كل مرة تتغير فيها الحالة، ستعيد الوظيفة القابلة للتركيب تكوين نفسها تلقائيًا وتعرض أحدث حالة للمستخدم. أضف هذا إلى TasksScreen composable function :

شاشات/المهام/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

بمجرد أن تتمكن الدالة القابلة للتركيب من الوصول إلى هذه الحالات، يمكنك تحديث LazyColumn (وهي البنية التي تستخدمها لعرض قائمة على الشاشة) لتبدو كما يلي:

شاشات/المهام/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

الوقت للاختبار!

ومن أجل اختبار نجاح الأمر، قم بإضافة مهمة جديدة باستخدام التطبيق (من خلال النقر على زر الإضافة في الركن الأيمن السفلي من الشاشة). بمجرد الانتهاء من إنشاء المهمة، يجب أن تظهر في مجموعة Firestore في Firestore Console. إذا قمت بتسجيل الدخول إلى Make it So على أجهزة أخرى بنفس الحساب، فستتمكن من تعديل عناصر المهام الخاصة بك ومشاهدتها يتم تحديثها على جميع الأجهزة في الوقت الفعلي.

5. مراقبة الأداء

ما الميزة التي ستضيفها؟

يعد الأداء أمرًا مهمًا جدًا يجب الانتباه إليه لأنه من المحتمل جدًا أن يتخلى المستخدمون عن استخدام تطبيقك إذا لم يكن الأداء جيدًا ويستغرقون الكثير من الوقت لإكمال مهمة بسيطة باستخدامه. ولهذا السبب يكون من المفيد في بعض الأحيان جمع بعض المقاييس حول رحلة معينة يقوم بها المستخدم في تطبيقك. ولمساعدتك في ذلك، توفر مراقبة أداء Firebase آثارًا مخصصة . اتبع الخطوات التالية لإضافة آثار مخصصة وقياس الأداء في أجزاء مختلفة من التعليمات البرمجية في Make it So.

حان الوقت للترميز!

إذا قمت بفتح ملف Performance.kt ، فسترى دالة مضمنة تسمى التتبع. تستدعي هذه الوظيفة واجهة برمجة تطبيقات مراقبة الأداء لإنشاء تتبع مخصص، وتمرير اسم التتبع كمعلمة. المعلمة الأخرى التي تراها هي كتلة التعليمات البرمجية التي ترغب في مراقبتها. المقياس الافتراضي الذي تم جمعه لكل تتبع هو الوقت الذي يستغرقه التشغيل بالكامل:

النموذج/الخدمة/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

يمكنك اختيار أجزاء قاعدة التعليمات البرمجية التي تعتقد أنها مهمة لقياسها وإضافة آثار مخصصة إليها. فيما يلي مثال على إضافة تتبع مخصص إلى وظيفة linkAccount التي شاهدتها سابقًا (في AccountServiceImpl.kt ) في هذا الدرس التطبيقي حول التعليمات البرمجية:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

الان حان دورك! أضف بعض الآثار المخصصة إلى تطبيق Make it So وانتقل إلى القسم التالي لاختبار ما إذا كان يعمل كما هو متوقع.

الوقت للاختبار!

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

انتقل إلى علامة التبويب "التتبعات المخصصة" وتأكد من عرض الآثار التي أضفتها في قاعدة التعليمات البرمجية هناك، وأنه يمكنك معرفة مقدار الوقت الذي يستغرقه عادةً تنفيذ هذه الأجزاء من التعليمات البرمجية.

6. التكوين عن بعد

ما الميزة التي ستضيفها؟

هناك العديد من حالات الاستخدام للتكوين عن بعد، بدءًا من تغيير مظهر تطبيقك عن بُعد وحتى تكوين سلوكيات مختلفة لشرائح مختلفة من المستخدمين. في هذا الدرس التطبيقي حول التعليمات البرمجية، ستستخدم Remote Config لإنشاء ميزة تبديل الميزات التي ستظهر أو تخفي ميزة مهمة التحرير الجديدة في تطبيق Make it So.

حان الوقت للترميز!

أول ما عليك فعله هو إنشاء التكوين في وحدة تحكم Firebase. للقيام بذلك، تحتاج إلى الانتقال إلى لوحة معلومات التكوين عن بعد والنقر فوق الزر "إضافة معلمة" . املأ الحقول حسب الصورة أدناه:

التكوين عن بعد إنشاء مربع حوار المعلمة

بمجرد ملء جميع الحقول، يمكنك النقر فوق الزر "حفظ " ثم "نشر" . الآن بعد أن تم إنشاء المعلمة وإتاحتها لقاعدة التعليمات البرمجية الخاصة بك، تحتاج إلى إضافة التعليمات البرمجية التي ستجلب القيم الجديدة إلى تطبيقك. افتح الملف ConfigurationServiceImpl.kt وقم بتحديث تنفيذ هاتين الوظيفتين:

model/service/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

تقوم الوظيفة الأولى بجلب القيم من الخادم، ويتم استدعاؤها بمجرد بدء تشغيل التطبيق، في SplashViewModel.kt . إنها أفضل طريقة لضمان توفر أحدث القيم في جميع الشاشات منذ البداية. إنها ليست تجربة مستخدم جيدة إذا قمت بتغيير واجهة المستخدم أو سلوك التطبيق لاحقًا، عندما يكون المستخدم في منتصف القيام بشيء ما!

تقوم الوظيفة الثانية بإرجاع القيمة المنطقية التي تم نشرها للمعلمة التي قمت بإنشائها للتو في وحدة التحكم. وستحتاج إلى استرداد هذه المعلومات في TasksViewModel.kt ، عن طريق إضافة ما يلي إلى وظيفة loadTaskOptions :

شاشات/المهام/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

أنت تقوم باسترداد القيمة الموجودة في السطر الأول، واستخدامها لتحميل خيارات القائمة لعناصر المهمة في السطر الثاني. إذا كانت القيمة false ، فهذا يعني أن القائمة لن تحتوي على خيار التعديل. الآن بعد أن أصبحت لديك قائمة الخيارات، تحتاج إلى جعل واجهة المستخدم تعرضها بشكل صحيح. أثناء قيامك بإنشاء تطبيق باستخدام Jetpack Compose، فإنك تحتاج إلى البحث عن composable function والتي توضح الشكل الذي يجب أن تبدو عليه واجهة المستخدم الخاصة TasksScreen . لذا افتح ملف TasksScreen.kt وقم بتحديث LazyColum للإشارة إلى الخيارات المتاحة في TasksViewModel.kt :

شاشات/المهام/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem هي composable function تعلن عن الشكل الذي يجب أن تبدو عليه واجهة المستخدم لمهمة واحدة. ولكل مهمة قائمة بها خيارات يتم عرضها عندما ينقر المستخدم على أيقونة النقاط الثلاث الموجودة في نهايتها.

الوقت للاختبار!

أنت الآن جاهز لتشغيل التطبيق! تأكد من أن القيمة التي نشرتها باستخدام وحدة تحكم Firebase تتطابق مع سلوك التطبيق:

  • إذا كانت false ، فيجب أن ترى خيارين فقط عند النقر على أيقونة النقاط الثلاث؛
  • إذا كان هذا true ، فمن المفترض أن ترى ثلاثة خيارات عند النقر على أيقونة النقاط الثلاث؛

حاول تغيير القيمة عدة مرات في وحدة التحكم وإعادة تشغيل التطبيق. هذا هو مدى سهولة إطلاق ميزات جديدة في تطبيقك باستخدام Remote Config!

7. تهانينا

تهانينا، لقد نجحت في إنشاء تطبيق Android باستخدام Firebase وJetpack Compose!

لقد أضفت مصادقة Firebase ومراقبة الأداء والتكوين عن بعد وCloud Firestore إلى تطبيق Android تم تصميمه بالكامل باستخدام Jetpack Compose لواجهة المستخدم، وجعلته ملائمًا لبنية MVVM الموصى بها!

قراءة متعمقة

المستندات المرجعية