Creating a alarm using AlarmManager in Android

Mubarak Native
6 min readMay 2, 2024

--

In this article i will show how to create an alarm using the AlarmManager class and what are the methods we will need to care about and more so let’s jump right into it.

AlarmManager is also a system service like other services on android, such as the Notification service. It helps us to execute some piece of code at a certain time when our application isn’t in the foreground.

Create a alarm

Let’s explore the syntax of declaring alarm manager class.

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

This is the syntax declaration of AlarmManger class, Now explore some of the methods in AlarmManager class that is important that decide the behaviour of our alarm.

I divided the method into two types In Exact alarms and Exact alarms.

In Exact alarms

In Exact alarms are those alarms that the system doesn’t guarantee the alarm will trigger at a supplied time. This is basically because exact alarms will need to hold a CPU awake. That affects our battery life and system resources.

Methods that come in the categories of In Exact alarms are:

/* 1. */ set(type:Int,triggerAtMillis:Long,operation:PendingIntent)
/* 2. */ setInexactRepeating(type:Int,triggerAtMillis:Long,intervalMillis:Long,operation:PendingIntent)
/* 3. */ setAndAllowWhileIdle(type:Int,triggerAtMillis:Long,operation:PendingIntent)
  1. set() : Execute a alarm that isn’t guarantee to be same as supplied time.
  2. setInexactRepeating() : Same as set() method, But with a repeating alarm we need to provide a interval at in mills seconds (Long).

Exact alarms

Exact alarms are those alarms, that system execute it at precisely with our supplied time, But it consumes our system resources lot.

Only use it, if our application is depend on exact alarm execution such example would be : Alarm clock app, or calendar app.

Methods that come in the categories of Exact alarms are.

/* 1. */ setExact(type:Int,triggerAtMillis:Long,operation:PendingIntent)
/* 2. */ setExactAndAllowWhileIdle(type:Int,triggerAtMillis:Long,operation:PendingIntent)
  1. setExact() : Execute a alarm at precise given time only if any-battary restrictions a.k.a (doze mode) are not there.
  2. setExactAndAllowWhileIdle() : This is the method we usually use in our alarm application where it execue a alarm precisely and doesn’t consider is the system is in low power mode or not.

Permission on Exact alarm

Whenever we use a Exact alarm we need a permission, there are two types of permission for exact alarms, Let’s explore it one by one.

If our target application api level is 31 / Android 12 or higher, We need to declare SCHEDULE_EXACT_ALARM this is a runtime permission it is must granted by user explicitly.

If our target application api level is 33 / Android 13 or higher, We have a option to declare USE_EXACT_ALARM this is a normal permission, doesn’t need to grant by user explicitly, Only use this permission in your app if your app core logic is based on exact alarm such as : Alarm clock app.

Declare the permission on AndroidManifest.xml

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />

I am developing alarm clock app, So i use USE_EXACT_ALARM permission.

So far we learned different types of methods in AlarmManager class to trigger alarm and we also declared necessary permission on exact alarm, Let’s dig even more and develop a simple alarm clock app.

        
// MainActivity.kt
val alarmManager: AlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

binding.btnScheduleAlarm.setOnClickListener {
val inputSeconds = binding.etAlarmInMillis.text.toString().toLong() * 1000 // don't forgot to set input type to number in edittext
val inputMessage = binding.etAlarmMsg.text.toString()

val pendingIntent = PendingIntent.getBroadcast(
this@MainActivity,
YOUR_UNIQUE_ID,
Intent(this, AlarmReceiver::class.java).apply {
putExtra("ALARM_MSG", inputMessage)
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
inputSeconds,
pendingIntent
)
}

binding.btnCancelAlarm.setOnClickListener {
alarmManager.cancel(
PendingIntent.getBroadcast(
this,
YOUR_UNIQUE_ID, // use same id that is used to schedule the alarm to cancel it
Intent(this, AlarmReceiver::class.java),
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
)
}
// AlarmReceiver.kt
class AlarmReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {

val alarmMessage = intent?.getStringExtra("ALARM_MSG")

Log.d("alarmManager", alarmMessage!!)
}
}

Let’s revist the setExactAndAllowWhileIdle and see what are the parameters that this method expect.

setExactAndAllowWhileIdle(type:Int,triggerAtMillis:Long,operation:PendingIntent)
  1. ) type: Int = Specify the type of the alarm we need to use in our alarm manager class.

