AlarmManager
) طريقة لتنفيذ
عمليات مستندة إلى الوقت خارج مدة نشاط تطبيقك.
على سبيل المثال، يمكنك استخدام المنبّه لبدء عملية تستغرق وقتًا طويلاً، مثل
بدء خدمة مرة واحدة في اليوم لتنزيل توقّعات الطقس.
تتسم التنبيهات بالخصائص التالية:
تتيح لك هذه الميزة تشغيل "المقصودات" في أوقات و/أو فواصل زمنية محدّدة.
ويمكنك استخدامها مع أجهزة استقبال البث لتحديد مواعيد المهام أو WorkRequests لتنفيذ عمليات أخرى.
تعمل هذه الخدمات خارج نطاق تطبيقك، لذا يمكنك استخدامها لبدء الأحداث أو الإجراءات حتى في حال عدم تشغيل تطبيقك، وحتى إذا كان الجهاز في وضع السكون.
وتساعدك هذه الأدوات في تقليل متطلبات الموارد لتطبيقك. يمكنك جدولة العمليات بدون الاعتماد على الموقّتات أو الخدمات التي تعمل باستمرار.
ضبط منبّه غير دقيق
عندما يضبط أحد التطبيقات منبّهًا غير دقيق، يُرسِل النظام المنبّه في وقت معيّن في المستقبل. توفّر الإنذارات غير الدقيقة بعض الضمانات بشأن توقيت إرسال الإنذار مع الالتزام بقيود توفير البطارية، مثل وضع السكون.
يمكن للمطوّرين الاستفادة من ضمانات واجهة برمجة التطبيقات التالية لتخصيص توقيت إرسال التنبيهات غير الدقيقة.
إرسال تنبيه بعد وقت محدّد
إذا كان تطبيقك يستدعي set()
،
setInexactRepeating()
،
أو setAndAllowWhileIdle()
،
لن يرن المنبّه أبدًا قبل وقت التفعيل المقدَّم.
في نظام التشغيل Android 12 (المستوى 31 من واجهة برمجة التطبيقات) والإصدارات الأحدث، يشغِّل النظام المنبّه في مهلة تبلغ ساعة واحدة من وقت التفعيل المقدَّم، ما لم تكن أي قيود لتوفير طاقة البطارية مفعَّلة، مثل ميزة توفير شحن البطارية أو وضع "الاستراحة".
إرسال تنبيه خلال فترة زمنية
إذا كان تطبيقك يستدعي setWindow()
، لن يتم إطلاق المنبّه أبدًا قبل وقت التفعيل الذي تم تقديمه. ما لم تكن أي قيود لتوفير البطارية سارية، يتم بث المنبّه
خلال الفترة الزمنية المحدّدة، بدءًا من وقت التفعيل
المحدّد.
إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو إصدارًا أحدث، يمكن للنظام تأخير
تشغيل إنذار غير دقيق ضمن فترة زمنية بمقدار 10 دقائق على الأقل. لهذا السبب، تتم إزالة قيم مَعلمة windowLengthMillis
ضمن 600000
لتصبح قيمها 600000
.
إرسال منبّه متكرّر على فترات منتظمة تقريبًا
إذا كان تطبيقك يستدعي setInexactRepeating()
،
يُشغِّل النظام إنذارات متعددة:
- يرنّ المنبّه الأول خلال الفترة الزمنية المحدّدة، بدءًا من وقت التفعيل المحدّد.
- يتم عادةً تفعيل المنبّهات اللاحقة بعد انقضاء الفترة الزمنية المحدّدة. يمكن أن يختلف الوقت بين عمليتَي تشغيل متتاليتَين للمنبّه.
ضبط منبّه محدّد الوقت
يُشغِّل النظام منبّهًا دقيقًا في لحظة محدّدة في المستقبل.
يمكن لمعظم التطبيقات جدولة المهام والأحداث باستخدام إنذارات غير دقيقة لإكمال عدة حالات استخدام شائعة. إذا كانت الوظيفة الأساسية لتطبيقك تعتمد على منبّه محدَّد الوقت بدقة، مثل تطبيق ساعة منبّه أو تطبيق تقويم، فلا بأس باستخدام منبّه محدَّد الوقت بدلاً من ذلك.
حالات الاستخدام التي قد لا تتطلّب منبّهات محدَّدة الوقت
تعرض القائمة التالية سير العمل الشائع الذي قد لا يتطلّب منبّهًا محدَّدًا:
- جدولة عمليات تحديد التوقيت أثناء مدة استخدام تطبيقك
- تتضمّن فئة
Handler
عدة methods جيدة لمعالجة العمليات المتعلقة بالتوقيت، مثل تنفيذ بعض الأعمال كل n ثانية عندما يكون تطبيقك قيد التشغيل:postAtTime()
وpostDelayed()
. يُرجى العِلم أنّ واجهات برمجة التطبيقات هذه تعتمد على وقت عمل النظام وليس الوقت الفعلي. - المهام المجدوَلة التي يتم تنفيذها في الخلفية، مثل تحديث التطبيق وتحميل السجلات يوفّر
WorkManager
طريقة لتحديد موعد لعمل دوار حساس زمنيًا. يمكنك تقديم فاصل تكرار وflexInterval
(15 دقيقة بحد أدنى) لتحديد وقت تشغيل دقيق للعمل.- إجراء يحدّده المستخدم من المفترض أن يحدث بعد وقت محدّد (حتى إذا كان النظام في حالة السكون)
- استخدام منبّه غير دقيق يُرجى الاتصال بالرقم التالي:
setAndAllowWhileIdle()
. - إجراء يحدّده المستخدم من المفترض أن يحدث بعد وقت محدّد
- استخدام منبّه غير دقيق يُرجى الاتصال بالرقم التالي:
set()
. - إجراء يحدّده المستخدم ويمكن أن يحدث خلال فترة زمنية محدّدة
- استخدام منبّه غير دقيق يُرجى الاتصال بالرقم التالي:
setWindow()
. يُرجى العِلم أنّه إذا كان تطبيقك يستهدف الإصدار Android 12 أو إصدارًا أحدث، فإنّ أصغر مدة مسموح بها للنافذة هي 10 دقائق.
طرق ضبط منبّه محدّد الوقت
يمكن لتطبيقك ضبط المنبّهات المحددة الوقت باستخدام إحدى الطريقتَين التاليتَين: يتم ترتيب هذه الطرق بحيث تؤدي الطرق الأقرب إلى أسفل القائمة مهَمًا أكثر أهمية من حيث الوقت، ولكنها تتطلّب المزيد من موارد النظام.
setExact()
تشغيل منبّه في وقت دقيق تقريبًا في المستقبل، ما دامت تدابير توفير البطارية الأخرى غير مفعّلة
استخدِم هذه الطريقة لضبط المنبّهات المحدّدة الوقت، ما لم يكن عمل تطبيقك مرتبطًا بوقت محدّد بالنسبة إلى المستخدم.
setExactAndAllowWhileIdle()
تشغيل منبّه في وقت دقيق تقريبًا في المستقبل، حتى إذا كانت تدابير توفير شحن البطارية مفعّلة
setAlarmClock()
تشغيل منبّه في وقت محدد في المستقبل ولأنّ هذه التنبيهات مرئية للمستخدمين بشكل كبير، لا يعدّل النظام وقت إرسالها مطلقًا. يحدِّد النظام هذه المنبّهات على أنّها الأكثر أهمية ويترك الأوضاع المنخفضة الطاقة إذا لزم الأمر لعرض المنبّهات.
استهلاك موارد النظام
عندما يشغِّل النظام المنبّهات الدقيقة التي يضبطها تطبيقك، يستهلك الجهاز موارد كبيرة، مثل عمر البطارية، خاصةً إذا كان في وضع توفير الطاقة. بالإضافة إلى ذلك، لا يمكن للنظام تجميع هذه الطلبات بسهولة من أجل استخدام الموارد بكفاءة أكبر.
ننصحك بشدة بإنشاء إنذار غير دقيق كلما
أمكن. لتنفيذ عمل أطول، يمكنك جدولته باستخدام
WorkManager
أو
JobScheduler
من
BroadcastReceiver
المنبّه. لتنفيذ عمل معيّن أثناء
وضع الجهاز في وضع "الاستراحة الذكية"، يمكنك إنشاء منبّه غير محدَّد الوقت باستخدام
setAndAllowWhileIdle()
،
وبدء مهمة من المنبّه.
تقديم بيان بشأن إذن استخدام المنبّهات المحدَّدة الوقت المناسب
إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث، يجب الحصول على إذن الوصول الخاص للتطبيق
"المنبّهات والتذكيرات". لإجراء ذلك، يجب إدراج الإذن
SCHEDULE_EXACT_ALARM
في ملف بيان تطبيقك، كما هو موضّح في مقتطف الرمز البرمجي التالي:
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
إذا كان تطبيقك يستهدف الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يمكنك
الإفصاح عن إذن SCHEDULE_EXACT_ALARM
أو إذن USE_EXACT_ALARM
.
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
على الرغم من أنّ إذنَي SCHEDULE_EXACT_ALARM
وUSE_EXACT_ALARM
يشيران إلى الإمكانات نفسها، يتم منحها بشكلٍ مختلف وتتيحان حالات استخدام مختلفة. يجب أن يستخدم تطبيقك المنبّهات المحدَّدة الوقت، وأن يفصح عن استخدام الإذنين SCHEDULE_EXACT_ALARM
أو USE_EXACT_ALARM
فقط إذا كانت إحدى وظائفه المخصّصة للمستخدمين تتطلّب إجراءات محدّدة الوقت بدقة.
USE_EXACT_ALARM
- تم منحه تلقائيًا
- لا يمكن للمستخدم إبطالها
- يخضع لسياسة Google Play القادمة
- حالات الاستخدام المحدودة
SCHEDULE_EXACT_ALARM
- منحها المستخدم
- مجموعة أوسع من حالات الاستخدام
- على التطبيقات تأكيد أنّه لم يتم إبطال الإذن.
لا يتم منح الإذن SCHEDULE_EXACT_ALARM
مسبقًا لعمليات التثبيت الجديدة ل
التطبيقات التي تستهدف الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث. إذا نقل مستخدم بيانات
التطبيق إلى جهاز يعمل بنظام التشغيل Android 14 من خلال عملية الاحتفاظ بنسخة احتياطية واستعادتها، سيتم رفض إذن
SCHEDULE_EXACT_ALARM
على الجهاز الجديد. ومع ذلك، إذا كان
تطبيق حالي يمتلك هذا الإذن، سيتم منحه مسبقًا عند
ترقية الجهاز إلى Android 14.
ملاحظة: إذا تم ضبط المنبّه المحدد باستخدام عنصر
OnAlarmListener
، مثل واجهة برمجة التطبيقات
setExact
، لن يكون إذن SCHEDULE_EXACT_ALARM
مطلوبًا.
استخدام إذن SCHEDULE_EXACT_ALARM
على عكس USE_EXACT_ALARM
، يجب أن يمنح المستخدم إذن SCHEDULE_EXACT_ALARM
. يمكن للمستخدم والنظام إبطال إذن
SCHEDULE_EXACT_ALARM
.
للتحقّق مما إذا تم منح الإذن لتطبيقك، يمكنك الاتصال بالرقم
canScheduleExactAlarms()
قبل محاولة ضبط منبّه محدّد الوقت. عند إبطال إذن SCHEDULE_EXACT_ALARM
لتطبيقك، سيتوقف تطبيقك، وسيتم إلغاء كل المنبّهات المحدّدة الوقت في المستقبل. ويعني ذلك أيضًا أنّ القيمة التي تعرضها
canScheduleExactAlarms()
تظل صالحة طوال دورة حياة تطبيقك.
عند منح تطبيقك إذن SCHEDULE_EXACT_ALARMS
، يُرسِل ال
النظام إليه البث
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
. يجب أن ينفِّذ تطبيقك بثًا
مُستلِمًا ينفِّذ الخطوات التالية:
- تأكيد أنّ تطبيقك لا يزال يملك إذن الوصول الخاص بالتطبيق لإجراء ذلك، يُرجى الاتصال بالرقم
canScheduleExactAlarms()
. يحمي هذا التحقّق تطبيقك من الحالة التي يمنح فيها المستخدم إذنًا لتطبيقك، ثم يُلغيه بعد ذلك مباشرةً تقريبًا. - إعادة جدولة أي تنبيهات محدّدة الوقت يحتاجها تطبيقك استنادًا إلى حالته الحالية
يجب أن يكون هذا المنطق مشابهًا لما يفعله تطبيقك عند تلقّي البث
ACTION_BOOT_COMPLETED
.
طلب إذن SCHEDULE_EXACT_ALARM
من المستخدمين
إذا لزم الأمر، يمكنك توجيه المستخدمين إلى شاشة المنبّهات والتذكيرات في إعدادات النظام، كما هو موضّح في الشكل 1. لإجراء ذلك، يُرجى إكمال الخطوات التالية:
- في واجهة مستخدم تطبيقك، اشرح للمستخدم سبب حاجة تطبيقك إلى جدولة رسائل التنبيهات بدقّة.
- استدعاء نية تتضمّن إجراء النيّة
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
ضبط منبّه متكرّر
تتيح التنبيهات المتكرّرة للنظام إرسال إشعارات إلى تطبيقك وفقًا لجدول زمني متكرّر.
يمكن أن يؤدي المنبّه المصمّم بشكلٍ سيئ إلى استنزاف البطارية وتحميل طلبات كبيرة على الخوادم. لهذا السبب، في الإصدار 4.4 من نظام التشغيل Android (المستوى 19 لواجهة برمجة التطبيقات) والإصدارات الأحدث، تكون كل رسائل التنبيه المتكررة رسائل تنبيه غير دقيقة.
يتسم المنبّه المتكرّر بالخصائص التالية:
نوع المنبّه لمزيد من المناقشة، يُرجى الاطّلاع على اختيار نوع التنبيه.
وقت تشغيل. إذا كان وقت التفعيل الذي تحدّده في الماضي، يتم تفعيل المنبّه على الفور.
الفاصل الزمني للمنبّه على سبيل المثال، مرة واحدة في اليوم أو كل ساعة أو كل 5 دقائق.
نية في انتظار المراجعة يتم تفعيلها عند تشغيل المنبّه. عند ضبط 🔔إنذار ثانٍ يستخدم النية المعلّقة نفسها، يتم استبدال الإنذار الأصلي.
لإلغاء PendingIntent()
، عليك تمرير
FLAG_NO_CREATE
إلى PendingIntent.getService()
للحصول على مثيل للنشاط (إذا كان متوفّرًا)، ثم تمرير هذا النشاط إلى
AlarmManager.cancel()
.
Kotlin
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager val pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE) if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent) }
Java
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent); }
اختيار نوع المنبّه
من بين العوامل الأولى التي يجب مراعاتها عند استخدام تنبيه متكرر هو نوعه.
هناك نوعان عامان من الساعات للمنبّهات: "الوقت الفعلي المنقضي" و "الساعة الفعلية" (RTC). يستخدِم الوقت الفعلي المنقضي "الوقت منذ بدء تشغيل النظام" كمرجع، ويستخدِم ساعة الوقت الفعلي التوقيت العالمي المنسّق (المعروف أيضًا باسم ساعة الحائط). وهذا يعني أنّ الوقت الفعلي المنقضي مناسب لضبط منبّه استنادًا إلى مرور الوقت (مثل المنبّه الذي يتم تشغيله كل 30 ثانية) لأنّه لا يتأثر بالمنطقة الزمنية أو اللغة. يكون نوع الساعة بالوقت الفعلي أكثر ملاءمةً للإنذارات التي تعتمد على اللغة والمنطقة الحالية.
يتضمّن كلا النوعَين إصدارًا "للتنشيط"، والذي يُطلب من خلاله تنشيط وحدة المعالجة المركزية (CPU) في الجهاز إذا كانت الشاشة مطفأة. ويضمن ذلك تشغيل المنبّه في الوقت المحدّد. يكون ذلك مفيدًا إذا كان تطبيقك يعتمد على الوقت. على سبيل المثال، إذا كان لديه فترة محدودة لتنفيذ عملية معيّنة. إذا لم تكن تستخدِم إصدار المنبّه المخصّص للاستيقاظ، سيتم تشغيل كل المنبّهات المتكرّرة عندما يستيقظ جهازك في المرة التالية.
إذا كنت ببساطة بحاجة إلى تشغيل المنبّه بعد فاصل زمني معيّن (مثلاً، كل نصف ساعة)، استخدِم أحد أنواع الوقت الفعلي المنقضي. بشكل عام، هو الخيار الأفضل.
إذا كنت بحاجة إلى تشغيل المنبّه في وقت معيّن من اليوم، اختَر أحد أنواع الساعات المستندة إلى الوقت الفعلي. يُرجى العِلم أنّ هذا النهج يمكن أن يمثّل بعض السلبيات. قد لا تتم ترجمة التطبيق بشكل جيد إلى لغات أخرى، وإذا غيّر المستخدم إعدادات الوقت على الجهاز، قد يؤدي ذلك إلى حدوث سلوك غير متوقّع في تطبيقك. ولا يتوافق استخدام نوع المنبّه في الساعة بالوقت الفعلي أيضًا مع الأجهزة المختلفة بشكل جيد، كما هو موضح أعلاه. ننصحك باستخدام إنذار "الوقت المنقضي بالثواني" إذا أمكن.
في ما يلي قائمة الأنواع:
ELAPSED_REALTIME
: يتم تشغيل النية المعلّقة استنادًا إلى المدة التي انقضت منذ التمهيد للجهاز، ولكن لا يتم تنشيط الجهاز. ويشمل الوقت المنقضي أي وقت كان الجهاز فيه في وضع السكون.
ELAPSED_REALTIME_WAKEUP
: يوقظ الجهاز ويُطلق النية المعلّقة بعد انقضاء المدة المحدّدة من وقت تشغيل الجهاز.
RTC
: يتم تشغيل النية المعلّقة في الوقت المحدّد، ولكن لا يتم تنشيط الجهاز.
RTC_WAKEUP
: لتنشيط الجهاز لتشغيل النية المعلّقة في الوقت المحدّد
أمثلة على المنبّهات التي تم تجاوزها في الوقت الفعلي
في ما يلي بعض الأمثلة على استخدام ELAPSED_REALTIME_WAKEUP
شغِّل الجهاز لتفعيل المنبّه بعد 30 دقيقة، وكل 30 دقيقة بعد ذلك:
Kotlin
// Hopefully your alarm will have a lower frequency than this! alarmMgr?.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent )
Java
// Hopefully your alarm will have a lower frequency than this! alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
يمكنك تنشيط الجهاز لتشغيل منبه لمرة واحدة (غير متكرر) بعد دقيقة واحدة:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } alarmMgr?.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
أمثلة على المنبّهات في الساعة في الوقت الفعلي
في ما يلي بعض الأمثلة على استخدام رمز
RTC_WAKEUP
.
شغِّل الجهاز لإيقاف المنبّه في الساعة 2:00 بعد الظهر تقريبًا، وتكرَّر العملية مرة واحدة في اليوم في الوقت نفسه:
Kotlin
// Set the alarm to start at approximately 2:00 p.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 14) } // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr?.setInexactRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, alarmIntent )
Java
// Set the alarm to start at approximately 2:00 p.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 14); // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
شغِّل الجهاز لتفعيل المنبّه في الساعة 8:30 صباحًا بالضبط، وكل 20 دقيقة بعد ذلك:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } // Set the alarm to start at 8:30 a.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 8) set(Calendar.MINUTE, 30) } // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr?.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 1000 * 60 * 20, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Set the alarm to start at 8:30 a.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 8); calendar.set(Calendar.MINUTE, 30); // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 20, alarmIntent);
تحديد مدى دقة المنبّه
كما هو موضّح سابقًا، غالبًا ما يكون اختيار نوع المنبّه هو الخطوة الأولى في
إنشاء منبّه. هناك فرق آخر وهو مدى دقة المنبّه
الذي تحتاجه. بالنسبة إلى معظم التطبيقات،
setInexactRepeating()
هو الخيار المناسب. عند استخدام هذه الطريقة، يُزامن Android عدة إنذارات متكررة غير دقيقة ويشغّلها
في الوقت نفسه. ويؤدي ذلك إلى تقليل استهلاك البطارية.
تجنَّب استخدام المنبّهات المحدَّدة الوقت إن أمكن. ومع ذلك، بالنسبة إلى التطبيقات النادرة التي تفرض متطلبات زمنية صارمة، يمكنك ضبط منبّه دقيق من خلال استدعاء setRepeating()
.
باستخدام setInexactRepeating()
،
لا يمكنك تحديد فاصل مخصّص بالطريقة نفسها التي يمكنك بها استخدام
setRepeating()
.
عليك استخدام أحد الثوابت الخاصة بالفواصل الزمنية، مثل
INTERVAL_FIFTEEN_MINUTES
،
INTERVAL_DAY
،
وما إلى ذلك. يمكنك الاطّلاع على AlarmManager
للحصول على القائمة الكاملة.
إلغاء منبّه
استنادًا إلى تطبيقك، قد تحتاج إلى تضمين إمكانية إلغاء المنبّه.
لإلغاء منبّه، اتصل بالرقم cancel()
في Alarm Manager، مع تضمين
PendingIntent
الذي لم تعُد تريد
إطلاقه. مثلاً:
Kotlin
// If the alarm has been set, cancel it. alarmMgr?.cancel(alarmIntent)
Java
// If the alarm has been set, cancel it. if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
بدء منبّه عند إعادة تشغيل الجهاز
يتم تلقائيًا إلغاء جميع المنبّهات عند إيقاف تشغيل الجهاز.
لمنع حدوث ذلك، يمكنك تصميم تطبيقك
لإعادة تشغيل المنبّه المتكرّر تلقائيًا إذا أعاد المستخدم تشغيل الجهاز. يضمن ذلك
أنّ AlarmManager
سيكمل عمله بدون الحاجة إلى إعادة تشغيل المنبّه يدويًا.
إليك الخطوات التي يمكنك اتّباعها:
اضبط الإذن
RECEIVE_BOOT_COMPLETED
في بيان تطبيقك. يتيح ذلك لتطبيقك تلقّي إشارةACTION_BOOT_COMPLETED
التي يتم بثها بعد انتهاء النظام من التشغيل (لا يعمل هذا الإجراء إلا إذا سبق للمستخدم تشغيل التطبيق مرة واحدة على الأقل):<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
نفِّذ
BroadcastReceiver
لتلقّي البث:Kotlin
class SampleBootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "android.intent.action.BOOT_COMPLETED") { // Set the alarm here. } } }
Java
public class SampleBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // Set the alarm here. } } }
أضِف المستلِم إلى ملف بيان تطبيقك باستخدام فلتر أهداف يُفلتر على الإجراء
ACTION_BOOT_COMPLETED
:<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
يُرجى ملاحظة أنّه في البيان، تم ضبط مستلِم التمهيد على
android:enabled="false"
. وهذا يعني أنّه لن يتم استدعاء المُستلِم ما لم يفعّله التطبيق صراحةً. ويمنع ذلك من استدعاء مستلِم التمهيد بدون داعٍ. يمكنك تفعيل جهاز استقبال (على سبيل المثال، إذا ضبط المستخدم منبّهًا) على النحو التالي:Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
بعد تفعيل جهاز الاستقبال بهذه الطريقة، سيظل مفعّلاً حتى إذا أعاد المستخدم تشغيل الجهاز. بعبارة أخرى، يؤدي تفعيل المُستلِمبرمجيًا إلى إلغاء إعداد البيان، حتى بعد عمليات إعادة التشغيل. سيظل جهاز الاستقبال مفعّلاً إلى أن يوقفه تطبيقك. يمكنك إيقاف جهاز استقبال (على سبيل المثال، إذا ألغى المستخدم إنذارًا) على النحو التالي:
Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
تفعيل المنبّهات عندما يكون الجهاز في وضع "الاستراحة"
تتيح الأجهزة التي تعمل بالإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات) وضع الاستراحة الذي يساعد في إطالة عمر بطارية الجهاز. لا يتم تشغيل المنبّهات عندما يكون الجهاز في وضع "الاستراحة" ويتم تأجيل أي منبّهات مجدوَلة إلى أن يخرج الجهاز من وضع "الاستراحة". إذا كنت بحاجة إلى إكمال العمل حتى عندما يكون الجهاز في وضع السكون، تتوفّر عدة خيارات:
اضبط منبّهًا دقيقًا.
استخدِم واجهة برمجة التطبيقات WorkManager API، وهي مصمّمة لتنفيذ المهام في background. يمكنك الإشارة إلى أنّه يجب على النظام تسريع عملك حتى تتمكّن من إكماله في أقرب وقت ممكن. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة جدولة المهام باستخدام WorkManager.
أفضل الممارسات
يمكن أن يكون لكل خيار تحدّده في تصميم المنبّه المتكرّر عواقب في كيفية استخدام تطبيقك لموارد النظام (أو إساءة استخدامه لها). على سبيل المثال، تخيل تطبيقًا شائعًا تتم مزامنته مع خادم. إذا كانت عملية المزامنة تستند إلى وقت المحاولة وكانت تتم مزامنة كل نسخة من التطبيق في الساعة 11:00 مساءً، قد يؤدي الحمل على الخادم إلى وقت استجابة طويل أو حتى "رفض الخدمة". اتّبِع أفضل الممارسات التالية عند استخدام المنبّهات:
أضِف عشوائية (تشويش) إلى أي طلبات شبكة يتم تفعيلها نتيجة منبه متكرر:
تنفيذ أي عمل محلي عند بدء المنبّه "العمل على الجهاز فقط" يعني أي إجراء لا يتطلّب الاتصال بالخادم أو طلب البيانات من الخادم.
في الوقت نفسه، حدِّد موعدًا للمنبه الذي يحتوي على طلبات الشبكة ليقوم بالانطلاق في فترة زمنية عشوائية.
اضبط معدّل تكرار المنبّه على الحد الأدنى.
عدم تنشيط الجهاز بدون داعٍ (يتم تحديد هذا السلوك من خلال نوع التنبيه، كما هو موضّح في اختيار نوع التنبيه)
لا تضبط وقت تفعيل المنبّه بدقة أكبر من اللازم.
استخدِم
setInexactRepeating()
بدلاً منsetRepeating()
. عند استخدامsetInexactRepeating()
، تتم مزامنة الإنذارات المتكررة من تطبيقات متعددة وإطلاقها في الوقت نفسه. ويؤدي ذلك إلى تقليل إجمالي عدد المرات التي يجب أن يوقظ فيها النظام الجهاز، وبالتالي تقليل استهلاك البطارية. اعتبارًا من الإصدار 4.4 من Android (المستوى 19 لواجهة برمجة التطبيقات)، تكون جميع المنبّهات المتكرّرة منبّهات غير دقيقة. يُرجى العِلم أنّه على الرغم من أنّsetInexactRepeating()
يمثّل تحسُّنًا مقارنةً بsetRepeating()
، يمكن أن يظلّ مثيل التطبيق يُحمّل الخادم في الوقت نفسه تقريبًا. لذلك، بالنسبة إلى طلبات الشبكة، أضِف بعض العشوائية إلى إنذاراتك، كما ناقشنا سابقًا.تجنَّب ضبط المنبّه على وقت الساعة إن أمكن.
لا يمكن توسيع نطاق المنبّهات المتكرّرة التي تستند إلى وقت تشغيل دقيق. استخدِم
ELAPSED_REALTIME
إذا أمكن. يتم وصف أنواع التنبيهات المختلفة بمزيد من التفصيل في القسم التالي.