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>
إذا كان تطبيقك يستهدف Android 13 (المستوى 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
على الجهاز الجديد. ومع ذلك، إذا كان
تطبيق حالي يمتلك هذا الإذن، سيتم منحه مسبقًا عند upgrade
الجهاز إلى 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، وهي مصمّمة لتنفيذ المهام في الخلفية. يمكنك الإشارة إلى أنّه يجب على النظام تسريع عملك حتى تتمكّن من إكماله في أقرب وقت ممكن. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة جدولة المهام باستخدام WorkManager.
أفضل الممارسات
كل اختيار تتخذه أثناء تصميم المنبّه المتكرر قد ينطوي على عواقب في كيفية استخدام تطبيقك لموارد النظام (أو إساءة استخدامها). على سبيل المثال، تخيل تطبيقًا شائعًا تتم مزامنته مع خادم. إذا كانت عملية المزامنة تستند إلى وقت المحاولة وكانت تتم مزامنة كل نسخة من التطبيق في الساعة 11:00 مساءً، قد يؤدي الحمل على الخادم إلى وقت استجابة طويل أو حتى "رفض الخدمة". يُرجى اتّباع أفضل الممارسات التالية عند استخدام المنبّهات:
أضف العشوائية (عدم الاستقرار) إلى أي طلبات شبكة تظهر نتيجة إنذار متكرر:
تنفيذ أي عمل محلي عند بدء المنبّه يعني "العمل المحلي" أي شيء لا يصل إلى أي خادم أو يتطلب البيانات من الخادم.
في الوقت نفسه، يمكنك جدولة المنبّه الذي يحتوي على طلبات الشبكة لإطلاقه في فترة زمنية عشوائية.
حافظ على الحد الأدنى لمعدل تكرار المنبه.
عدم تنشيط الجهاز بدون داعٍ (يتم تحديد هذا السلوك من خلال نوع التنبيه، كما هو موضّح في اختيار نوع التنبيه)
لا تضبط وقت تفعيل المنبّه بدقة أكبر من اللازم.
استخدِم
setInexactRepeating()
بدلاً منsetRepeating()
. عند استخدامsetInexactRepeating()
، تتم مزامنة المنبّهات المتكرّرة من تطبيقات متعددة وتشغيلها في الوقت نفسه. ويؤدي ذلك إلى تقليل إجمالي عدد المرات التي يجب أن يوقظ فيها النظام الجهاز، وبالتالي تقليل استهلاك البطارية. اعتبارًا من الإصدار 4.4 من Android (المستوى 19 لواجهة برمجة التطبيقات)، تكون جميع المنبّهات المتكرّرة منبّهات غير دقيقة. يُرجى العِلم أنّه على الرغم من أنّsetInexactRepeating()
يمثّل تحسُّنًا مقارنةً بsetRepeating()
، يمكن أن يظلّ مثيل التطبيق يُحمّل الخادم في الوقت نفسه تقريبًا. لذلك، بالنسبة إلى طلبات الشبكة، أضِف بعض العشوائية إلى إنذاراتك، كما ناقشنا سابقًا.تجنَّب ضبط وقت المنبّه على وقت الساعة إن أمكن.
لا يمكن توسيع نطاق المنبّهات المتكرّرة التي تستند إلى وقت تشغيل دقيق. استخدِم
ELAPSED_REALTIME
إذا أمكن. يتم وصف أنواع التنبيهات المختلفة بمزيد من التفصيل في القسم التالي.