Schedule Exact Alarms with AlarmManager on Android

Abu Yousuf
2 min readAug 25, 2023

--

In Android Development precise task scheduling is essential for reliable and responsive applications. Recently in a project, I had to schedule a task at a precise time. I have used AlarmManager exact alarm in that project. I will share my learning and experience here.

Why Exact Alarm?

Exact Alarm is essential when your app requires a time-sensitive task to execute. InExact alarm depends on system optimization and exact alarm guarantee that it will be triggered at a specific time.

From Official doc:

InExact :

When an app sets an inexact alarm, the system delivers the alarm at some point in the future.

Exact:

The system invokes an exact alarm at a precise moment in the future.

Understanding Android Exact Alarm

The AlarmManager class supports time-based operation. AlarmManager can operate outside the lifetime of your application, so your app doesn’t need to run in the background.

Implementation steps of Exact AlarmManager:

  • Acquiring AlarmManager: Get an instance of the AlarmManager service using getSystemService() method
  • Creating PendingIntent: Use PendingIntent class to define the intent that will be triggered when the alarm fires.
  • Schedule the Alarm: Set up the exact Alarm by using the exact alarm API from the AlarmManager class. There are 3 APIs for the exact Alarm
  • setExactAndAllowWhileIdle() : This invokes an alarm at a nearly precise time in the future, even if battery-saving measures are in effect
  • Handling the Alarm: To handle an alarm you need to use a BroadCastReceiver. Ensure that your app’s BroadcastReceiver receives the intent from the PendingIntent you created earlier.

Here is the simple code to schedule Alarm

First, create a BroadcastReceiver

class AlarmReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
Log.i("AlarmReceiver", "Alarm Received")
}
}

Then schedule Alarm

   private val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

fun schedule(requestCode: Int , triggerTimeInMillis : Long) : Boolean {

if (triggerTimeInMillis < System.currentTimeMillis()) {
return false
}
val pendingIntent = getPendingIntent(requestCode)
val alarmClockInfo =AlarmClockInfo(triggerTimeInMillis, pendingIntent)
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
Log.i("AlarmScheduler", "Alarm Scheduled")
return true
}

private fun getPendingIntent(requestCode : Int) : PendingIntent {
return PendingIntent.getBroadcast(
context,
requestCode,
getIntent(),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
}

private fun getIntent() : Intent {
return Intent(context, AlarmReceiver::class.java)
}

Register your BroadcastReceiver in AndroidManifest

<receiver android:name=".AlarmReceiver"/>

That’s it

If your app targets Android 12 or higher you must declare “uses-permission android:name=”android.permission.SCHEDULE_EXACT_ALARM”

If your app targets Android 13 (API level 33) or higher, you have the option to declare either the SCHEDULE_EXACT_ALARM or the USE_EXACT_ALARM permission.

Check official doc for more details.

There is an excellent article by Pablo Guardiola that explains different types of alarms. He also added a flow chart for making decisions about which API you should use.

Here is the flow

Flow chart for choosing Alarm API

Should consider

For less time-sensitive work you should use an inexact alarm. Check this use case where might not need an exact alarm.

--

--