Schedule repeating alarms

Alarms (based on the AlarmManager class) give you a way to perform
time-based operations outside the lifetime of your application.
For example, you could use an alarm to initiate a long-running operation, such
as starting a service once a day to download a weather forecast.

Alarms have these characteristics:

They let you fire Intents at set times and/or intervals.

You can use them in conjunction with broadcast receivers to start services and perform
other operations.

They operate outside of your application, so you can use them to trigger events or
actions even when your app is not running, and even if the device itself is asleep.

They help you to minimize your app's resource requirements. You can schedule operations
without relying on timers or continuously running background services.

Note: For timing operations that are guaranteed to occur
during the lifetime of your application,
instead consider using the Handler class in conjunction with
Timer and Thread. This approach gives Android better
control over system resources.

Understand the trade-offs

A repeating alarm is a relatively simple mechanism with limited flexibility.
It may
not be the best choice for your app, particularly if you need to trigger network
operations. A poorly designed alarm can cause battery drain and put a significant load on
servers.

A common scenario for triggering an operation outside the lifetime of your app is
syncing data with a server. This is a case where you might be tempted to use a
repeating alarm. But if you own the server that is hosting your app's
data, using Google Cloud Messaging (GCM)
in conjunction with sync adapter
is a better solution than AlarmManager. A sync adapter gives you all
the same scheduling options as AlarmManager, but it offers
you significantly more flexibility. For example,
a sync could be based on a "new data" message from the server/device (see
Running a Sync
Adapter for details), the user's activity (or inactivity), the time of day, and so on.
See the linked videos at the top of this page for a detailed discussion of when and how
to use GCM and sync adapter.

Alarms do not fire when the device is idle in
Doze mode. Any scheduled alarms will
be deferred until the device exits Doze. If you need to ensure that your work completes even when
the device is idle there are several options available. You can use
setAndAllowWhileIdle() or
setExactAndAllowWhileIdle() to guarantee
that the alarms will execute. Another option is to use the new WorkManager API, which is built to perform
background work either once or periodically. For more information, see
Schedule tasks with WorkManager.

Best practices

Every choice you make in designing your repeating alarm can have consequences in how your
app uses (or abuses) system resources. For example, imagine a popular app that
syncs with a server. If the sync operation is based on clock time and every instance of the
app syncs at 11:00 p.m., the load on the server could result in high latency or even
"denial of service." Follow these best practices in using alarms:

Add randomness (jitter) to any network requests that
trigger as a result of a repeating alarm:

Do any local work when the alarm triggers. "Local work" means anything that doesn't
hit a server or require the data from the server.

At the same time, schedule the alarm that contains the network requests to fire at some
random period of time.

Keep your alarm frequency to a minimum.

Don't wake up the device unnecessarily (this behavior is determined by the alarm type,
as described in Choose an alarm type).

Don't make your alarm's trigger time any more precise than it has to be.

Use setInexactRepeating() instead
of setRepeating().
When you use setInexactRepeating(),
Android synchronizes repeating alarms from multiple apps and fires
them at the same time. This reduces the total number of times the system must wake the
device, thus reducing drain on the battery. As of Android 4.4
(API Level 19), all repeating alarms are inexact. Note that while
setInexactRepeating() is an
improvement over setRepeating(), it can
still overwhelm a server if every instance of an app hits the server around the same time.
Therefore, for network requests, add some randomness to your alarms, as discussed above.

Avoid basing your alarm on clock time if possible.

Repeating alarms that are based on a precise trigger time don't scale well.
Use ELAPSED_REALTIME if you can. The different alarm
types are described in more detail in the following section.

Set a repeating alarm

As described above, repeating alarms are a good choice for scheduling regular events or
data lookups. A repeating alarm has the following characteristics:

A trigger time. If the trigger time you specify is in the past, the alarm triggers
immediately.

The alarm's interval. For example, once a day, every hour, every 5 minutes, and so on.

A pending intent that fires when the alarm is triggered. When you set a second alarm
that uses the same pending intent, it replaces the original alarm.

Choose an alarm type

One of the first considerations in using a repeating alarm is what its type should be.

