Schedule Exact Alarms with AlarmManager on Android
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
Should consider
For less time-sensitive work you should use an inexact alarm. Check this use case where might not need an exact alarm.