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
setExact(): This API invokes an alarm at a nearly precise time in the future if other battery-saving measures aren’t in effect
setExactAndAllowWhileIdle() : This invokes an alarm at a nearly precise time in the future, even if battery-saving measures are in effect
setAlrmClock() : This invokes an alarm at a precise time in the future. The system treats this as the most critical one.
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.
Subscribe to my newsletter
Read articles from Abu Yousuf directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Abu Yousuf
Abu Yousuf
Hi, I'm Abu Yousuf. Software engineer, currently focusing on Android.