Skip to main content

Exact Alarms

Exact alarms are alarms that will be invoked at a precise moment in the future.

Exact Alarm Permissions​

Before using exact alarms in your application, you need to declare one of these two permissions:

  1. SCHEDULE_EXACT_ALARM or
  2. USE_EXACT_ALARM.

Depending on your application's use cases, you should only declare either one of them.

SCHEDULE_EXACT_ALARM Permission​

You should use SCHEDULE_EXACT_ALARM permission if:

  • Your application targets API level 31 (or above).
  • Your application only uses exact alarms for secondary features, not core functionality.

SCHEDULE_EXACT_ALARM permission has these characteristics:

  • Before Android 14 (API level 34), this permission is granted by default. On Android 14 and above, this permission is no-longer being pre-granted to most newly installed apps targeting Android 13 and higher.
  • There is a setting page where user can grant/revoke this permission. Read more about this setting page here.
  • There is a dedicated method where you can check whether user has granted this permission. Read more about this here.
  • You can listen to a broadcast whenever this permission state is changed. Read more about this here.

Basic Usages​

Opening SCHEDULE_EXACT_ALARM Setting Page​

There is a dedicated setting page for user to toggle SCHEDULE_EXACT_ALARM permission. To access this page, navigate to Settings > Apps > Special app access > Alarm & reminders. Or you can programmatically open this page by using ACTION_REQUEST_SCHEDULE_EXACT_ALARM intent action:

import android.content.Context
import android.content.Intent
import android.os.Build
import android.provider.Settings
import androidx.core.content.ContextCompat.startActivity

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
startActivity(
context,
Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM),
null,
)
}

If we want to access our app's setting page directly, we can add our application package's URI to the intent:

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.core.content.ContextCompat.startActivity

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
startActivity(
context,
Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).apply {
data = Uri.parse("package:${context.packageName}")
},
null,
)
}

Checking Whether User Has Granted SCHEDULE_EXACT_ALARM Permission​

You can check whether user has granted SCHEDULE_EXACT_ALARM permission for your application by using canScheduleExactAlarms() method:

import android.app.AlarmManager
import android.content.Context
import android.os.Build
import android.util.Log

val alarmManager = context.getSystemService(AlarmManager::class.java)
val canSchedule = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
alarmManager.canScheduleExactAlarms()
} else {
null
}
Log.i("TAG", canSchedule.toString())

Listening Whenever SCHEDULE_EXACT_ALARM Permission State Changes​

You can listen to a broadcast whenever SCHEDULE_EXACT_ALARM permission is being granted (not revoked) by using ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED intent action.

Here is a simple broadcast receiver class that listens to the intent action:

ScheduleExactAlarmPermissionStateChangedBroadcastReceiver.kt
package com.hanmajid.androidnotebook

import android.app.AlarmManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log

/**
* Simple broadcast receiver that listens to [AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED]
* intent action.
*/
class ScheduleExactAlarmPermissionStateChangedBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED) {
val alarmManager = context.getSystemService(AlarmManager::class.java)
val canSchedule = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
alarmManager.canScheduleExactAlarms()
} else {
null
}
Log.i("TAG", canSchedule.toString())
}
}
}

Then you can register the broadcast receiver in your Context or AndroidManifest.xml file:

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application>

<receiver
android:name=".ScheduleExactAlarmPermissionStateChangedBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>

</manifest>

References​