آلارم ها را برنامه ریزی کنید

هشدارها (بر اساس کلاس AlarmManager ) به شما امکان می‌دهند عملیات مبتنی بر زمان را خارج از طول عمر برنامه خود انجام دهید. برای مثال، می‌توانید از یک هشدار برای شروع یک عملیات طولانی مدت استفاده کنید، مانند شروع یک سرویس یک بار در روز برای دانلود پیش‌بینی آب و هوا.

آلارم‌ها این ویژگی‌ها را دارند:

  • آنها به شما اجازه می‌دهند Intentها را در زمان‌ها و/یا فواصل زمانی مشخص اجرا کنید.

  • شما می‌توانید از آنها در ارتباط با گیرنده‌های پخش برای زمان‌بندی کارها یا از WorkRequests برای انجام سایر عملیات استفاده کنید.

  • آنها خارج از برنامه شما عمل می‌کنند، بنابراین می‌توانید از آنها برای ایجاد رویدادها یا اقدامات حتی زمانی که برنامه شما در حال اجرا نیست و حتی اگر خود دستگاه در حالت خواب باشد، استفاده کنید.

  • آنها به شما کمک می‌کنند تا نیازهای منابع برنامه خود را به حداقل برسانید. می‌توانید عملیات را بدون تکیه بر تایمرها یا سرویس‌های در حال اجرای مداوم، زمان‌بندی کنید.

تنظیم زنگ هشدار نادرست

وقتی یک برنامه آلارم نادرستی تنظیم می‌کند، سیستم در مقطعی از آینده آلارم را ارسال می‌کند. آلارم‌های نادرست ضمن رعایت محدودیت‌های صرفه‌جویی در مصرف باتری مانند Doze ، تضمین‌هایی در مورد زمان‌بندی ارسال آلارم ارائه می‌دهند.

توسعه‌دهندگان می‌توانند از ضمانت‌های API زیر برای سفارشی‌سازی زمان‌بندی ارسال هشدارهای نادرست استفاده کنند.

ارسال آلارم پس از زمان مشخص

اگر برنامه شما set() ، setInexactRepeating() یا setAndAllowWhileIdle() را فراخوانی کند، زنگ هشدار هرگز قبل از زمان فعال شدن تعیین شده به صدا در نمی‌آید.

در اندروید ۱۲ (سطح API 31) و بالاتر، سیستم ظرف یک ساعت از زمان فعال‌سازی ارائه شده، زنگ هشدار را فعال می‌کند، مگر اینکه محدودیت‌های صرفه‌جویی در باتری مانند صرفه‌جویی در باتری یا Doze اعمال شده باشد.

ارسال آلارم در یک بازه زمانی مشخص

اگر برنامه شما تابع setWindow() فراخوانی کند، زنگ هشدار هرگز قبل از زمان فعال شدن تعیین شده به صدا در نمی‌آید. مگر اینکه محدودیت‌های صرفه‌جویی در مصرف باتری اعمال شده باشد، زنگ هشدار در بازه زمانی مشخص شده، از زمان فعال شدن داده شده، فعال می‌شود.

اگر برنامه شما اندروید ۱۲ یا بالاتر را هدف قرار می‌دهد، سیستم می‌تواند فراخوانی یک آلارم نادرستِ پنجره زمانی را حداقل ۱۰ دقیقه به تأخیر بیندازد. به همین دلیل، مقادیر پارامتر windowLengthMillis زیر 600000 به 600000 محدود می‌شوند.

ارائه آلارم تکراری در فواصل تقریباً منظم

اگر برنامه شما تابع setInexactRepeating() را فراخوانی کند، سیستم چندین هشدار را فراخوانی می‌کند:

  1. اولین زنگ هشدار در بازه زمانی مشخص شده، از زمان شروع داده شده، به صدا در می‌آید.
  2. آلارم‌های بعدی معمولاً پس از گذشت بازه زمانی مشخص شده به صدا در می‌آیند. زمان بین دو فراخوانی متوالی آلارم می‌تواند متفاوت باشد.

تنظیم زنگ هشدار دقیق

این سیستم در لحظه‌ای دقیق در آینده، یک آلارم دقیق را فراخوانی می‌کند.

اکثر برنامه‌ها می‌توانند وظایف و رویدادها را با استفاده از هشدارهای غیردقیق برای تکمیل چندین مورد استفاده رایج، زمان‌بندی کنند. اگر عملکرد اصلی برنامه شما به یک هشدار با زمان‌بندی دقیق بستگی دارد - مانند برنامه ساعت زنگ‌دار یا برنامه تقویم - استفاده از یک هشدار دقیق اشکالی ندارد.

