الإشعار المحلي هو رسالة يرسلها التطبيق إلى المستخدم دون مشاركة خادم عن بُعد. تتم معالجة جميع البيانات وعرضها مباشرة على جهاز المستلم. هذه الآلية مناسبة للتذكيرات والمؤقتات والمنبهات عندما يكون التطبيق في الخلفية أو مغلقًا. وفقًا لوثائق مطوري Apple، يوفر UNUserNotificationCenter إدارة مركزية للإشعارات المحلية على iOS.
النقاط الرئيسية
الإشعار المحلي هو رسالة تشغيلية يتم إنشاؤها وعرضها بواسطة نظام التشغيل على نفس الجهاز الذي تم تثبيت التطبيق عليه. على عكس الإشعارات الفورية، لا تمر الإشعارات المحلية عبر خادم خارجي — كل منطق الجدولة يعمل على العميل.
تعمل هذه الإشعارات بغض النظر عن حالة التطبيق: نشط أو مصغر أو مغلق بالكامل. يتولى نظام التشغيل مهمة التوصيل في الوقت المحدد، بينما يحدد المطور فقط المحتوى والمشغل.
يضمن النظام توصيل الإشعار المحلي حتى في حالة عدم وجود اتصال بالشبكة. هذه ميزة رئيسية على الإشعارات الفورية التي تتطلب اتصال إنترنت مستقر وخادم عامل.
يتكون كل إشعار محلي من ثلاثة أجزاء: المحتوى (العنوان، النص، الصوت)، المشغل (شرط زمني أو جغرافي) ومعرف الطلب. يسمح المعرف بإلغاء أو تحديث الإشعار قبل توصيله.
يمكن للمطور جدولة ما يصل إلى 64 إشعارًا محليًا لكل تطبيق على iOS وعدد غير محدود على Android. هذا الاختلاف ناتج عن قيود معمارية لأنظمة التشغيل.
توفر كلتا المنصتين واجهات برمجة تطبيقات خاصة بهما للعمل مع الإشعارات المحلية. على iOS، المكون المركزي هو UNUserNotificationCenter، على Android — NotificationManager. على الرغم من اختلاف الواجهات، فإن المنطق هو نفسه: ينشئ التطبيق طلبًا، ويسجله في النظام، ويقوم نظام التشغيل بتوصيل الإشعار في الوقت المحدد.
يستخدم iOS UNCalendarNotificationTrigger للأحداث التقويمية، وUNTimeIntervalNotificationTrigger للفترات الزمنية، وUNLocationNotificationTrigger للموقع الجغرافي. يقدم Android AlarmManager وWorkManager والجدولة الدقيقة عبر setExact.
منذ Android 12 — SCHEDULE_EXACT_ALARM يتطلب إذنًا خاصًا من المستخدم. على iOS، يتم طلب الإذن مرة واحدة عبر UNUserNotificationCenter.requestAuthorization، ويختار المستخدم مستوى الوصول: اللافتات، الأصوات، الشارات.
تصنف الإشعارات المحلية حسب نوع المشغل، وليس حسب المحتوى. يحدد كل نوع متى وتحت أي ظروف سيتم عرض الإشعار للمستخدم.
على iOS وAndroid، يتم تنفيذ أنواع المشغلات بشكل مختلف، على الرغم من أن التصنيف المنطقي هو نفسه. يستخدم iOS UNCalendarNotificationTrigger للتواريخ، وUNTimeIntervalNotificationTrigger للفترات الزمنية، وUNLocationNotificationTrigger للموقع الجغرافي. يقدم Android AlarmManager مع setExact وsetRepeating، بالإضافة إلى WorkManager للمهام المؤجلة.
| نوع المشغل | الوصف | مثال |
|---|---|---|
| فاصل زمني | إشعار بعد N ثانية من التشغيل | مؤقت العد التنازلي |
| تاريخ تقويمي | إشعار في وقت وتاريخ محددين | تذكير باجتماع |
| موقع جغرافي | إشعار عند الدخول/الخروج من منطقة | تذكير في المتجر |
| فوري | توصيل فوري عند استدعاء API | إشعار تنزيل |
يدعم iOS أيضًا UNNotificationAttachment — إرفاق صورة أو صوت أو فيديو بجسم الإشعار. يدعم Android قوالب مخصصة بأزرع وصور كبيرة عبر NotificationCompat.Style.
يعتمد اختيار المشغل على السيناريو: تذكيرات التقويم تعمل بشكل أفضل مع مشغلات التقويم، والتذكيرات الجغرافية مع الموقع الجغرافي. مشغلات الفاصل الزمني مناسبة للأحداث المتكررة بفترة ثابتة.
على iOS، يتم توصيل الإشعارات المحلية بواسطة النظام حتى عند إغلاق التطبيق — يدير UNUserNotificationCenter قائمة الانتظار بشكل مستقل. على Android، يعتمد التوصيل على الآلية المختارة: يعمل AlarmManager حتى مع إيقاف تشغيل الشاشة، بينما يراعي WorkManager توفير الطاقة.
تحل الإشعارات المحلية المهام التي تكون فيها البنية التحتية الخارجية زائدة عن الحاجة أو غير متاحة. السيناريوهات الرئيسية: التذكيرات، المؤقتات، نصائح الإعداد، والإجراءات المؤجلة.
تظهر أبحاث Localytics أن التطبيقات التي تستخدم التذكيرات المحلية تحتفظ بنسبة 35% أكثر من المستخدمين في الأسبوع الأول بعد التثبيت. هذا يجعل الإشعارات المحلية أداة قوية للإعداد.
من المهم عدم الإفراط في الاستخدام — يقوم النظام نفسه بتجميع الإشعارات من نفس التطبيق، ويمكن للمستخدم تعطيل جميع الإشعارات المحلية إذا أصبحت مزعجة. التردد الأمثل هو لا يزيد عن 2–3 إشعارات في اليوم للأحداث غير الحرجة.
لجدولة إشعار محلي على Android، استخدم NotificationManager مع AlarmManager. على Android 8+، يجب أولاً إنشاء قناة إشعارات، وإلا لن يتم عرض الإشعار.
val channelId = "reminder_channel"
val notificationId = "task_reminder_42"
val channel = NotificationChannel(
channelId,
"تذكيرات",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "قناة لتذكيرات المهام"
}
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
val intent = Intent(this, ReminderReceiver::class.java).apply {
putExtra("notification_id", notificationId)
putExtra("channel_id", channelId)
}
val pendingIntent = PendingIntent.getBroadcast(
this, notificationId.hashCode(),
intent, PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = getSystemService(AlarmManager::class.java)
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTimeMillis,
pendingIntent
)
على Android 12+، تحقق من إذن SCHEDULE_EXACT_ALARM قبل استدعاء setExact. إذا لم يتم منح الإذن — استخدم setWindow، الذي يضمن التوصيل ضمن نافذة زمنية.
عند تشغيل AlarmManager، يرسل النظام Intent بث يستقبله BroadcastReceiver. داخله، تحتاج إلى إنشاء وعرض الإشعار عبر NotificationManager. تأكد من أن PendingIntent يستخدم FLAG_UPDATE_CURRENT، وإلا ستستمر الإشعارات القديمة في استخدام Intent قديم عند تغيير البيانات.
على iOS، يتم إنشاء الإشعارات المحلية عبر UNUserNotificationCenter باستخدام UNMutableNotificationContent وأحد المشغلات. قبل الجدولة، يجب طلب الإذن من المستخدم.
import UserNotifications
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
guard granted else { return }
}
let content = UNMutableNotificationContent()
content.title = "تذكير بمهمة"
content.body = "لا تنسَ إكمال التقرير بحلول الساعة 18:00"
content.sound = .default
content.userInfo = ["task_id": "42"]
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 3600,
repeats: false
)
let request = UNNotificationRequest(
identifier: "task_reminder_42",
content: content,
trigger: trigger
)
center.add(request)
يدعم iOS ما يصل إلى 64 طلب إشعار محلي متزامن. إذا تم تجاوز الحد، يرفض النظام الطلبات الجديدة حتى يتم توصيل الطلبات النشطة أو إلغاؤها. استخدم getPendingNotificationRequests للتحقق من قائمة الانتظار الحالية.
عندما يتفاعل المستخدم مع إشعار محلي على iOS، يتم استدعاء طريقة userNotificationCenter:didReceive response لمفوض UNUserNotificationCenterDelegate. توفر هذه الطريقة معرف الطلب وactionIdentifier (أي زر تم الضغط عليه) وuserInfo المخصص. هذا يسمح بالتمييز بين فتح الإشعار البسيط والضغط على زر إجراء معين.
لجعل الإشعارات المحلية مفيدة بدلاً من أن تكون مزعجة، اتبع عدة قواعد رئيسية. أولاً: تحكم في التردد — لا يزيد عن 2–3 إشعارات في اليوم للأحداث غير الحرجة، وإلا سيعطل المستخدم جميع إشعارات التطبيق.
ثانيًا: امنح المستخدم خيارًا. أضف في الواجهة إمكانية تعطيل أنواع معينة من الإشعارات المحلية. على Android، استخدم NotificationChannel منفصل بأهمية منخفضة؛ على iOS، استخدم فئة منفصلة في إعدادات التطبيق.
ثالثًا: الملاءمة السياقية — يجب أن يظهر الإشعار عندما يحتاجه المستخدم. المشغلات الجغرافية مثالية للتذكيرات بالقرب من المنزل، مشغلات التقويم للاجتماعات، مشغلات الفاصل الزمني للأنشطة المنتظمة مثل شرب الماء أو التمدد. لا تخلط الأنواع دون داع.
رابعًا: اختبر على أجهزة حقيقية. محاكي iOS لا يحاكي جميع سيناريوهات توصيل الإشعارات المحلية، خاصة في الخلفية. على Android، استخدم adb shell dumpsys notification للتحقق من قائمة انتظار الإشعارات المجدولة ومعلماتها. خامسًا: قدم دائمًا للمستخدم إمكانية تعطيل الإشعارات عبر واجهة التطبيق — هذا شرط إلزامي لتجربة المستخدم وإرشادات مراجعة App Store.
الأسئلة الشائعة
الإشعار المحلي تتم جدولته وتوصيله بواسطة الجهاز دون مشاركة الخادم. الإشعار الفوري يتطلب خدمة خارجية (FCM, APNS) واتصال إنترنت. الإشعارات المحلية تعمل بدون اتصال، بينما الفورية تعمل فقط عند توفر الشبكة.
iOS يحدد بـ 64 طلبًا مجدولاً متزامنًا. Android ليس لديه حد صارم، لكن أكثر من 500 إشعار قد يقلل من أداء النظام ويؤثر على وقت التوصيل.
نعم، على iOS استخدم removePendingNotificationRequests مع معرف الطلب. على Android، استدع NotificationManager.cancel أو ألغِ PendingIntent عبر AlarmManager. المعرف الفريد إلزامي للإلغاء.
على iOS، الإذن إلزامي عبر requestAuthorization. على Android 13+ (Tiramisu)، مطلوب أيضًا إذن POST_NOTIFICATIONS. الإصدارات الأقدم من Android لا تتطلب إذنًا صريحًا للإشعارات المحلية.
على iOS، أنشئ UNNotificationAction وأضفه إلى UNNotificationCategory. على Android، استخدم NotificationCompat.Builder.addAction مع PendingIntent موجه إلى BroadcastReceiver. كل زر يشغل إجراء منفصل في التطبيق.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا