In this article, we will go through the improvements that Android12 brings for Exact alarms ⏰.
- To make sure that the effective usage of system resources, Android 12 requires the
“Alarms & reminders”
special app access if apps that target Android 12 want to set exact alarms. - SCHEDULE_EXACT_ALARM permission needs to be added in the manifest to get this special app access.
- Exact alarms should only be used for user-facing features. Acceptable use cases
Users or the system can revoke the “Alarms & reminders” special app access. All future exact alarms are canceled when the “Alarms & reminders” special app access is revoked for your app.
- The system sends the
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED broadcast to your app when the “Alarms & reminders” special app access is granted to your app.
- It will be sent to both runtime receivers and manifest receivers.
- It will not be sent when the user revokes the permission.
Check if the app has permission to set exact alarms?
- With the help of the canScheduleExactAlarms() method from
AlarmManager
, we can check that if we have access or not to set exact alarms ⏰
val alarmManager: AlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager | |
// check if our app can set exact alarms | |
if(alarmManager.canScheduleExactAlarms()){ | |
Log.d("MainActivity", "onCreate: SCHEDULE ALARM") | |
} |
canScheduleExactAlarms()
SecurityException occurs if an app tries to use APIs that set exact alarms but isn’t granted special app access.
Ask users to grant the app access
If canScheduleExactAlarms() returns false
, You can navigate the users to the Alarms & reminders screen
in system settings where they can provide this special access to our app.
To do so, complete the following steps:
- Explain to the user why your app needs to schedule exact alarms ⏰.
- Invoke an intent with
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
intent action
val alarmManager: AlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager | |
when { | |
alarmManager.canScheduleExactAlarms() -> { | |
Log.d("MainActivity", "onCreate: SCHEDULE ALARM") | |
} | |
else -> { | |
// go to exact alarm settings | |
Intent().apply { | |
action = ACTION_REQUEST_SCHEDULE_EXACT_ALARM | |
}.also { | |
startActivity(it) | |
} | |
} | |
} |
Open Alarms and Reminders Settings
BroadcasterReceiver implementation
To listen to the state of special app access permission, we need to implement the
BroadcasterReceiver
- AlarmReciever
class AlarmReceiver : BroadcastReceiver() { | |
private val TAG = "AlarmReceiver" | |
override fun onReceive(context: Context, intent: Intent) { | |
when (intent.action) { | |
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED -> { | |
Toast.makeText(context, "RECEIVED ALARM PERMISSION", Toast.LENGTH_LONG).show() | |
} | |
"from alarm" -> { | |
Toast.makeText(context, "ALARM FIRED", Toast.LENGTH_LONG).show() | |
} | |
} | |
} | |
} |
AlarmReceiver-Android12
- Register receiver via manifest
<receiver | |
android:name=".alarmreceiver.AlarmReceiver" | |
android:enabled="true" | |
android:exported="true"> | |
<intent-filter> | |
<action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" /> | |
<action android:name="from alarm" /> | |
</intent-filter> | |
</receiver> |
Add receiver to manifest
- Register runtime receiver
override fun onCreate() { | |
super.onCreate() | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | |
alarmReceiver = AlarmReceiver() | |
registerReceiver( | |
alarmReceiver, | |
IntentFilter(android.app.AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED), | |
) | |
} | |
} | |
override fun onDestroy() { | |
alarmReceiver?.let { | |
Log.d(TAG, "onStop: Un-register receiver") | |
unregisterReceiver(it) | |
} | |
super.onDestroy() | |
} |
Register runtime receiver
Job Offers
Check full sample code
😊😊 👏👏👏👏 HAPPY CODING 👏👏👏👏 😊😊
Demo 🥳🥳🥳🥳
- Special app access settings
Special app access settings
- Navigate to settings, allow the permission, and set the alarm
Application demo