از مواردی استفاده کنید که ممکن است به آلارم‌های دقیق نیاز نداشته باشند

لیست زیر گردش‌های کاری رایجی را نشان می‌دهد که ممکن است نیازی به آلارم دقیق نداشته باشند:

زمان‌بندی عملیات زمان‌بندی در طول عمر برنامه شما
کلاس Handler شامل چندین متد خوب برای مدیریت عملیات زمان‌بندی است، مانند انجام برخی کارها هر n ثانیه، در حالی که برنامه شما فعال است: postAtTime() و postDelayed() . توجه داشته باشید که این APIها به زمان روشن بودن سیستم متکی هستند و نه به صورت بلادرنگ .
کارهای پس‌زمینه‌ی زمان‌بندی‌شده، مانند به‌روزرسانی برنامه و آپلود گزارش‌ها
WorkManager راهی برای برنامه‌ریزی کارهای دوره‌ای حساس به زمان ارائه می‌دهد. می‌توانید یک بازه تکرار و flexInterval (حداقل ۱۵ دقیقه) برای تعریف زمان اجرای جزئی برای کار ارائه دهید.
عملی که توسط کاربر مشخص می‌شود و باید پس از زمان مشخصی (حتی اگر سیستم در حالت آماده به کار باشد) انجام شود
از یک هشدار نادرست استفاده کنید. به طور خاص، تابع setAndAllowWhileIdle() را فراخوانی کنید.
عملی که توسط کاربر مشخص شده و باید پس از یک زمان خاص انجام شود
از یک هشدار نادرست استفاده کنید. به طور خاص، تابع set() را فراخوانی کنید.
اقدام مشخص شده توسط کاربر که می‌تواند در یک بازه زمانی مشخص انجام شود
از یک هشدار نادرست استفاده کنید. به طور خاص، تابع setWindow() را فراخوانی کنید. توجه داشته باشید که اگر برنامه شما اندروید ۱۲ یا بالاتر را هدف قرار می‌دهد، کمترین طول پنجره مجاز ۱۰ دقیقه است.

راه‌های تنظیم دقیق زنگ هشدار

برنامه شما می‌تواند با استفاده از یکی از روش‌های زیر، آلارم‌های دقیقی تنظیم کند. این روش‌ها به گونه‌ای مرتب شده‌اند که روش‌های نزدیک‌تر به انتهای لیست، وظایف حساس‌تر به زمان را انجام می‌دهند اما به منابع سیستم بیشتری نیاز دارند.

setExact()

زنگ هشدار را در زمانی تقریباً دقیق در آینده فعال کنید، البته تا زمانی که سایر اقدامات صرفه‌جویی در مصرف باتری در حال اجرا نباشند.

از این روش برای تنظیم دقیق آلارم‌ها استفاده کنید، مگر اینکه کار برنامه شما از نظر زمانی برای کاربر بسیار مهم باشد.

setExactAndAllowWhileIdle()

حتی اگر اقدامات صرفه‌جویی در مصرف باتری در حال اجرا باشند، زنگ هشدار را در زمانی تقریباً دقیق در آینده فعال کنید.

setAlarmClock()

در زمان دقیقی در آینده، آلارمی را فعال کنید. از آنجا که این آلارم‌ها برای کاربران بسیار قابل مشاهده هستند، سیستم هرگز زمان ارسال آنها را تنظیم نمی‌کند. سیستم این آلارم‌ها را به عنوان مهمترین آلارم‌ها شناسایی می‌کند و در صورت لزوم، حالت‌های کم‌مصرف را برای ارسال آلارم‌ها باقی می‌گذارد.

مصرف منابع سیستم

وقتی سیستم دقیقاً همان آلارم‌هایی را که برنامه شما تنظیم کرده است، فعال می‌کند، دستگاه منابع زیادی، مانند عمر باتری، را مصرف می‌کند، به خصوص اگر در حالت صرفه‌جویی در مصرف انرژی باشد. علاوه بر این، سیستم نمی‌تواند به راحتی این درخواست‌ها را دسته بندی کند تا از منابع به طور کارآمدتری استفاده کند.