There are two general clock types for alarms: "elapsed real time" and "real time clock"
(RTC).
Elapsed real time uses the "time since system boot" as a
reference, and real time clock uses UTC (wall clock) time. This means that
elapsed real time is suited to setting an alarm based on the passage of time (for
example, an alarm that fires every 30 seconds) since it isn't affected by
time zone/locale. The real time clock type is better suited for alarms that are dependent
on current locale.

Both types have a "wakeup" version, which says to wake up the device's CPU if the
screen is off. This ensures that the alarm will fire at the scheduled time. This is useful
if your app has a time dependency—for example, if it has a limited window to perform a
particular operation. If you don't use the wakeup version of your alarm type, then
all the repeating alarms will fire when your device is next awake.

If you simply need your alarm to fire at a particular interval (for example, every half
hour), use one of the elapsed real time types. In general, this is the better choice.

If you need your alarm to fire at a particular time of day,
then choose one of the clock-based real time clock types. Note, however, that this approach can
have some drawbacks—the app may not translate well to other locales, and if the user
changes the device's time setting, it could cause unexpected behavior in your app. Using a
real time clock alarm type also does not scale well, as discussed above. We recommend
that you use a "elapsed real time" alarm if you can.

Here is the list of types:

ELAPSED_REALTIME—Fires the pending intent based
on the amount of time since the device was booted, but doesn't wake up the device. The
elapsed time includes any time during which the device was asleep.

ELAPSED_REALTIME_WAKEUP—Wakes up the device and
fires the pending intent after the specified length of time has elapsed since device
boot.

RTC—Fires the pending intent
at the specified time but does not wake up the device.

RTC_WAKEUP—Wakes up the
device to fire the pending intent at the specified time.

Examples of real time clock alarms

Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day
at the same time:

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

Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes
thereafter:

Decide how precise your alarm needs to be

As described above, choosing the alarm type is often the first step in creating an alarm.
A further distinction is how precise you need your alarm to be. For most apps,
setInexactRepeating() is the right
choice.
When you use this method, Android synchronizes multiple inexact repeating alarms and fires
them at the same time. This reduces the drain on the battery.

For the rare app that has rigid time requirements—for example, the alarm needs to
fire precisely at 8:30 a.m., and every hour on the hour
thereafter—use setRepeating(). But you
should avoid using exact alarms if possible.

Cancel an alarm

Depending on your app, you may want to include the ability to cancel the alarm.
To cancel an alarm, call cancel() on the Alarm
Manager, passing in the PendingIntent you no longer want to fire. For
example:

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

Start an alarm when the device restarts

By default, all alarms are canceled when a device shuts down.
To prevent this from happening, you can design your application
to automatically restart a repeating alarm if the user reboots the device. This ensures
that the AlarmManager will continue doing its task without the user
needing to manually restart the alarm.

Here are the steps:

Set the RECEIVE_BOOT_COMPLETED permission in your application's manifest. This allows
your app to receive the
ACTION_BOOT_COMPLETED that is broadcast after the system
finishes booting (this only works if the app has already been launched by the user at least once):

Notice that in the manifest, the boot receiver is set to
android:enabled="false". This means that the receiver will not be called
unless the application explicitly enables it. This prevents the boot receiver from being
called unnecessarily. You can enable a receiver (for example, if the user sets an alarm)
as follows:

Once you enable the receiver this way, it will stay enabled, even if the user reboots
the device. In other words, programmatically enabling the receiver overrides the
manifest setting, even across reboots. The receiver will stay enabled until your app disables it.
You can disable a receiver (for example, if the user cancels an alarm) as follows:

Impacts of Doze and App Standby

Doze and App Standby were introduced in Android 6.0 (API level 23) in an effort to extend device
battery life. When the device is in Doze mode any standard alarms will be deferred until the
device exits Doze mode or a maintenance window opens. If you must have an alarm fire even in Doze
mode you can use either setAndAllowWhileIdle()
or setExactAndAllowWhileIdle().
Your app will enter App Standby mode when it is idle, meaning the user has not used it for a period
of time and the app does not have a foreground process. When the app is in App Standby alarms are
deferred just like in Doze mode. This restriction is
lifted when the app is no longer idle or if the device is plugged in to a power supply. For more
information on how your app is impacted by these modes, read
Optimizing for Doze and App Standby.