Types of alarm

There are two types of general clock alarm, ELAPSED & RTC both have a wakeup versions to wake up the device screen.

ELAPSED

Elapsed real time calculate the time since device is boot .

AlarmManager.ELAPSED_REALTIME = Elapsed realtime uses time since device boot including sleeping, But is doesn’t wake up the device screen.

AlarmManager.ELAPSED_REALTIME_WAKEUP = Same as ELAPSED_REALTIME but it also wake up the device screen.

RTC

RTC uses UTC the wall clock as a reference.

AlarmManager.RTC = Uses wall clock time it doesn’t wake up the device screen.

AlarmManager.RTC_WAKEUP = RTC with a wake up version.

In this example, i uses the AlarmManager.RTC_WAKEUP for my alarm clock app this is suitable for alarm clock app that needs to trigger the alarm based current locale and turn on the user display.

2. ) triggerAtMillis:Long = When to execute this alarm we need to provide the time value in mills (Long), we can easily convert our time into millis in our real world app by the help of Material Time Picker in Views System we easily pick the hour and minute, and we convert the hours and minute to mills second (Long) using java.util.Calendar.

This is the code for that.

for this example i use seconds from the user input in EditText and just convert it into by just multiply the second value * 1000, We get the millis second value.

3. ) operation:PendingIntent

We need to provide PendingIntent it executes when our alarm is triggered, We usually wrap our PendingIntent With our intent, In this case our destination would be a BroadCast receiver, it happens outside of our application, So we use Broadcast receiver here. if you want to pass some data into your receiver class, pass that data using Intent Extra.

Note : While creating PendingIntent you need to pass this flag PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT this is because of security reasons in android.

Don’t forgot to register your broadcast receiver in AndroidManifest.xml.

<!-- AndroidManifest.xml -->        
<receiver android:name=".AlarmReceiver" />

Alarm get cancelled when the device is restart.

By default all alarms are cancelled when the device is restart, We need to manually schedule the alarm again.

Create a another Broadcast receiver for Boot Completion, the system will send a broadcast when the device is restarted, We need to observe it.

Add a permission in AndroidManifest.xml

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- Don't forgot to register this broadcast receiver in AndroidManifest.xml -->
<receiver android:name=".BootCompletedReceiver"/>
class BootCompletedReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == "android.intent.action.BOOT_COMPLETED"){
// Set your alarm here
}
}
}

Cancel the alarm

To cancel the scheduled alarm we simply call cancel() in alarm manager class.

alarmManager.cancel(
PendingIntent.getBroadcast( // pass the pending intent
this,
YOUR_UNIQUE_ID, // this id is need to be same as the id you will use to schedule the alarm previously
Intent(this, AlarmReceiver::class.java),
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
)

Now, we understand how to create a basic alarm using AlarmManager, But we not limited to basic AlarmManager implementation, So i created a Alarm Clock app in Github

It will teaches you how to get time by using Material Time Picker and how to send a notification when alarm is triggered and how to store the scheduled alarm in Room database and more…

AlarmManagerExample app demo

Checkout : AlarmManagerEx Repository

This is all for this article, I hope you will find this article helpful, if it is don’t forgot to 👏applause this article that helps this article to separate out from writers who primarily just copy docs from developer page or generate the responses from AI.

Signing off 🫡, Mubarak Native

--

--

Mubarak Native

Mubarak Basha a.k.a (Mubarak Native) Mobile App Developer, Embedded Systems Developer, Tech talks lover,...