اکیداً توصیه می‌شود که در صورت امکان، یک هشدار غیردقیق ایجاد کنید. برای انجام کار طولانی‌تر، آن را با استفاده از WorkManager یا JobScheduler از BroadcastReceiver مربوط به هشدار خود زمان‌بندی کنید. برای انجام کار در حالی که دستگاه در حالت Doze است، با استفاده از setAndAllowWhileIdle() یک هشدار غیردقیق ایجاد کنید و یک کار را از هشدار شروع کنید.

مجوز دقیق و مناسب برای آلارم را اعلام کنید

اگر برنامه شما اندروید ۱۲ یا بالاتر را هدف قرار می‌دهد، باید دسترسی ویژه برنامه "Alarms & reminders" را دریافت کنید. برای انجام این کار، مجوز SCHEDULE_EXACT_ALARM را در فایل مانیفست برنامه خود، همانطور که در قطعه کد زیر نشان داده شده است، اعلام کنید:

<manifest ...>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

اگر برنامه شما اندروید ۱۳ (سطح API ۳۳) یا بالاتر را هدف قرار می‌دهد، می‌توانید مجوز 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 برای نصب‌های جدید برنامه‌هایی که اندروید ۱۳ (سطح API ۳۳) و بالاتر را هدف قرار می‌دهند، از پیش اعطا نمی‌شود. اگر کاربری داده‌های برنامه را از طریق عملیات پشتیبان‌گیری و بازیابی به دستگاهی که اندروید ۱۴ را اجرا می‌کند منتقل کند، مجوز SCHEDULE_EXACT_ALARM در دستگاه جدید رد می‌شود. با این حال، اگر یک برنامه موجود از قبل این مجوز را داشته باشد، هنگام ارتقاء دستگاه به اندروید ۱۴، از پیش اعطا می‌شود.

نکته : اگر زنگ هشدار دقیق با استفاده از یک شیء OnAlarmListener تنظیم شود، مانند API 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 را اعطا کنند

این گزینه «اجازه تنظیم هشدارها و یادآوری‌ها» نام دارد.
شکل ۱. صفحه دسترسی ویژه برنامه «هشدارها و یادآوری‌ها» در تنظیمات سیستم، جایی که کاربران می‌توانند به برنامه شما اجازه دهند هشدارهای دقیقی را تنظیم کند.

در صورت لزوم، می‌توانید کاربران را به صفحه هشدارها و یادآوری‌ها در تنظیمات سیستم، همانطور که در شکل ۱ نشان داده شده است، هدایت کنید. برای انجام این کار، مراحل زیر را انجام دهید:

  1. در رابط کاربری برنامه خود، به کاربر توضیح دهید که چرا برنامه شما نیاز به زمان‌بندی دقیق آلارم‌ها دارد.
  2. یک intent را که شامل اکشن ACTION_REQUEST_SCHEDULE_EXACT_ALARM است، فراخوانی کنید.

تنظیم زنگ هشدار تکرارشونده

آلارم‌های تکرارشونده به سیستم اجازه می‌دهند تا برنامه شما را در یک برنامه زمانی تکرارشونده مطلع کند.

یک آلارم با طراحی ضعیف می‌تواند باعث تخلیه باتری و ایجاد بار قابل توجه روی سرورها شود. به همین دلیل، در اندروید ۴.۴ (سطح API ۱۹) و بالاتر، همه آلارم‌های تکرارشونده، آلارم‌های نادرستی هستند.

یک آلارم تکرارشونده دارای ویژگی‌های زیر است:

  • نوع زنگ هشدار. برای بحث بیشتر، به انتخاب نوع زنگ هشدار مراجعه کنید.

  • زمان فعال شدن. اگر زمان فعال شدنی که مشخص می‌کنید مربوط به گذشته باشد، آلارم بلافاصله فعال می‌شود.

  • فاصله زمانی زنگ هشدار. به عنوان مثال، یک بار در روز، هر ساعت یا هر ۵ دقیقه.

  • یک هدف در حال انتظار که هنگام فعال شدن زنگ هشدار فعال می‌شود. وقتی زنگ هشدار دومی را تنظیم می‌کنید که از همان هدف در حال انتظار استفاده می‌کند، جایگزین زنگ هشدار اصلی می‌شود.

برای لغو یک PendingIntent() ، FLAG_NO_CREATE به PendingIntent.getService() ارسال کنید تا نمونه‌ای از intent (در صورت وجود) دریافت شود، سپس آن intent را به AlarmManager.cancel() ارسال کنید.

کاتلین

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)
}

