جدولة المنبّهات

المنبّهات (استنادًا إلى AlarmManager الفصل) طريقة لأداء العمليات المستندة إلى الوقت خارج الفترة منذ إنشاء التطبيق. على سبيل المثال، يمكنك استخدام تنبيه لبدء عملية طويلة الأمد، مثل كبدء خدمة مرة واحدة في اليوم لتنزيل توقعات الطقس.

تشمل المنبّهات السمات التالية:

  • فهي تتيح لك تنشيط أهداف Intent في أوقات و/أو فترات زمنية محدّدة.

  • يمكنك استخدامها مع مستقبلات البث لجدولة الوظائف أو WorkRequests لتنفيذ طلبات أخرى العمليات التجارية.

  • وهي تعمل خارج التطبيق، لذا يمكنك استخدامها لتشغيل الأحداث أو الإجراءات حتى في حال عدم تشغيل تطبيقك، وحتى إذا كان الجهاز نفسه نائم.

  • وتساعدك في تقليل متطلبات الموارد اللازمة لتطبيقك. يمكنك جدولة العمليات بدون الاعتماد على مؤقتات أو تشغيل خدمات باستمرار.

ضبط منبّه غير دقيق

عندما يضبط أحد التطبيقات منبّهًا غير محدَّد، يُرسِل النظام الإنذار في مرحلة ما. في المستقبل. توفر المنبهات غير المحددة بعض الضمانات فيما يتعلق بتوقيت تسليم المنبّه مع مراعاة قيود توفير شحن البطارية، مثل قيلولة:

يمكن للمطوّرين الاستفادة من ضمانات واجهات برمجة التطبيقات التالية لتخصيص توقيت إِطْلَاعُ الْمُنَبِّهْ غَيْرْ مُحَدَّدْ.

ضبط منبّه بعد وقت محدّد

إذا كان تطبيقك يطلب البيانات من set()، setInexactRepeating(), أو setAndAllowWhileIdle()، لا ينطلق صوت الإنذار أبدًا قبل وقت التشغيل المحدد.

