AlarmManager هي خدمة نظام Android تتيح للتطبيقات تنفيذ المهام في وقت محدد، حتى إذا كان التطبيق غير قيد التشغيل أو كان الجهاز في وضع السكون. على عكس JobScheduler أو WorkManager، يضمن AlarmManager دقة التشغيل، مما يجعله لا غنى عنه للمنبهات وتذكيرات التقويم والمهام الحرجة من حيث وقت التنفيذ. وفقًا لـ Android Developers, 2026، اعتبارًا من Android 4.4، يتصرف setRepeating كتكرار غير دقيق، وتتطلب المنبهات الدقيقة setExact أو setAlarmClock.
الخلاصة
AlarmManager هي خدمة نظام Android توفر API لجدولة المهام مع وقت تنفيذ دقيق أو تقريبي. إنها موجودة منذ الإصدار الأول من Android ولا تزال الطريقة الموثوقة الوحيدة لتنفيذ التعليمات البرمجية في لحظة محددة، بغض النظر عن حالة التطبيق والجهاز.
مبدأ العمل بسيط: يرسل التطبيق إلى النظام PendingIntent مع وقت التشغيل المحدد. عندما يحين الوقت المحدد، يرسل النظام Intent إلى BroadcastReceiver مسجل أو يبدأ Service. حتى إذا كان الجهاز في وضع السكون، يسمح WakeLock للمعالج بالاستيقاظ ومعالجة الحدث.
مجال التطبيق الرئيسي لـ AlarmManager هو المهام التي تتطلب توقيتًا دقيقًا: المنبهات وتذكيرات التقويم وتشغيل العمليات الطويلة في ساعة محددة. بالنسبة للمهام حيث الدقة غير حرجة (المزامنة اليومية)، يوصي Google باستخدام WorkManager أو JobScheduler لأنهما أكثر كفاءة في استهلاك الطاقة.
AlarmManager يستقبل PendingIntent ووقت التشغيل من التطبيق. يحفظ النظام هذا الطلب في المجدول الداخلي الخاص به ويوقظ المعالج في الوقت المحدد لتسليم Intent. يجب على المطور تسجيل BroadcastReceiver مسبقًا للتعامل مع هذا Intent.
AlarmManager يدعم 4 أنواع من المنبهات: ELAPSED_REALTIME (الوقت منذ الإقلاع، لا يوقظ)، RTC (الوقت الحقيقي، لا يوقظ)، ELAPSED_REALTIME_WAKEUP (الوقت منذ الإقلاع، يوقظ الجهاز)، وRTC_WAKEUP (الوقت الحقيقي، يوقظ). إصدارات WAKEUP ضرورية إذا كان يجب تنفيذ المهمة حتى عندما يكون الجهاز نائمًا.
| النوع | الوقت | يوقظ | مثال |
|---|---|---|---|
| ELAPSED_REALTIME | منذ الإقلاع | لا | مؤقت التشغيل |
| RTC | طابع زمني Unix | لا | تسجيل |
| ELAPSED_REALTIME_WAKEUP | منذ الإقلاع | نعم | مهمة دورية |
| RTC_WAKEUP | طابع زمني Unix | نعم | منبه |
اعتبارًا من Android 12 (API 31)، يتطلب استخدام المنبهات الدقيقة (setExact) الإذن SCHEDULE_EXACT_ALARM. يمكن للمستخدم إلغاءه من خلال الإعدادات. للتطبيقات التي تحتاج إلى منبه دقيق مع عرض (مثل تطبيقات الساعة)، يتم استخدام USE_EXACT_ALARM الذي يُمنح أثناء التثبيت.
AlarmManager يوفر ثلاث طرق رئيسية لجدولة المهام. يحدد اختيار الطريقة دقة التشغيل والتأثير على استهلاك طاقة الجهاز.
set — الطريقة الأساسية للتشغيل الفردي غير الدقيق. قد يغير النظام الوقت بما يصل إلى بضع دقائق للتجميع مع أحداث أخرى. مناسبة للمهام حيث الدقة غير حرجة: تذكيرات لفتح التطبيق.
setRepeating — طريقة للتكرارات الدورية. منذ Android 4.4 (API 19)، أصبح setRepeating غير دقيق — قد تختلف الفواصل الزمنية. لم يعد النظام يضمن فترة ثابتة. بدلاً من setRepeating، يوصى باستخدام setExact مع إعادة الجدولة أو WorkManager مع PeriodicWorkRequest.
setExact — طريقة للتشغيل الفردي الدقيق. يوقظ النظام الجهاز في أقرب وقت ممكن من الوقت المحدد. setAlarmClock هو حالة خاصة من setExact تعرض أيضًا أيقونة منبه في شريط الحالة ولها الأولوية القصوى بين جميع أنواع المنبهات.
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// منبه دقيق لمرة واحدة
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
this, 0, intent,
PendingIntent.FLAG_IMMUTABLE
)
alarmManager.setAlarmClock(
AlarmManager.AlarmClockInfo(
targetTime, pendingIntent
),
pendingIntent
)
سيناريو نموذجي هو إنشاء تذكير يومي في وقت محدد. يتم استخدام RTC_WAKEUP مع setExact لهذا الغرض. عند التشغيل، يطلق BroadcastReceiver إشعارًا أو Service. بعد المعالجة، يجب إعادة جدولة المهمة لليوم التالي.
class ReminderReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
val notification = NotificationCompat.Builder(
context, "reminder_channel"
)
.setContentTitle("تذكير")
.setContentText("حان وقت إكمال المهمة")
.setSmallIcon(R.drawable.ic_reminder)
.build()
notificationManager.notify(1001, notification)
}
}
للتكرار اليومي، يتم استخدام setExact مع حساب وقت التشغيل التالي. يمكن تمرير العلامات في Intent لتحديد أنواع مختلفة من التذكيرات. تأكد من تسجيل BroadcastReceiver في AndroidManifest.xml مع معالجة إجراء WAKEUP.
fun scheduleDailyReminder(context: Context, hour: Int, minute: Int) {
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
set(Calendar.SECOND, 0)
if (before(Calendar.getInstance())) {
add(Calendar.DAY_OF_MONTH, 1)
}
}
val alarmManager =
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
pendingIntent
)
}
AlarmManager أداة قوية لكنها تستهلك طاقة كبيرة. كل منبه WAKEUP يخرج الجهاز من وضع السكون، مما يستهلك طاقة البطارية. توصي Google بتقليل استخدام المنبهات الدقيقة وتفضيل setExactAndAllowWhileIdle على Android 6+ لتقليل التأثير على Doze Mode. للمهام الدورية بدون متطلبات دقة، استخدم WorkManager مع PeriodicWorkRequest الذي لا يتطلب إيقاظ الجهاز ولا يستنزف البطارية في كل تنفيذ.
لاختبار AlarmManager، استخدم TestAlarmManager من Android Test Framework. يسمح بمحاكاة تشغيل المنبه دون انتظار الوقت الحقيقي. يوفر Robolectric ShadowAlarmManager الذي يعترض استدعاءات set وsetExact وsetRepeating، مما يوفر طرقًا للتشغيل القسري والتحقق من عدد المهام المجدولة. لاختبارات الوحدة لـ BroadcastReceiver، استخدم Robolectric.getForegroundScheduler(). تتوفر أيضًا اختبارات Espresso مع IdlingResource التي تنتظر تشغيل المنبه في اختبارات التكامل.
إذا كان تطبيقك يستخدم AlarmManager للمهام الدورية التي لا تتطلب توقيتًا دقيقًا، ففكر في الترحيل إلى WorkManager. يستبدل PeriodicWorkRequest بفاصل زمني أدنى 15 دقيقة setRepeating، بينما يضمن WorkManager التنفيذ بعد إعادة التشغيل، ويتعامل مع Doze Mode، ولا يتطلب الإذن SCHEDULE_EXACT_ALARM. للمهام الحرجة من حيث الوقت (منبه الساعة 7 صباحًا)، يظل AlarmManager هو الخيار الصحيح الوحيد. الاستراتيجية المثلى هي استخدام AlarmManager فقط للمنبهات مع setAlarmClock، ونقل جميع المهام الخلفية الأخرى إلى WorkManager.
للمهام الدورية بدون متطلبات دقة، استخدم WorkManager مع PeriodicWorkRequest. للمهام ذات التوقيت الدقيق ولكن غير الحرجة للتشغيل في وضع السكون — استخدم setExact بدون WAKEUP. وفقط للمنبهات مع التنبيه الإجباري — استخدم setAlarmClock أو RTC_WAKEUP.
من المهم أيضًا التحقق من وجود الإذن SCHEDULE_EXACT_ALARM على Android 12+. إذا لم يتم منح الإذن، سيعمل setExact كـ set عادي (غير دقيق). استخدم AlarmManager.canScheduleExactAlarms() للتحقق. إذا كان الإذن مفقودًا، يمكنك مطالبة المستخدم بالذهاب إلى الإعدادات عبر Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).
ميزة مهمة جدًا في AlarmManager — جميع المنبهات المجدولة يتم إعادة تعيينها بعد إعادة تشغيل الجهاز. لاستعادتها، يجب عليك تعريف BroadcastReceiver يعالج Intent.ACTION_BOOT_COMPLETED وإعادة جدولة جميع المنبهات النشطة في طريقة onReceive. بدون هذا، سيفقد المستخدم جميع التذكيرات بعد إيقاف تشغيل الهاتف وتشغيله.
class BootReceiver : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
if (intent.action ==
Intent.ACTION_BOOT_COMPLETED
) {
val prefs =
context.getSharedPreferences("alarms", 0)
val savedTime =
prefs.getLong("next_alarm", 0L)
if (savedTime > System.currentTimeMillis()) {
scheduleReminder(context, savedTime)
}
}
}
}
من الناحية العملية، يظل AlarmManager أفضل حل لتطبيقات المنبه والتقويم وتذكيرات الأدوية وأي مهام حيث يكون وقت التنفيذ حرجًا للمستخدم. لجميع سيناريوهات العمل الخلفي الأخرى، يُفضل WorkManager أو JobScheduler.
عند الاختيار بين AlarmManager وWorkManager، اتبع هذه القاعدة: إذا طلب المستخدم صراحة تذكيرًا في الساعة 2:30 مساءً — استخدم AlarmManager مع setAlarmClock. إذا كانت المهمة يجب أن تنفذ «مرة واحدة تقريبًا في الساعة» — سيكون WorkManager مع PeriodicWorkRequest أكثر كفاءة في استهلاك الطاقة وأكثر موثوقية.
الأسئلة الشائعة
كلا الطريقتين تضمنان التشغيل الدقيق، لكن setAlarmClock يعرض أيضًا أيقونة منبه في شريط الحالة ويخبر النظام أنه منبه للمستخدم. على Android 6+، يتمتع setAlarmClock بحصانة من Doze Mode، بينما قد يتم تأخير setExact.
بعد إعادة التشغيل، يتم إعادة تعيين جميع المنبهات المجدولة. لاستعادتها، يجب تسجيل BroadcastReceiver لإجراء BOOT_COMPLETED وإعادة جدولة جميع المهام في onReceive. بدون هذا، لن يتم تشغيل أي منبه بعد تشغيل الجهاز.
منذ API 19، أصبح setRepeating غير دقيق — قد يغير النظام الفواصل الزمنية لتوفير الطاقة. بدلاً من ذلك، استخدم setExact مع إعادة الجدولة اليدوية أو WorkManager مع PeriodicWorkRequest الذي يوفر سلوكًا أكثر قابلية للتنبؤ.
لـ setExact، الإذن SCHEDULE_EXACT_ALARM مطلوب، ويمكن للمستخدم منحه أو إلغاؤه في الإعدادات. لـ setAlarmClock مع عرض واجهة الساعة، يتم استخدام USE_EXACT_ALARM الذي يُمنح تلقائيًا عند التثبيت من المتجر.
لا، AlarmManager يعمل دائمًا من خلال PendingIntent. يمكن أن يكون PendingIntent.getBroadcast لـ BroadcastReceiver أو PendingIntent.getService لـ Service أو PendingIntent.getActivity لـ Activity. بدون PendingIntent، لا يمكن للنظام تسليم الحدث إلى التطبيق.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.