جاوا

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 : بر اساس مدت زمان سپری شده از بوت شدن دستگاه، intent در حال انتظار را اجرا می‌کند، اما دستگاه را بیدار نمی‌کند. زمان سپری شده شامل هر زمانی است که دستگاه در حالت خواب بوده است.

  • ELAPSED_REALTIME_WAKEUP : دستگاه را بیدار می‌کند و پس از گذشت مدت زمان مشخص شده از زمان بوت دستگاه، قصد (intent) در حال انتظار را اجرا می‌کند.

  • RTC : در زمان مشخص شده، قصد در حال انتظار را اجرا می‌کند اما دستگاه را از خواب بیدار نمی‌کند.

  • RTC_WAKEUP : دستگاه را برای اجرای intent در حال انتظار در زمان مشخص شده، بیدار می‌کند.

نمونه‌هایی از آلارم‌های بلادرنگ سپری‌شده

در اینجا چند مثال از استفاده از ELAPSED_REALTIME_WAKEUP آورده شده است.

دستگاه را برای به صدا درآوردن زنگ هشدار ظرف ۳۰ دقیقه و هر ۳۰ دقیقه پس از آن بیدار کنید:

کاتلین

// 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
)

جاوا

// 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);

دستگاه را برای فعال کردن یک زنگ هشدار یکباره (غیر تکراری) در عرض یک دقیقه بیدار کنید:

کاتلین

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
)

جاوا

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 آورده شده است.

دستگاه را برای به صدا درآوردن زنگ هشدار تقریباً ساعت ۲ بعد از ظهر بیدار کنید و این کار را روزی یک بار در همان ساعت تکرار کنید:

کاتلین

// 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
)

جاوا

// 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);

دستگاه را برای به صدا درآوردن زنگ هشدار دقیقاً رأس ساعت ۸:۳۰ صبح و هر ۲۰ دقیقه پس از آن بیدار کنید:

کاتلین

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
)

جاوا

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() انتخاب مناسبی است. وقتی از این روش استفاده می‌کنید، اندروید چندین آلارم تکرارشونده غیردقیق را همگام‌سازی کرده و همزمان آنها را فعال می‌کند. این کار باعث کاهش مصرف باتری می‌شود.

در صورت امکان از استفاده از آلارم‌های دقیق خودداری کنید. با این حال، برای برنامه‌های نادری که الزامات زمانی دقیقی دارند، می‌توانید با فراخوانی setRepeating() یک آلارم دقیق تنظیم کنید.

با استفاده از setInexactRepeating() ، نمی‌توانید مانند تابع setRepeating() یک بازه سفارشی تعیین کنید. باید از یکی از ثابت‌های بازه، مانند INTERVAL_FIFTEEN_MINUTES ، INTERVAL_DAY و غیره استفاده کنید. برای مشاهده لیست کامل به AlarmManager مراجعه کنید.

لغو زنگ هشدار

بسته به برنامه‌تان، ممکن است بخواهید قابلیت لغو زنگ هشدار را نیز اضافه کنید. برای لغو زنگ هشدار، تابع cancel() در Alarm Manager فراخوانی کنید و PendingIntent ای را که دیگر نمی‌خواهید فعال شود، به آن ارسال کنید. برای مثال:

کاتلین

// If the alarm has been set, cancel it.
alarmMgr?.cancel(alarmIntent)

جاوا

// 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 برای دریافت broadcast پیاده‌سازی کنید:

    کاتلین

    class SampleBootReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "android.intent.action.BOOT_COMPLETED") {
                // Set the alarm here.
            }
        }
    }

    جاوا

    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. گیرنده را به فایل مانیفست برنامه خود با یک فیلتر intent که روی اکشن 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" تنظیم شده است. این بدان معناست که گیرنده تا زمانی که برنامه صریحاً آن را فعال نکند، فراخوانی نخواهد شد. این امر از فراخوانی غیرضروری گیرنده بوت جلوگیری می‌کند. می‌توانید یک گیرنده را (به عنوان مثال، اگر کاربر زنگ هشدار را تنظیم کند) به شرح زیر فعال کنید:

    کاتلین

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP
    )

    جاوا

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

    وقتی گیرنده را از این طریق فعال می‌کنید، حتی اگر کاربر دستگاه را مجدداً راه‌اندازی کند، فعال می‌ماند. به عبارت دیگر، فعال کردن گیرنده از طریق برنامه‌نویسی، تنظیمات مانیفست را حتی در راه‌اندازی‌های مجدد نادیده می‌گیرد. گیرنده تا زمانی که برنامه شما آن را غیرفعال کند، فعال می‌ماند. می‌توانید یک گیرنده را غیرفعال کنید (برای مثال، اگر کاربر زنگ هشدار را لغو کند) به شرح زیر:

    کاتلین

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
    )

    جاوا

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