في نظام التشغيل Android 12 (المستوى 31 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يستدعي النظام الإنذار خلال ساعة واحدة ساعة من وقت التشغيل المقدم، ما لم يتم فرض أي قيود على توفير شحن البطارية سارية مثل توفير شحن البطارية أو قيلولة:

ضبط منبّه خلال فترة زمنية

إذا اتصل تطبيقك بـ setWindow()، لن يرنّ المنبّه قبل أن يتم تزويد الجهاز بالإنذار. وقت الإطلاق. ما لم يتم تطبيق أي قيود على توفير شحن البطارية، سيتم ضبط المنبّه على تسليمه خلال الفترة الزمنية المحدّدة، بدءًا من المشغّل المحدّد الوقت.

إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو إصدارًا أحدث، قد يؤخر النظام استدعاء إنذار غير محدد ضمن إطار زمني لمدة 10 دقائق على الأقل. بالنسبة ولهذا السبب، يتم اقتصاص قيم معلَمات windowLengthMillis ضمن 600000 إلى 600000

إطلاق منبّه متكرّر على فترات منتظمة تقريبًا

إذا كان تطبيقك يطلب البيانات من setInexactRepeating()، يستدعي النظام تنبيهات متعددة:

  1. يرن الإنذار الأول خلال الفترة الزمنية المحدّدة، بدءًا من المحدد وقت التشغيل.
  2. تصدر المنبّهات اللاحقة عادةً بعد الفترة الزمنية المحددة ينقضي. قد يختلف الوقت بين استدعاءين متتاليين للإنذار.

ضبط منبّه دقيق

يستدعي النظام منبّهًا محددًا في لحظة محدّدة في المستقبل.

يمكن لمعظم التطبيقات جدولة المهام والأحداث باستخدام منبّهات غير محدَّدة وإكمال العديد من حالات الاستخدام الشائعة. إذا كان التطبيق الأساسي تعتمد وظيفته على منبّه محدد الوقت بدقة، مثل أحد تطبيقات المنبّه أو تطبيق تقويم - فعندئذٍ يمكنك استخدام منبّه محدد بدلاً من ذلك.

حالات الاستخدام التي قد لا تتطلّب ضبط منبّهات محدَّدة الوقت

تعرض القائمة التالية عمليات سير العمل الشائعة التي قد لا تتطلب منبّهًا محددًا:

جدولة عمليات التوقيت خلال فترة بقاء تطبيقك
تتضمن فئة Handler العديد من الفئات طرق للتعامل مع عمليات التوقيت، مثل القيام ببعض الأعمال كل n ثانية، عندما يكون تطبيقك قيد التشغيل: postAtTime() أو postDelayed(). تجدر الإشارة إلى أنّ واجهات برمجة التطبيقات هذه تعتمد على مدة تشغيل النظام وليس في الوقت الفعلي.
الأعمال التي تم إجراؤها في الخلفية، مثل تحديث التطبيق وتحميل السجلّات
توفّر WorkManager طريقة لجدولة مواعيد دورية تتضمّن التوقيت. العمل. يمكنك توفير فاصل زمني متكرر وflexInterval (15 دقيقة كحد أدنى) وتحدّد وقت تشغيل دقيق للعمل.
إجراء يحدده المستخدم يجب أن يحدث بعد وقت محدد (حتى إذا كان النظام في حالة عدم النشاط)
يُرجى استخدام منبّه غير محدَّد. على وجه التحديد، اتصل setAndAllowWhileIdle()
إجراء يحدده المستخدم ويجب أن يحدث بعد وقت محدّد
يُرجى استخدام منبّه غير محدَّد. على وجه التحديد، اتصل set()
إجراء يحدده المستخدم ويمكن أن يحدث خلال فترة زمنية محدّدة
يُرجى استخدام منبّه غير محدَّد. على وجه التحديد، اتصل setWindow() يُرجى ملاحظة أنّه إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو إصدارًا أحدث، فإن أصغر المدة المسموح بها هي 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

SCHEDULE_EXACT_ALARM

  • منح المستخدم
  • مجموعة أوسع من حالات الاستخدام
  • على التطبيقات تأكيد عدم إبطال الإذن.

لا يتم منح إذن SCHEDULE_EXACT_ALARM مسبقًا لعمليات التثبيت الجديدة التطبيقات التي تستهدف الإصدار 13 من نظام التشغيل Android (المستوى 33 من واجهة برمجة التطبيقات) والإصدارات الأحدث. في حال نقل المستخدم التطبيق البيانات إلى جهاز يعمل بنظام التشغيل Android 14 من خلال عملية الاحتفاظ بنسخة احتياطية من البيانات واستعادتها سيتم رفض إذن "SCHEDULE_EXACT_ALARM" على الجهاز الجديد. ومع ذلك، إذا أحد التطبيقات الحالية لديه هذا الإذن بالفعل، فسيتم منحه مسبقًا عند ترقيات الجهاز إلى الإصدار 14 من نظام التشغيل Android.

ملاحظة: إذا تم ضبط المنبه المحدد باستخدام 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 البث. يجب أن يبث التطبيق بثًا المستلِم الذي يتولى تنفيذ التالي:

  1. يؤكِّد أنّ تطبيقك لا يزال لديه إذن الوصول الخاص إلى التطبيق. لإجراء ذلك، اتصل canScheduleExactAlarms() تحمي هذه العملية تطبيقك من الحالة التي يمنح فيها المستخدم تطبيقك ثم يُبطله على الفور بعد ذلك.
  2. إعادة جدولة أي تنبيهات محدّدة يحتاجها تطبيقك، بناءً على حالته الحالية وينبغي أن يكون هذا المنطق مشابهًا لما يفعله تطبيقك عند تلقي ACTION_BOOT_COMPLETED البث.

الطلب من المستخدمين منح إذن "SCHEDULE_EXACT_ALARM"

يُعرَف هذا الخيار باسم &quot;السماح بضبط المنبّهات والتذكيرات&quot;.
الشكل 1. المنبّهات تذكيرات" أذونات خاصة للتطبيقات صفحة في إعدادات النظام، حيث يمكن للمستخدمين السماح لتطبيقك بضبط الإعدادات المنبّهات

إذا لزم الأمر، يمكنك توجيه المستخدمين إلى المنبّهات التذكيرات في النظام الإعدادات، كما هو موضح في الشكل 1. للقيام بذلك، أكمل الخطوات التالية:

  1. في واجهة المستخدم الخاصة بتطبيقك، اشرح للمستخدم سبب حاجة تطبيقك إلى وضع جدول زمني دقيق المنبّهات.
  2. استدعاء غرض يتضمن ACTION_REQUEST_SCHEDULE_EXACT_ALARM الهدف من الإجراء.

ضبط منبّه متكرّر

يسمح تكرار المنبّهات للنظام بإشعار تطبيقك برصد زمني للمشروع.

يمكن أن يؤدي استخدام منبّه غير مصمَّم بشكل سيئ إلى استنزاف البطارية وزيادة الحمل على الخوادم. ولهذا السبب، على نظام التشغيل Android 4.4 (المستوى 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). يستخدم الوقت الفعلي المنقضي "الوقت منذ تشغيل النظام". كـ المرجعية، وتستخدم ساعة الوقت الفعلي التوقيت العالمي المنسّق (UTC) (ساعة الحائط). هذا يعني أنّ يتناسب الوقت الفعلي المنقضي لضبط منبّه بناءً على مرور الوقت ( مثل، إنذار يطلق كل 30 ثانية) نظرًا لأنه لا يتأثر المنطقة الزمنية أو اللغة. يكون نوع الساعة في الوقت الفعلي أكثر ملاءمة للمنبهات التي تعتمد على اللغة الحالية.

يتطلب كلا النوعين "تنشيط" والذي يشير إلى تنشيط وحدة المعالجة المركزية للجهاز في حالة عندما تكون الشاشة مطفأة. ويضمن ذلك إطلاق الإنذار في الوقت المحدَّد. ويكون هذا الإجراء مفيدًا إذا كان تطبيقك يعتمد على الوقت. على سبيل المثال، إذا كان نافذة محدودة لإجراء عملية معينة. إذا كنت لا تستخدم الملف إصدار المنبّه من نوع المنبّه، سيتم تنشيط جميع المنبّهات المتكرّرة. عند تنشيط جهازك في المرة التالية

فإذا كنت تحتاج ببساطة إلى أن ينطلق صوت المنبه في فاصل معين (على سبيل المثال، كل نصف ساعة)، استخدم أحد أنواع الوقت الفعلي المنقضية. بشكل عام، هو الخيار الأفضل.

إذا أردت تشغيل المنبّه في وقت معيّن من اليوم، اختَر أحد الأوقات. أنواع الساعات المستندة إلى الساعة في الوقت الفعلي. ومع ذلك، لاحظ أن هذا المنهج يمكن بها بعض العيوب. قد لا تتم ترجمة التطبيق بشكل جيد إلى اللغات الأخرى، وإذا تغيير المستخدم لإعداد الوقت في الجهاز، قد يؤدي ذلك إلى سلوك غير متوقّع في تطبيقك. لا يؤدي استخدام نوع منبه في الوقت الفعلي أيضًا إلى ضبط المقياس بشكل جيد، التي تمت مناقشتها أعلاه. ننصحك باستخدام القيمة "الوقت الفعلي المنقضي". تنبيه إذا كنت تستطيع.

في ما يلي قائمة الأنواع:

  • ELAPSED_REALTIME: يتم تنشيط الطلب الذي كان في انتظار المراجعة بناءً على مقدار الوقت المنقضي منذ إنشاء الجهاز تم تشغيله، إلا أنه لا يوقظ الجهاز. تشير رسالة الأشكال البيانية ويشمل الوقت المنقضي أي وقت كان الجهاز في وضع السكون خلاله.

  • ELAPSED_REALTIME_WAKEUP: تنشيط الجهاز وتشغيل الطلب المعلَّق بعد المدة المحددة انقضى من الوقت منذ تشغيل الجهاز.

  • RTC: لتشغيل رسالة intent التي كانت في انتظار المراجعة في الوقت المحدّد، ولكن لا يتم تنشيط الجهاز.

  • 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 مواصلة أداء مهمته دون أن يحتاج المستخدم إلى إعادة تشغيل المنبّه يدويًا

إليك الخطوات التي يمكنك اتّباعها:

  1. ضبط RECEIVE_BOOT_COMPLETED إذن في بيان التطبيق. ويسمح هذا الإجراء لتطبيقك بتلقي ACTION_BOOT_COMPLETED يتم بثه بعد انتهاء تشغيل النظام (لا يعمل هذا إلا إذا تم تشغيل التطبيق بواسطة المستخدم مرة واحدة على الأقل):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. تنفيذ 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.
            }
        }
    }
    
  3. أضِف المستلِم إلى ملف بيان تطبيقك باستخدام فلتر أهداف الفلاتر على 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);
    

