يُعد هذا الدرس التطبيقي جزءًا من الدورة التدريبية المتقدّمة لنظام التشغيل Android في لغة Kotlin. ستحصل على أقصى استفادة من هذه الدورة التدريبية إذا كنت تعمل من خلال الدروس التطبيقية حول الترميز بالتسلسل، ولكن هذا ليس إلزاميًا. يتم إدراج جميع الدروس التطبيقية حول ترميز الدورات التدريبية في الصفحة المقصودة لبرنامج Android المتقدّم في لغة ترميز Kotlin.
مقدمة
الإشعارات هي رسائل تظهر للمستخدم خارج واجهة مستخدم التطبيق. تظهر الإشعارات في أعلى الشاشة إذا كان الجهاز غير مقفل أو استنادًا إلى إعدادات الأمان على شاشة القفل عندما يكون الجهاز مقفلاً.
يتألف الإشعار العادي من عنوان ووصف ورمز. يمكن أن يتضمن الإشعار أيضًا إجراءات قابلة للنقر، والرد السريع، والمحتوى القابل للتمديد، والصور.
يمكن أن تعرض الإشعارات مواد في الوقت المناسب، ويمكن أن تحتوي على أزرار للسماح للمستخدم بتنفيذ إجراءات سريعة، مثل إرسال رد أو تأجيل منبّه. يؤدي النقر على إشعار إلى نقل المستخدم إلى ملف شخصي في تطبيقك مرتبط بمحتوى الإشعار.
وتُعد الإشعارات طريقة مفيدة لتذكير المستخدمين بمهمة مهمة أو إعلامهم بحدث ما أو إعلامهم بالمعلومات المهمة التي يحتاجون إليها على الفور أثناء عمل التطبيق في الخلفية. استخدام الإشعارات باعتدال ولا يؤدي ذلك إلى احترام المستخدمين فحسب، بل يزيد أيضًا من احتمال تلقي إشعار تطبيقك ما يجذبه من إشعارات.
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إنشاء الإشعارات واستخدامها في تطبيق متوافق مع Android.
ما يجب معرفته
ويجب أن تكون على دراية بما يلي:
- كيفية إنشاء تطبيقات Android في Kotlin. وعلى وجه الخصوص، يمكنك العمل مع Android SDK.
- كيفية تصميم بنية أساسية باستخدام "مكونات البنية" وربط البيانات.
- فهم أساسي لأجهزة BroadcastReceivers
- فهم أساسيات AlarmManager
ما ستتعرَّف عليه
- كيفية إنشاء إشعار وتصميمه وإرساله.
- كيفية إلغاء الإشعارات.
- كيفية إنشاء قنوات الإشعارات
- كيفية إضافة إجراءات سريعة إلى الإشعارات
- طريقة عرض شارات الإشعارات على رمز التطبيق.
الإجراءات التي ستنفذّها
- أضِف إشعارًا إلى تطبيق إجراء التفعيل.
- ألغِ الإشعار الذي أرسلته سابقًا.
- أنشئ قنوات لأنواع مختلفة من الإشعارات.
- يمكنك تخصيص الإشعارات في تطبيق إجراء التفعيل.
- يمكنك إضافة إجراءات سريعة لجعل الإشعار تفاعليًا.
- أوقِف شارات الإشعارات.
إنّ تحضير البيض أمر بسيط، ولكن يمكن أن يمثّل مهمة صعبة إذا تعذّرت تتبُّع الوقت. من خلال هذا الدرس التطبيقي حول الترميز، عليك العمل على تطبيق موقّت البيض وجعله مثاليًا، تمامًا كما هو الحال في إعداد البيض المستقبلي. ستبدأ بتطبيق موقت البيض الذي يتيح للمستخدم ضبط إعدادات مختلفة لطهو البيض على أنماط البيض المختلفة. يضمّ الموقّت عدًا تنازليًا من الفاصل الزمني المختار ويعرض رسالة محمصة عندما يصبح البيض جاهزًا.
قد يبدو هذا عمليًا، ولكنه ليس مثاليًا، وليس سهلاً للمستخدم. للبدء، تظهر رسالة الخبز المحمّل لفترة زمنية قصيرة فقط، ومن ثم يمكن تفويتها. وإذا لم يكن التطبيق في المقدّمة أو كان الجهاز مقفلاً، لا يتوفّر مؤشر مرئي لحالة الموقّت بعد اختفاء رسالة الخبز المحمّل.
من المفترض أن يستخدم موقّت البيض إشعارات لإعلام المستخدمين بانتهاء الوقت. على المستخدم معرفة أنّ البيض أصبح جاهزًا على الفور، وإلا سيتم طهيه أكثر من اللازم. وتكون الإشعارات مرئية ويمكن أن تشمل أصواتًا ويمكن أن تؤدي إلى اهتزاز الجهاز، ما يؤدي إلى جذب انتباه المستخدم. وبهذه الطريقة، يمكنك الوصول إلى البيض المثالي والحصول على تجربة جيدة ومُرضية للمستخدمين.
للحصول على نموذج التطبيق، يمكنك تنفيذ أي مما يلي:
يمكنك نسخ المستودع من GitHub والتبديل إلى الفرع Starter.
$ git clone https://github.com/googlecodelabs/android-kotlin-notifications
بدلاً من ذلك، يمكنك تنزيل المستودع كملف Zip وفك ضغطه وفتحه في"استوديو Android".
- افتح التطبيق وشغِّله في "استوديو Android".
ستظهر لك صورة بيضة وقائمة منسدلة بها قائمة بفترات زمنية محددة مسبقًا لطهي البيض. انقر على المثلث في القائمة المنسدلة سلق الغلق. ويُقدَّم الخيار الأول في القائمة لأغراض الاختبار ويضبط المنبّه على 10 ثوانٍ فقط. بجانب القائمة، يوجد مفتاح تفعيل يؤدي إلى بدء موقّت البيض. ويمكنك استخدام هذا المفتاح لبدء موقّت البيض وإيقافه في أي وقت. يعمل رمز التفعيل بشكل كامل، ما يعني أنّه يمكنك إعداد موقّت البيض ومشاهدته أثناء العدّ تنازليًا إلى 0. وبعد انتهاء المؤقّت، يتم عرض رسالة الخبز المحمّل، كما هو موضّح أدناه.
- افحص رمز المصدر. يتكون تطبيق إجراء التفعيل من نشاط واحد يُسمى
MainActivity
. هناك ثلاث حِزم فرعية باسمreceiver
وui
وutil
.
- /receiver: تحتوي حزمة
receiver
على جهازَي استقبال، وهماAlarmReceiver
وSnoozeReceiver
. يتم تشغيلAlarmReceiver
بواسطةAlarmManager
لإرسال الإشعار عند انتهاء المؤقت الذي يحدده المستخدم. يتعاملSnoozeReceiver
مع نقرة المستخدم لتأجيل الإشعار. - /ui: يحتوي هذا العمود على
EggTimerFragment
التي تشكّل جزءًا من جزء واجهة المستخدم في التطبيق. وتقع علىEggTimerViewModel
مسؤولية بدء الموقّت وإلغائه ومهام التطبيق الأخرى المتعلقة بمراحل الحياة. - /util: في هذه الحزمة، هناك ملفان. يحتوي
BindingUtils.kt
على محوّلات ربط لتفعيل ربط البيانات بين واجهة مستخدم التطبيق وViewModel
.NotificationUtils.kt
لديه طرق إضافة علىNotificationManager
.
يُعدّ استخدام الإشعارات طريقة رائعة لجذب انتباه المستخدمين إلى تطبيقك، سواء كان تطبيقك قيد التشغيل أو يعمل في المقدّمة، سيعرض الإشعار نافذة منبثقة أعلى الشاشة وقد يتضمن صوتًا أو اهتزازًا. لإنشاء إشعار، يجب استخدام أداة إنشاء الإشعارات وتوفير نص عنوان ونص محتوى ورمز. بعد أن تتوفّر في أداة الإنشاء جميع الحقول اللازمة، تساعدك أداة NotificationManager
، وهي خدمة النظام، على عرض هذا المحتوى كإشعار. يقع على عاتق NotificationManager
مسؤولية إرسال الإشعار وتعديل محتوياته وإلغاء الإشعار. في الخطوات التالية، سيتم إدراج طرق إضافات إلى NotificationManager
. بهذه الطريقة، في كل مرة تحتاج فيها إلى استخدام NotificationManager
، ستتمكن من استخدام وظائف الإضافات هذه لتحقيق الوظيفة التي تحتاج إلى استخدامها.
الخطوة 1: إنشاء إشعار أساسي
في هذه المهمة، يتم إنشاء إشعار جديد وإعداد رسالة للمستخدم وإرسال الإشعار.
- افتح الصف
NotificationUtils.kt
وابحث عنTODO: Step 1.1
. ستجد'، مهام المطابقة في هذا الدرس التطبيقي ورمز التطبيق. - افحص الدالة
sendNotification()
المحدّدة. سيتم توسيع دالة الإضافة هذه إلىNotificationManager
لإرسال الإشعارات.
//NotificationUtils.kt
// TODO: Step 1.1 extension function to send messages (GIVEN)
/**
* Builds and delivers a notification.
*
* @param messageBody, notification text.
* @param context, activity context.
*/
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
- احصل على مثيل لأداة إنشاء الإشعارات، ووفّر في سياق التطبيق ومعرّف القناة. معرّف القناة هو قيمة سلسلة للقناة.
قنوات الإشعارات هي طريقة لتجميع الإشعارات. ومن خلال تجميع أنواع إشعارات مشابهة معًا، يمكن لمطوّري البرامج والمستخدمين التحكّم في كل الإشعارات في القناة. وبعد إنشاء القناة، يمكن استخدامها لإرسال أي عدد من الإشعارات.
//NotificationUtils.kt
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
val builder = NotificationCompat.Builder(
applicationContext,
applicationContext.getString(R.string.egg_notification_channel_id)
)
- يمكنك ضبط رمز الإشعار ليمثّل تطبيقك وعنوانًا ونص المحتوى للرسالة التي تريد إرسالها إلى المستخدم. سترى المزيد من الخيارات لتخصيص الإشعار مرة أخرى في درس تطبيقي حول الترميز، ولكن هذا هو الحد الأدنى للبيانات التي تحتاج إلى إعدادها لإرسال إشعار.
//NotificationUtils.kt
// TODO: Step 1.3 set title, text and icon to builder
.setSmallIcon(R.drawable.cooked_egg)
.setContentTitle(applicationContext.getString(R.string.notification_title))
.setContentText(messageBody)
- وبعد ذلك، عليك استدعاء
notify()
باستخدام معرّف فريد لإشعارك وكائنNotification
من أداة الإنشاء.
يمثّل رقم التعريف هذا نسخة الإشعار الحالية وهو مطلوب لتعديل هذا الإشعار أو إلغاؤه. بما أنّه سيتم إرسال إشعار نشط واحد فقط إلى تطبيقك في وقت معيّن، يمكنك استخدام رقم التعريف نفسه لجميع الإشعارات. ويتم حاليًا تحديد ثابت لهذا الغرض باسم NOTIFICATION_ID
في NotificationUtils.kt
. يُرجى ملاحظة أنه يمكنك الاتصال بـ notify()
مباشرةً لأنك تُجري الاستدعاء من دالة الإضافة في الصف نفسه.
//NotificationUtils.kt
// TODO: Step 1.4 call notify to send the notification
// Deliver the notification
notify(NOTIFICATION_ID, builder.build())
- افتح
ui/EggTimerViewModel.kt
وابحث عن دالةstartTimer()
. تنشئ هذه الدالة منبّهًا باستخدام الفاصل الزمني المحدّد عندما يفعّل المستخدم موقّت البيض. - سيؤدي إلى إرسال إشعار في هذه الوظيفة عندما يبدأ المستخدم الموقّت. لاستدعاء الدالة
sendNotification()
التي نفَّذتها سابقًا، تحتاج إلى مثيلNotificationManager
.NotificationManager
هي خدمة نظام توفّر كل الوظائف التي تم الكشف عنها من خلال واجهة برمجة التطبيقات للإشعارات، بما في ذلك وظيفة الإضافة التي أضفتها. وفي أي وقت تريد فيه إرسال إشعار أو إلغائه أو تعديله، عليك طلب مثيل لنظام التشغيلNotificationManager
من النظام. يجب استدعاء الدالةsendNotification()|
مع رسالة الإشعار والسياق.
// EggTimerViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager
// and call sendNotification
val notificationManager = ContextCompat.getSystemService(
app,
NotificationManager::class.java
) as NotificationManager
notificationManager.sendNotification(app.getString(R.string.timer_running), app)
أنت على وشك الانتهاء ومع ذلك، إذا شغَّلت تطبيقك الآن واضبطت الموقِّت، لن تتلقى إشعارًا.
- افتح
logcat
وابحث عن"No Channel found"
. من المفترض أن تظهر لك رسالة خطأ تفيد بأنّegg_channel
غير متوفّر. في الخطوات التالية، ستتعرّف على المزيد من المعلومات عن قنوات الإشعارات وحل هذه المشكلة.
الخطوة 2: قنوات الإشعارات
بدءًا من المستوى 26 لواجهة برمجة التطبيقات، يجب تعيين كل الإشعارات لقناة. إذا نقرت مع الاستمرار على رمز مشغّل التطبيقات، واختَرت معلومات التطبيق وانقرت على الإشعارات، ستظهر لك قائمة بقنوات الإشعارات المرتبطة بالتطبيق. في الوقت الحالي، القائمة فارغة لأن تطبيقك لم ينشئ أي قنوات.
تمثّل القنوات إشعارًا وإشعارًا، مثل موقّت البيض، ويمكن إرسال إشعار عند طهي البيض، ويمكن أيضًا استخدام قناة أخرى لإرسال إشعارات يومية لتذكيرك بتناول البيض مع وجبة الفطور. يتمّ تجميع كل الإشعارات في القناة معًا، ويمكن للمستخدمين ضبط إعدادات الإشعارات لقناة بأكملها. ويتيح ذلك للمستخدمين تخصيص إعدادات الإشعارات لديهم استنادًا إلى نوع الإشعار الذي يهتمون به. على سبيل المثال، يمكن للمستخدمين إيقاف إشعارات الفطور، ولكن يظل بإمكانهم اختيار الاطّلاع على الإشعارات من الموقّت.
يضبط مطوّرو البرامج الإعدادات الأولية والأهمية والسلوك، ليتم تطبيقها على جميع الإشعارات في القناة. بعد ضبط الإعدادات الأولية، يمكن للمستخدمين إلغاء هذه الإعدادات.
لقد استخدمت في egg_notification_channel_id
1.1 قناة الإشعارات الخاصة بك، لذا عليك الآن إنشاء وتخصيص إعدادات الإشعارات وتخصيصها لهذه القناة.
- افتح
EggTimerFragment.kt
وابحث عن دالةcreateChannel()
. - تمرير معرّف القناة الفريد إلى منشئ
NotificationChannel
- أدخِل اسم قناة الإشعار، والذي سيظهر للمستخدمين أيضًا في شاشة الإعدادات.
- بصفتك المعلمة الأخيرة، يجب تمرير مستوى الأهمية لقناة الإشعارات. سيتم تناول مستويات الأهمية لاحقًا في هذا الدرس التطبيقي، حتى يمكنك في الوقت الحالي استخدام
NotificationManag
er.IMPORTANCE_LOW
. - في الكائن
notificationChannel
، يتم ضبطenableLights
على "صحيح". سيؤدي هذا الإعداد إلى تفعيل الأضواء عندما يتم عرض إشعار. - في الكائن
notificationChannel
، اضبطlightColor
على اللون الأحمر لعرض ضوء أحمر عند عرض إشعار. - في الكائن
notificationChannel
، يتم ضبط السياسةenableVibration
على "صحيح" لتفعيل الاهتزاز. - في عنصر
notificationChannel
، اضبط وصف القناة على‘Time for breakf
ast'. - يمكنك الحصول على مثال من
NotificationManager
من خلال الاتصال بـgetSystemService()
. - يمكنك طلب الرقم
createNotificationChannel()
علىNotificationManager
وتمرير العنصرnotificationChannel
الذي أنشأته في الخطوة السابقة.
//EggTimerFragment.kt
private fun createChannel(channelId: String, channelName: String) {
// TODO: Step 1.6 START create a channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId,
channelName,
// TODO: Step 2.4 change importance
NotificationManager.IMPORTANCE_LOW
)
// TODO: Step 2.6 disable badges for this channel
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationChannel.description = "Time for breakfast"
val notificationManager = requireActivity().getSystemService(
NotificationManager::class.java
)
notificationManager.createNotificationChannel(notificationChannel)
}
// TODO: Step 1.6 END create channel
}
- ولإنشاء قناة، عليك استدعاء دالة
createChannel()
التي كتبتها للتو (الخطوة 1.7). تتطلب هذه الدالة معلَمتَين، هما معرّف القناة واسم القناة. يجب البحث عن معرّف القناة واسم القناة من مصادر السلاسل المتوفّرة في مشروعك.
// EggTimerFragment.kt
// TODO: Step 1.7 call createChannel
createChannel(
getString(R.string.egg_notification_channel_id),
getString(R.string.egg_notification_channel_name)
)
- يجب تمرير معرّف القناة إلى أداة إنشاء الإشعارات. هذا ما فعلته في الخطوة 1.2. وفي حال ضبط قيمة غير صحيحة لأنّ معرّف القناة سيؤدي إلى تعذّر إرسال الإشعار. افتح
NotificationUtils.kt
لإثبات صحة رقم تعريف القناة الذي ضبطته في السابق.
// NotificationUtils.kt
val builder = NotificationCompat.Builder(
applicationContext,
// TODO: Step 1.8 verify the notification channel name
applicationContext.getString(R.string.egg_notification_channel_id)
)
- شغِّل التطبيق، وسترى التطبيق يرسل إشعارًا في كل مرة تبدأ فيها الموقّت.
- اسحب شريط الحالة ولاحظ أنّ عنوان الإشعار ومحتواه ورمزه سيتم ضبطهما في الخطوات السابقة.
- لإثبات ملكية القناة التي تم إنشاؤها حديثًا، أغلق التطبيق وابحث عن رمز التطبيق. انقر مع الاستمرار على رمز التطبيق واختَر معلومات التطبيق.
- انقر على الإشعارات من قائمة الإعدادات. من المفترض أن تظهر قناة جديدة تُسمّى البيضة تحت الإعداد عرض الإشعارات مباشرةً.
عند تشغيل التطبيق، يتم عرض الإشعار الآن. يمكنك أنت ومطوّر التطبيق والمستخدمون تخصيص الإعدادات والسلوك لجميع الإشعارات المُرسَلة على هذه القناة. تهانينا، لقد أنشأت إشعارًا.
الخطوة 3: إضافة إشعارات إلى تطبيقك
وحتى الآن، يعرض هذا الاستخدام الأساسي لواجهة برمجة تطبيقات الإشعارات، ولكن من غير المنطقي إرسال إشعار بعد بدء الموقّت مباشرةً. من المحتمل أن يفضّل المستخدمون تلقّي إشعارات عندما تصبح البيضة جاهزة. في الجزء التالي من الدرس التطبيقي حول الترميز، ستتعرّف على كيفية حلّ هذه المشكلة وتغيير رسالة الترخيص إلى إشعار.
لقد سبق أن أرسلت الإشعار ولاحظت كيفية عرضه للمستخدمين، ولكنها كانت فقط الخطوة الأولى في إنشاء إشعارات رائعة. وفي هذه الخطوة، ستغيّر الإشعار ليتم إرساله في الوقت المناسب.
يستخدم تطبيقك AlarmManager
لإعداد منبّه. سبق أن تم إدخال الرمز المرتبط بالرمز AlarmManager
في رمز التفعيل ويتم استخدامه لعرض رسالة الترخيص. يتتبّع AlarmManager
اختيار الوقت المطلوب، وسيشغّل الدالة onReceive()
الدالة AlarmReceiver.kt
عند انتهاء الوقت. إذا فتحت AlarmReceiver.kt
وانتقلت إلى onReceive()
، من المفترض أن تظهر لك رسالة الخبز المحمّل التي يتم عرضها في كل مرة يتم فيها ضبط موقّت بيض.
- افتح
AlarmReceiver.kt
، مثال عنNotificationManager
، واستدعِ الدالةsendNotification()
باستخدام نص الرسالة ومعلمات السياق.
// AlarmReceiver.kt
// TODO: Step 1.9 add call to sendNotification
val notificationManager = ContextCompat.getSystemService(
context,
NotificationManager::class.java
) as NotificationManager
notificationManager.sendNotification(
context.getText(R.string.eggs_ready).toString(),
context
)
- يمكنك اختياريًا إزالة الخبز المحمّل لأن تطبيقك سيرسل إشعارًا عند انتهاء الموقّت.
// AlarmReceiver.kt
// TODO: Step 1.10 [Optional] remove toast
// Toast.makeText(
// context,
// context.getText(R.string.eggs_ready),
// Toast.LENGTH_SHORT
// ).show()
- شغِّل تطبيقك . من المفترض أن يظهر لك إشعار في كل مرة تبدأ فيها الموقّت وكل مرة ينتهي فيها الموقّت.
وهذا ليس مثاليًا. أنت لا تريد إرسال عدد كبير جدًا من الإشعارات إلى المستخدمين. يمكنك إزالة الإشعار الأول الذي يتم إرساله عندما يبدأ المستخدم الموقّت.
- افتح
EggTimerFragment.kt
وأزِل رمز الإشعار للخطوة 1.5.
// EggTimeViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager
// and call sendNotification
// val notificationManager = ContextCompat.getSystemService(
// app,
// NotificationManager::class.java
// ) as NotificationManager
// notificationManager.sendNotification(app.getString(R.string.eggs_ready), app)
- شغِّل تطبيقك مرة أخرى.
- يمكنك ضبط موقّت ووضعه في الخلفية والانتظار حتى انتهاء الوقت. سيظهر لك إشعار. هذا الإشعار أكثر فائدة.
الخطوة 4: إضافة هدف للمحتوى
- شغِّل التطبيق مرة أخرى، إذا لم يكن قيد التشغيل.
- انقر على الإشعار. لا يحدث أي تغيير.
يُعد عرض الإشعار وإبلاغ المستخدم أمرًا رائعًا، ولكن عندما ينقر المستخدم على إشعار، فإنه يتوقع العودة إلى التطبيق المتوافق. وفي هذا الجزء من الدرس التطبيقي، ستضيف نية إلى الإشعار لإعادة المستخدم إلى شاشة الموقِّت.
عنصر Intent
هو عنصر مراسلة يمكنك استخدامه لطلب اتخاذ إجراء من مكوّن تطبيق آخر. يمكن استخدام Intents لبدء نشاط أو خدمة أو بث إعلان. في هذه الحالة، يتم استخدام هذا القصد لإبلاغ النظام بفتح MainActivity
عندما ينقر المستخدم على الإشعار. لا يتوفر العديد من الخيارات هنا، لأن التطبيق يتكون من ملف شخصي واحد فقط. ومع ذلك، في التطبيق الأكبر، من المفترض أن يؤدي الإشعار إلى إنشاء تجربة سلسة من خلال نقل المستخدم إلى شاشة معقولة عند تفاعله مع الإشعار.
- افتح
NotificationUtils.kt
وابحث عن دالة الإضافةsendNotification()
. - يمكنك إنشاء
Intent
باستخدامapplicationContext
والنشاط الذي سيتم إطلاقهMainActivity::class.java
.
// NotificationUtils.kt
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
// Create the content intent for the notification, which launches
// this activity
// TODO: Step 1.11 create intent
val contentIntent = Intent(applicationContext, MainActivity::class.java)
لقد أنشأت الهدف، ولكن يتم عرض الإشعار خارج تطبيقك. ولإجراء نية الشراء خارج تطبيقك، عليك إنشاء PendingIntent
جديد.
يمنح PendingIntent
الحقوق لتطبيق آخر أو للنظام لتنفيذ عملية نيابة عن التطبيق. إنّ السمة PendingIntent
نفسها هي إشارة إلى رمز مميّز يحفظه النظام يصف البيانات الأصلية المستخدَمة لاستردادها. وهذا يعني أنه حتى في حال إنهاء عملية تقديم الطلب، ستظل PendingIntent
نفسها قابلة للاستخدام من خلال العمليات الأخرى التي تم تقديمها إليها. في هذه الحالة، سيستخدِم النظام النية بالشراء المعلّقة لفتح التطبيق نيابةً عنك، بغض النظر عما إذا كان تطبيق الموقّت قيد التشغيل أم لا.
- إنشاء
PendingIntent
باستخدامapplicationContext
وNOTIFICATION_ID
وcontentIntent
التي أنشأتها في الخطوة السابقة وعلامةPendingIntent
. تحدّد العلامةPendingIntent
خيار إنشاءPendingIntent
جديد أو استخدام علامة حالية. يجب ضبط العلامةPendingIntent.FLAG_UPDATE_CURRENT
على أنها العلامة، حيث إنك لا تريد إنشاء إشعار جديد في حال توفّر إشعار حالي. وبهذه الطريقة، ستعدّلPendingIntent
الحالية المرتبطة بالنية بالشراء.
// NotificationUtils.kt
// TODO: Step 1.12 create PendingIntent
val contentPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_ID,
contentIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
- يُرجى تمرير
PendingIntent
إلى الإشعار. يمكنك إجراء ذلك من خلال الاتصال بـsetContentIntent()
علىNotificationBuilder
. والآن، عند النقر على الإشعار، سيتم تشغيلPendingIntent
، ما يؤدي إلى فتحMainActivity
. - يمكنك أيضًا ضبط
setAutoCancel()
علىtrue
. وبالتالي، عندما ينقر المستخدم على الإشعار، يتم إغلاق الإشعار نفسه عند نقله إلى التطبيق.
// NotificationUtils.kt
// TODO: Step 1.13 set content intent
.setContentIntent(contentPendingIntent)
.setAutoCancel(true)
- شغِّل التطبيق مرة أخرى.
- يمكنك ضبط موقّت ووضع التطبيق في الخلفية والانتظار حتى ظهور الإشعار.
- بعد رؤية الإشعار، انقر على الإشعار من خلال سحب شريط الحالة لأسفل، ولاحظ كيفية عرض التطبيق في المقدّمة.
الخطوة 5: إلغاء الإشعار
فِيهْ مُوَقِّتْ شَغَّالْ مَعَ الْإِشْعَارَاتْ، بَسّْ فِيهْ مُشْكِلَة صَغِيرَة. إذا ضبطت الموقّت وتلقّيت إشعارًا وضبطت الموقّت مرة أخرى، سيبقى الإشعار السابق في شريط الحالة أثناء تشغيل الموقّت الجديد. يمكن أن يؤدي ذلك إلى إرباك المستخدم إذا كان التطبيق في الخلفية، وقد ينتج عنه بيض غير مطبوخ.
ولحل هذه المشكلة، عليك محو الإشعار السابق عند بدء موقّت جديد. ابدأ بإنشاء وظيفة إضافة أخرى في NotificationUtils.kt
. لدى NotificationManager
واجهة برمجة تطبيقات لإلغاء جميع الإشعارات النشطة التي تُسمى cancelAll
()
.
- فتح
NotificationsUtil.kt
- عليك إضافة دالة الإضافة على
NotificationManager
والتي تستدعيcancelAll()
.
// NotificationUtils.kt
// TODO: Step 1.14 Cancel all notifications
/**
* Cancels all notifications.
*
*/
fun NotificationManager.cancelNotifications() {
cancelAll()
}
- افتح
EggTimerViewModel.kt
وانتقِل إلى الدالةstartTimer()
. - في
startTimer()
، احصل على مثيلNotificationManager
من النظام واستدعِcancelNotifications()
.
// EggTimerViewModel.kt
//TODO Step 1.15 call cancel notification
val notificationManager =
ContextCompat.getSystemService(
app,
NotificationManager::class.java
) as NotificationManager
notificationManager.cancelNotifications()
- شغِّل التطبيق وابدأ الموقّت.
- بعد رؤية الإشعار، يمكنك بدء الموقِّت مرة أخرى وملاحظة كيفية حذف التطبيق للإشعار السابق تلقائيًا من شريط الحالة.
يوفّر إطار عمل الإشعارات مجموعة متنوعة من خيارات التخصيص لمطوّري البرامج لضبط الإجراءات المخصّصة وتصميم إشعاراتهم حسب الحاجة. ستتعرّف خلال هذه المهمة على كيفية تخصيص إشعارات موقّت البيض.
الخطوة 1: اختيار نمط الإشعار
وإذا أنشأت نمطًا من الإشعارات وفقًا لاحتياجاتك ومحتوى الإشعار، سيتم إبراز الإشعارات وتبدو كإضافة في تطبيقك. يتوفّر إطار عمل الإشعارات مع العديد من الأنماط المضمّنة للمساعدة، ويمكنك دائمًا إنشاء أنماط خاصة بك.
يوفّر NotificationCompat
أنماطًا مضمّنة لما يلي:
BigTextStyle
، والذي يمكنه عرض مجموعة كبيرة من النصوص، مثل عرض محتوى رسالة إلكترونية عند توسيعه.BigPictureStyle
، والذي يعرض إشعارات كبيرة الحجم تتضمن مرفقًا كبيرًا للصورة.InboxStyle
، الذي يعرض محتوى نصيًا على شكل محادثةMediaStyle
: يعرض هذا القسم عناصر التحكّم لتشغيل الوسائط.MessagingStyle
، والذي يعرض الإشعارات ذات التنسيق الكبير التي تتضمن رسائل متعددة بين أي عدد من الأشخاص.
يمكنك العثور على مزيد من المعلومات حول الأنماط الأخرى في مستندات إنشاء إشعار قابل للتوسعة. وفي هذه الخطوة، ستستخدم NotificationCompat.BigPictureStyle
لإنشاء إشعار قابل للتوسعة يعرض صورة كبيرة للبيضة عند توسيعها.
- افتح
NotificationUtils.kt
وابحث عن دالةsendNotification()
. - ابدأ بتحميل صورة من
resources
باستخدامBitmapFactory
.
// NotificationUtils.kt
// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
applicationContext.resources,
R.drawable.cooked_egg
)
- يمكنك إنشاء
BigPictureStyle
جديد وتحديد صورتك. - اضبط
bigLargeIcon()
علىnull
بحيث يختفي الرمز الكبير عند توسيع الإشعار.
// NotificationUtils.kt
// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
applicationContext.resources,
R.drawable.cooked_egg
)
val bigPicStyle = NotificationCompat.BigPictureStyle()
.bigPicture(eggImage)
.bigLargeIcon(null)
- ضبط النمط باستخدام
setStyle()
علىbigPicStyle
- يمكنك ضبط الرمز الكبير باستخدام
setLargeIcon()
علىeggImage
، حتى يتم عرض الصورة كرمز أصغر عند تصغير الإشعار.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
- تشغيل التطبيق وضبط موقّت عند عرض الإشعار لأول مرة، يصبح في الحالة المصغّرة في درج الإشعارات. في حال توسيع الإشعار، تظهر صورة كبيرة في منطقة الإشعار الموسّعة.
الخطوة 2: إجراءات الإشعارات
إجراءات الإشعارات هي تخصيص آخر يمكنك إضافته إلى إشعاراتك. تتم حاليًا إعادة توجيه الإشعارات إلى تطبيقك عندما ينقر المستخدمون عليها. بالإضافة إلى إجراء الإشعار التلقائي هذا، يمكنك إضافة أزرار الإجراءات التي تؤدي إلى إكمال مهمة متعلّقة بالتطبيق من الإشعار.
يمكن أن يقدم الإشعار ما يصل إلى ثلاثة أزرار إجراءات تتيح للمستخدم الاستجابة بسرعة، مثل تأجيل تذكير أو الرد على رسالة نصية. يجب ألا تكرِّر أزرار الإجراءات هذه الإجراء الذي يتم تنفيذه عندما ينقر المستخدم على الإشعار.
لإضافة زر إجراء، مرِّر دالة PendingIntent
إلى الدالة addAction()
على أداة الإنشاء. هذا مشابه لإعداد إجراء النقر التلقائي للإشعار عن طريق الاتصال بـ setContentIntent()
، باستثناء بدلاً من تشغيل نشاط، يمكنك تنفيذ مجموعة متنوعة من الإجراءات الأخرى، على سبيل المثال، بدء BroadcastReceiver
يؤدي مهمة في الخلفية بحيث لا تقاطع الإجراء التطبيق الذي سبق له فتحه.
في هذا الدرس التطبيقي حول الترميز، حصلت على BoadcastReceiver
بالاسم SnoozeReceiver
. ستستخدم SnoozeReceiver
لتلقي نقرة المستخدم على إجراء الإشعار. في الخطوات التالية، ستضيف رمزًا لتأجيل إشعار موقّت البيض لمدة 60 ثانية عندما ينقر المستخدم على زر الإجراء "تأجيل". عند النقر على إجراء التأجيل، سيتلقّى SnoozeReceiver
رسالة intent وينشئ منبّهًا جديدًا لإرسال إشعار جديد بعد 60 ثانية.
- فتح
SnoozeReceiver.kt
هذا الصف مشابه لصفAlarmReceiver
الذي استخدمته من قبل. وفي الخطوات التالية، ستضيف رمزًا سيؤدي إلى تشغيل دالةonReceive()
فيSnoozeReceiver
. وباختصار، سينشئ الرمز فيSnoozeReceiver
إنذارًا جديدًا لإرسال إشعار جديد بعد دقيقة واحدة. انتقِل للأسفل إلى أسفل دالة onReceived، واحصل على نسخة من ManagerManager من النظام واطلب "إلغاء الكل".
// SnoozeReceiver.kt
val notificationManager = ContextCompat.getSystemService(
context,
NotificationManager::class.java
) as NotificationManager
notificationManager.cancelAll()
- لاستخدام
SnoozeReceiver
، افتحNotificationUtils.kt
. - أنشئ
Intent
snoozeIntent
جديدة للسمةSnoozeReceiver
بعد النمط مباشرةً في دالةsendNotification()
. - أنشئ هدفًا معلّقًا من خلال استدعاء الطريقة
getBroadcast()
فيPendingIntent
والتي تتوقع المعلمات في الخطوات التالية. سيستخدم النظام جهازPendingIntent
هذا لإعداد منبّه جديد لنشر إشعار جديد بعد 60 ثانية عندما ينقر المستخدم على زر "تأجيل". - المعلمة الأولى هي سياق التطبيق الذي يجب أن يبدأ فيه
PendingIntent
النشاط. - المعلّمة الثانية هي رمز الطلب، وهو رمز الطلب لهذه النية المعلّقة. إذا كنت بحاجة إلى تعديل حالة intent هذه في انتظار المراجعة أو إلغائها، عليك استخدام هذا الرمز للوصول إلى النية بالشراء.
- بعد ذلك، أضِف العنصر
snoozeIntent
، الذي يمثل الهدف من النشاط الذي سيتم إطلاقه. - أخيرًا، أضِف قيمة العلامة
#FLAG_ONE_SHOT
بما أنّه سيتم استخدام النية مرة واحدة فقط. سيختفي الإجراء السريع والإشعار بعد النقرة الأولى، ولهذا السبب يمكن استخدام تلك intent مرة واحدة فقط.
// NotificationUtils.kt
// TODO: Step 2.2 add snooze action
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
applicationContext,
REQUEST_CODE,
snoozeIntent,
FLAGS
)
- بعد ذلك، عليك استدعاء دالة
addAction()
علىnotificationBuilder
. تتوقع هذه الدالة رمزًا ونصًا يصف الإجراء الذي تنفذه للمستخدم. عليك أيضًا إضافةsnoozeIntent
. سيتم استخدام هذا الهدف لتشغيلboadcastReceiver
الصحيح عند النقر على الإجراء.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
R.drawable.egg_icon,
applicationContext.getString(R.string.snooze),
snoozePendingIntent
)
- يمكنك تشغيل تطبيق موقّت البيض لاختبار إجراء التأجيل.
- تشغيل الموقّت ووضع التطبيق في الخلفية بعد انتهاء الموقّت، يمكنك توسيع الإشعار وسيظهر أمامك الآن زر يتضمّن إجراء تأجيل يؤدي إلى تأجيل موقّت البيض لمدة دقيقة أخرى.
الخطوة 3: أهمية الإشعار
يحدِّد مدى الأهمية التي يجب أن يؤثر بها الإشعار على المستخدم بشكل مرئي وبسمعة سمعية. ستكون الإشعارات ذات الأهمية الأعلى أكثر مقاطعة للمستخدمين.
يجب تحديد مستوى الأهمية في طريقة وضع NotificationChannel
. لقد حدّدت في الأساس قيمة منخفضة لتطبيق موقّت البيض. ويمكنك استخدام أحد مستويات الأهمية الخمسة، بدءًا من IMPORTANCE_NONE(0)
إلى IMPORTANCE_HIGH(4)
. ينطبق مستوى الأهمية الذي تحدده لقناتك على جميع رسائل الإشعارات التي تنشرها فيها.
مستويات أهمية القناة
مستوى الأهمية المرئي للمستخدم | الأهمية (Android 8.0 والإصدارات الأحدث) | الأولوية (الإصدار Android 7.1 والإصدارات الأقدم) |
يصدر صوتًا ويظهر كإشعار رأس (ينبثق في أعلى الشاشة) | ||
إصدار صوت | ||
بلا صوت | ||
بلا صوت ولا يظهر في شريط الحالة |
لمزيد من المعلومات حول اختيار مستوى الأولوية المناسب، راجع "،مستويات الأولوية&" في دليل تصميم الإشعارات. يجب توخي الحذر عند اختيار مستوى الأهمية للإشعارات في تطبيقك، ويجب اختيار أهمية القناة مع مراعاة وقت المستخدم وانتباهه. عندما يؤدي وضع إشعار غير مهم على هيئة عاجلة، يمكن أن يؤدي ذلك إلى منبّه غير ضروري ويشتّت الانتباه. يمكن للمستخدمين التحكّم بشكل كامل في مستوى أهمية الإشعارات، لذا إذا أنشأت إشعارًا مزعجًا، يمكنهم إيقاف قناة الإشعارات بالكامل.
عندما أنشأت الإشعار في الخطوة 1.6 لأول مرة، تم ضبط موقّت البيضة لإرسال إشعارات ذات أولوية منخفضة لأنه تم تصميمه لعدم إزعاج المستخدم بالإشعارات. ومع ذلك، قد يكون من المفيد جذب انتباه المستخدم قبل طهي البيض بشكل مفرط. لتغيير مستوى أهمية الإشعار، يمكنك البدء بإعدادات القناة. تؤثر أهمية القناة على مستوى انقطاع كل الإشعارات المنشورة في القناة، ويجب تحديدها في المُنشئ NotificationChannel
.
- لتغيير مستوى أهمية قناة الإشعارات في تطبيقك، افتح
EggTimerFragment.kt
وانتقِل إلىcreateChannel()
. تغيير مستوى الأهمية منIMPORTANCE_LOW
إلىIMPORTANCE_HIGH
.
// EggTimerFragment.kt
val notificationChannel = NotificationChannel(
channelId,
channelName,
// TODO: Step 2.4 change importance
NotificationManager.IMPORTANCE_HIGH
)
لإتاحة الأجهزة التي تعمل بنظام التشغيل Android 7.1 (المستوى 25 من واجهة برمجة التطبيقات) أو الإصدارات الأقدم، يجب أيضًا الاتصال بالرقم setPriority()
لكل إشعار باستخدام ثابت الأولوية من الفئة NotificationCompat
.
- افتح
NotificationUtils.kt
وأضِف ما يلي إلى عنصر أداة إنشاء الإشعارات.
// NotificationUtils.kt
.addAction(
R.drawable.common_google_signin_btn_icon_dark,
applicationContext.getString(R.string.snooze),
snoozePendingIntent
)
// TODO: Step 2.5 set priority
.setPriority(NotificationCompat.PRIORITY_HIGH)
- قبل تشغيل التطبيق، انقر مع الاستمرار على رمز التطبيق على جهازك أو المحاكي واختَر إلغاء التثبيت لمحو إعدادات القناة السابقة. في حال تعذّر إلغاء تثبيت التطبيق، لن تتغير إعدادات أولوية القناة، ولن ينتج عن ذلك أي تغيير في السلوك عند نشر الإشعار.
- شغِّل التطبيق الآن مرة أخرى وابدأ الموقّت. هذه المرة، عندما يتم تسليم الإشعار، من المفترض أن تظهر نافذة منبثقة في أعلى الشاشة، بغض النظر عما إذا كان التطبيق يعمل في المقدّمة أو الخلفية.
الخطوة 4: شارات الإشعارات
شارات الإشعارات هي نقاط صغيرة تظهر على رمز مشغّل التطبيقات للتطبيق المرتبط عندما يحتوي التطبيق على إشعار نشط. ويمكن للمستخدمين الضغط مع الاستمرار على رمز التطبيق للاطّلاع على الإشعارات.
تظهر هذه النقاط المعروفة باسم الشارات تلقائيًا، ولا يلزم أن ينفّذ تطبيقك أي إجراء، ولكن قد تكون هناك حالات لا تسري فيها الشارات على الإشعارات، لذا يمكنك إيقافها على أساس كل قناة من خلال استدعاء setShowBadge(false)
في الكائن NotificationChannel
. وبما أنّ موقّت البيض يحتوي على إشعار نشط واحد فقط في وقت معيّن، لا تقدّم الشارة على رمز تطبيقك أي فائدة للمستخدمين. في الخطوات التالية، عليك إيقاف الشارة وعرض إشعار لموقت البيض فقط.
- أضِف
setShowBadge(false)
إلى رمز إنشاء القناة لموقّت البيض لإيقاف الشارات.
// EggTimerFragment.kt
).apply {
// TODO: Step 2.6 disable badges for this channel
setShowBadge(false)
}
- شغِّل التطبيق مرة أخرى وابدأ الموقّت وشاهد رمز التطبيق. من المفترض ألا ترى أي شارات على رمز التطبيق.
يمكنك العثور على رمز الحل في الفرع الرئيسي للرمز الذي تم تنزيله.
- استخدم صف NotificationsManager لإنشاء إشعار وإرساله وتحديثه وإلغائه باستخدام.
- استخدِم العنصر NotificationChannel مع طريقة createNotificationChannel لضبط قناة للإشعار.
- استخدم addAction() لإضافة إجراءات سريعة إلى إشعار.
- استخدِم setShowBadge() لتفعيل الشارات أو إيقافها.
- يمكنك اختيار نمط الإشعارات باستخدام أنماط تمتد من Notification.Style
- ضبط مستوى الأهمية باستخدام NotificationChannel.setImportance()
دورة Udacity:
مستندات مطوّر برامج Android:
للحصول على روابط إلى دروس تطبيقية أخرى حول الترميز في هذه الدورة التدريبية، اطّلِع على الصفحة المقصودة للإصدارات المتقدّمة من Android في لغة ترميز Kotlin.