فعال کردن آلارم‌ها در حالت Doze دستگاه

دستگاه‌هایی که اندروید ۶.۰ (سطح API ۲۳) را اجرا می‌کنند از حالت Doze پشتیبانی می‌کنند که به افزایش عمر باتری دستگاه کمک می‌کند. وقتی دستگاه در حالت Doze است، آلارم‌ها فعال نمی‌شوند. هرگونه آلارم برنامه‌ریزی‌شده تا زمانی که دستگاه از Doze خارج شود، به تعویق می‌افتد. اگر نیاز دارید حتی زمانی که دستگاه در حالت آماده به کار است، کار خود را انجام دهید، چندین گزینه در دسترس است:

  • یک زنگ هشدار دقیق تنظیم کنید.

  • از API WorkManager که برای انجام کارهای پس‌زمینه ساخته شده است، استفاده کنید. می‌توانید مشخص کنید که سیستم باید کار شما را تسریع کند تا کار در اسرع وقت به پایان برسد. برای اطلاعات بیشتر، به بخش «زمان‌بندی وظایف با WorkManager» مراجعه کنید.

بهترین شیوه‌ها

هر انتخابی که در طراحی آلارم تکرارشونده خود انجام می‌دهید، می‌تواند پیامدهایی در نحوه استفاده (یا سوءاستفاده) برنامه شما از منابع سیستم داشته باشد. به عنوان مثال، یک برنامه محبوب را تصور کنید که با یک سرور همگام‌سازی می‌شود. اگر عملیات همگام‌سازی بر اساس زمان ساعت باشد و هر نمونه از برنامه ساعت 11 شب همگام‌سازی شود، بار روی سرور می‌تواند منجر به تأخیر زیاد یا حتی "عدم سرویس" شود. در استفاده از آلارم‌ها، این بهترین شیوه‌ها را دنبال کنید:

  • به هر درخواست شبکه‌ای که در نتیجه‌ی تکرار یک آلارم فعال می‌شود، تصادفی بودن (jitter) را اضافه کنید:

    • هر کار محلی را هنگام به صدا درآمدن زنگ هشدار انجام دهید. «کار محلی» به هر کاری گفته می‌شود که به سرور آسیب نمی‌رساند یا به داده‌های سرور نیاز ندارد.

    • همزمان، زنگ هشداری که شامل درخواست‌های شبکه است را طوری برنامه‌ریزی کنید که در یک بازه زمانی تصادفی فعال شود.

  • تعداد دفعات زنگ هشدار خود را به حداقل برسانید.

  • دستگاه را بی‌جهت روشن نکنید (این رفتار با توجه به نوع زنگ هشدار، همانطور که در بخش «انتخاب نوع زنگ هشدار» توضیح داده شده است، تعیین می‌شود).

  • زمان فعال شدن زنگ هشدار خود را دقیق‌تر از حد لازم تنظیم نکنید.

    به جای setRepeating setInexactRepeating() setRepeating() استفاده کنید. وقتی از setInexactRepeating() استفاده می‌کنید، اندروید آلارم‌های تکراری را از چندین برنامه همگام‌سازی کرده و آنها را همزمان اجرا می‌کند. این کار تعداد کل دفعاتی را که سیستم باید دستگاه را بیدار کند کاهش می‌دهد و در نتیجه مصرف باتری را کاهش می‌دهد. از اندروید ۴.۴ (API سطح ۱۹)، همه آلارم‌های تکراری ، آلارم‌های نادقیق هستند. توجه داشته باشید که اگرچه setInexactRepeating() نسبت به setRepeating() بهبود یافته است، اما اگر هر نمونه از یک برنامه تقریباً در یک زمان به سرور برسد، همچنان می‌تواند سرور را تحت فشار قرار دهد. بنابراین، برای درخواست‌های شبکه، همانطور که قبلاً بحث شد، کمی تصادفی بودن به آلارم‌های خود اضافه کنید.

  • در صورت امکان، از تنظیم زنگ هشدار خود بر اساس زمان ساعت خودداری کنید.

    آلارم‌های تکراری که بر اساس یک زمان دقیق شروع به کار هستند، به خوبی مقیاس‌بندی نمی‌شوند. در صورت امکان ELAPSED_REALTIME استفاده کنید. انواع مختلف آلارم در بخش بعدی با جزئیات بیشتری توضیح داده شده است.