استدعِ المنبّهات عندما يكون الجهاز في وضع "القيلولة"

الأجهزة التي تعمل بنظام التشغيل Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات) قيلولة الذي للمساعدة في إطالة عمر بطارية الجهاز. لا يتم إطلاق المنبّهات عندما يكون الجهاز داخله. وضع القيلولة سيتم تأجيل أي منبّهات مُجدوَلة إلى أن يخرج الجهاز من وضع "القيلولة". إذا كنت بحاجة إلى لإنجاز العمل حتى عندما يكون الجهاز غير نشِط لفترة قصيرة، فهناك العديد من الخيارات متوفرة:

  • اضبط منبّهًا محدّدًا.

  • استخدام واجهة برمجة تطبيقات WorkManager التي صُممت لأداء للعمل في الخلفية. يمكنك الإشارة إلى أن النظام يجب أن يسرّع عملك حتى الانتهاء من العمل في أقرب وقت ممكن. لمزيد من المعلومات، يُرجى مراجعة جدولة المهام باستخدام WorkManager

أفضل الممارسات

كل قرار تتخذه أثناء تصميم المنبّه المتكرر يمكن أن يكون له عواقب. في كيفية استخدام تطبيقك لموارد النظام (أو إساءة استخدامها) على سبيل المثال، تخيل أن تطبيق مشهور يتزامن مع الخادم. إذا كانت عملية المزامنة تستند إلى الساعة الوقت وتتم مزامنة كل مثيل من التطبيق في الساعة 11:00 مساءً، فإن التحميل على إلى وقت الاستجابة الطويل أو حتى "رفض الخدمة". يُرجى اتّباع أفضل الممارسات التالية عند استخدام المنبّهات:

  • أضف العشوائية (عدم الاستقرار) إلى أي طلبات شبكة يشغّل نتيجة لإنذار متكرر:

    • القيام بأي عمل محلي عند تشغيل المنبه "العمل المحلي" تعني أي شيء لا تصل إلى أي خادم أو لا تتطلب البيانات من الخادم.

    • وفي الوقت نفسه، يمكنك جدولة المنبه الذي يحتوي على طلبات الشبكة تطلق في فترة زمنية عشوائية.

  • حافظ على الحد الأدنى لمعدل تكرار المنبه.

  • عدم تنشيط الجهاز بدون داعٍ (يتم تحديد هذا السلوك من خلال نوع التنبيه، كما هو موضَّح في مقالة اختيار نوع التنبيه).

  • لا تجعل وقت تشغيل المنبه أكثر دقة مما ينبغي.

    استخدام setInexactRepeating() بدلاً من setRepeating() عند استخدام setInexactRepeating()، يعمل Android على مزامنة المنبّهات المتكرّرة من تطبيقات متعددة وحالات الحرائق. معهما في نفس الوقت. ومن شأن هذا تقليل العدد الإجمالي للمرات التي يجب أن ينشط فيها النظام مما يقلل من استنزاف البطارية. اعتبارًا من الإصدار Android 4.4 (مستوى واجهة برمجة التطبيقات 19)، جميع المنبّهات المتكرّرة هي منبّه غير دقيق. ملاحظة في حين setInexactRepeating() هو تحسين خلال setRepeating(), فقد يظل بإمكانه إرباك الخادم إذا ضرب كل مثيل من التطبيق في الخادم في نفس الوقت تقريبًا. وبالتالي، عندما يتعلق الأمر بطلبات الشبكة، أضف بعض العشوائية إلى المنبهات، كما ناقشنا سابقًا.

  • تجنَّب ضبط وقت المنبّه على وقت الساعة إن أمكن.

    لا يتم ضبط المنبهات المتكررة التي تستند إلى وقت تشغيل دقيق بشكل جيد. استخدام ELAPSED_REALTIME إذا يمكنك. المنبّه المختلف الأنواع المذكورة بمزيد من التفصيل في القسم التالي.