【Kotlin/Android Studio】How to use AlarmManager! Time-specified processing with BroadcastReceiver
What you will learn from this article
- Android Studio/KotlinでAlarmManagerの実装方法
- BroadcastReceiverとは?
- 任意の指定した時間に処理を実行するには?
- 一定間隔でアラームを繰り返す
- setメソッドやsetExact、setInexactRepeatingの違いと役割
index
[open]
\ アプリをリリースしました /
Official Reference: AlarmManager
Official Reference: PendingIntent
Environment
- Android Studio:Meerkat
- Kotlin:2.0.21
What is AlarmManager
Android's AlarmManager is, like an alarm function, a class that allows you to schedule arbitrary processing to be executed at a specified future time. It's not just a delayed process; it can execute processes even when the device is in a sleep state, but this consumes a significant amount of battery, so care must be taken in its use.
The mechanism involves AlarmManager activating a specified Intent at a specific time, and this Intent then triggers the launch of a service or the sending of a broadcast (a mechanism to notify the system or other apps of an event).
Recommended Article: [Kotlin/Android Studio] What is an Intent? Passing data between Activities
The time for activating an Intent can be specified using RTC (Real-Time Clock) or absolute time.
RTC (Real-Time Clock)
RTC is used when you want to repeatedly issue events at a fixed time, like a typical alarm function. You specify only the time you want it to fire, and it fires each time it matches the system time.
Absolute Time
This is used when you want to issue an event only once at a specific date and time.
Events That Are Not Time-Accurate
Perhaps because Android prioritizes reducing battery consumption over functional accuracy, even with normal use, alarms are often not triggered at the exact specified time. Despite being able to specify time in milliseconds, delays of several seconds to several minutes in firing are common.
AlarmManager provides multiple methods for setting alarms, and if you want an alarm to fire more strictly on time, you should use a dedicated method.
Using BroadcastReceiver with AlarmManager
First, let's look at how to use AlarmManager itself. We will implement a feature to "display a toast 3 seconds after a button tap".
Flow
- Create BroadcastReceiver class
- Add settings to AndroidManifest
- Set alarm (broadcast) from MainActivity
1. Creating the BroadcastReceiver Class
First, we define a class that inherits from BroadcastReceiver, which is executed when a broadcast is received. The onReceive method is the method that is actually executed when a broadcast is received.
class ReceivedActivity : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Processing to execute when a broadcast is received
Toast.makeText(context, "Broadcast received!", Toast.LENGTH_SHORT).show()
}
}
Recommended Article: [Kotlin/Android] How to use BroadcastReceiver! Registration, release, and firing methods
2. Adding Configuration to AndroidManifest
Next, declare the class that will receive broadcasts in the manifest file. Be aware that without this, you cannot receive broadcasts.
<application
<!-- Omitted -->
<activity
<!-- Omitted -->
</activity>
<!-- Add -->
<receiver android:name=".ReceivedActivity"
android:process=":remote" />
</application>
3. Setting the Alarm (Broadcast) from MainActivity
From here, we will use the AlarmManager class to set an alarm for a future time. The detailed processing flow is left in the comments.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val alarmButton: Button = findViewById(R.id.button)
alarmButton.setOnClickListener {
// Get AlarmManager instance
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// Generate an Intent
val notificationIntent = Intent(this, ReceivedActivity::class.java)
// If you want to pass values from the Activity, store them here
notificationIntent.putExtra("Message", "Message you want to pass")
// Get PendingIntent for broadcasting
// The second argument, requestCode, can be 0 if there's only one broadcast to register, but needs to be changed if there are multiple -> e.g., data ID
val pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
// Define the execution time
// SystemClock.elapsedRealtime : Method to get elapsed time in milliseconds since system boot
val triggerTime = SystemClock.elapsedRealtime() + 3000L // 3 seconds later
// Set the alarm
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pendingIntent)
}
}
}
With this, an alarm event will be issued once, 3 seconds after tapping the button. The set method used at the end is the part that actually sets the alarm. In this implementation, the broadcast was issued approximately 3 seconds later without any particular deviation in the firing time.
Specifying with Absolute Time
If you want to set an alarm by explicitly specifying the date and time and want the broadcast to be issued at an exact time, use the setExact method instead of the set method. This method sets the event to be scheduled as accurately as possible to the specified time, but it is officially recommended not to use unnecessarily exact alarms. Also, when using methods that guarantee accuracy, you need to add the following two permissions to the manifest file.
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
To specify the time, create a Calendar instance, set the desired date and time, get the millisecond representation using the timeInMillis method, and pass it to the alarmManager.setExact method.
val timeZone = TimeZone.getTimeZone("Asia/Tokyo")
val calendar = Calendar.getInstance(timeZone) // Specify the time zone
calendar.timeInMillis = System.currentTimeMillis() // Initialize with current time (or 0 to reset completely)
calendar.set(Calendar.YEAR, 2023) // Set any year
calendar.set(Calendar.MONTH, Calendar.OCTOBER) // Set any month
calendar.set(Calendar.DAY_OF_MONTH, 22) // Set any day
calendar.set(Calendar.HOUR_OF_DAY, 11) // Set any hour
calendar.set(Calendar.MINUTE, 32) // Set any minute
calendar.set(Calendar.SECOND, 0) // Set any second
val triggerTime = calendar.timeInMillis // Get the millisecond representation of the specified date and time
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent)
Repeating Alarms at Regular Intervals
If you want to repeat alarm events at regular intervals, implement it as follows using setRepeating or setInexactRepeating.
val triggerTime = SystemClock.elapsedRealtime() + 3000L // 3 seconds later
val intervalTime = 10000L // 10-second interval
alarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerTime,
intervalTime,
pendingIntent
)
As the name setInexactRepeating (Set an inexact repeating alarm) suggests, the trigger time and interval are not exact. The official documentation also states, "it will not necessarily occur exactly on the hour".
Official Reference: setInexactRepeating
Incidentally, the interval duration can also be specified using AlarmManager constants as follows.
alarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerTime,
AlarmManager.INTERVAL_DAY, // 1 day later
pendingIntent
)
Registering Multiple Broadcasts
If you want to register multiple broadcasts, use the setType method to specify a type name for the Intent so it can be identified as a different type, and pass a non-duplicate number to the second argument requestCode of the getBroadcast method. For example, using a data ID is convenient.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val alarmButton: Button = findViewById(R.id.button)
alarmButton.setOnClickListener {
// Assume 'id' is a unique integer for each alarm
val id = System.currentTimeMillis().toInt() // Example of a unique ID
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val notificationIntent = Intent(this, ReceivedActivity::class.java)
// Specify the Intent type
notificationIntent.setType("NotifyIntent:" + id.toString())
notificationIntent.putExtra("Message", "Message you want to pass for ID: " + id)
// The second argument, requestCode, can be 0 if there's only one broadcast to register, but needs to be changed if there are multiple -> e.g., data ID
val pendingIntent = PendingIntent.getBroadcast(this, id, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
// SystemClock.elapsedRealtime : Method to get elapsed time in milliseconds since system boot
val triggerTime = SystemClock.elapsedRealtime() + 10000L // 10 seconds later
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pendingIntent)
}
}
}
In implementing alarm functions or notifications, it's often the case that you want to use the same Intent (ReceivedActivity in this instance) to execute it multiple times at different times, so this can be achieved using the code above.
Cancelling an Alarm
If you want to cancel a registered broadcast, etc., simply specify the Intent and execute the cancel method on both the PendingIntent and the AlarmManager.
// Assume 'context' and 'id' (the one used for registration) are available
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val notificationIntent = Intent(context, ReceivedActivity::class.java)
notificationIntent.setType("NotifyIntent:" + id.toString())
val pendingIntent = PendingIntent.getBroadcast(context, id, notificationIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE) // Use FLAG_NO_CREATE if you only want to cancel an existing one
if (pendingIntent != null) {
pendingIntent.cancel()
alarmManager.cancel(pendingIntent)
}
Types and Differences of AlarmManager Alarm Settings
Several methods for setting alarms have been introduced, so their roles and features are summarized here.
set
Official Reference: set method
- Method to schedule an alarm at the specified time
- If the specified time is in the past, it fires immediately
- Trigger time is inexact (will not be delivered before the specified time, but may be deferred)
setExact
Official Reference: setExact method
- Method to schedule an alarm accurately at the specified time
- If the specified time is in the past, it fires immediately
- Delivered as close as possible to the requested trigger time
- Excessive use is discouraged
setRepeating
Official Reference: setRepeating method
- Method to schedule an alarm at a specified time and repeat at a specified interval
- If the specified time is in the past, it fires immediately
- Trigger time/interval time is relatively accurate (repetition is generally inexact)
- Note: As of API 31, exact alarms using this method require the SCHEDULE_EXACT_ALARM permission. Consider setInexactRepeating for most use cases.
setInexactRepeating
Official Reference: setInexactRepeating method
- Method to schedule an alarm at a specified time and repeat at a specified interval
- If the specified time is in the past, it fires immediately
- Trigger time/interval time is inexact
setAndAllowWhileIdle
Official Reference: setAndAllowWhileIdle method
- Method to schedule an alarm at the specified time
- If the specified time is in the past, it fires immediately
- Executes even if the system is in low-power idle (Doze) mode
setAlarmClock
Official Reference: setAlarmClock method
- Method to schedule an alarm at the specified time
- If the specified time is in the past, it fires immediately
- Schedules an alarm that represents a clock alarm (e.g., for a user-visible alarm clock app)
- Expected to wake the device, turn on the screen, play a sound, and vibrate to notify the user
- Executes even if the system is in low-power idle (Doze) mode
Types and Differences of AlarmManager Constants
The types and differences of AlarmManager constants passed as the first argument to methods like set are summarized here.
AlarmManager.RTC
Official Reference: AlarmManager.RTC
Sets an alarm based on the system clock (wall clock time). Does not wake up the device; if the device is asleep when it goes off, it will not be delivered until the device next wakes up.
AlarmManager.RTC_WAKEUP
Official Reference: AlarmManager.RTC_WAKEUP
Sets an alarm based on the system clock (wall clock time). Wakes up the device even if it is asleep.
AlarmManager.ELAPSED_REALTIME
Official Reference: AlarmManager.ELAPSED_REALTIME
Sets an alarm based on the elapsed time since the device booted (using SystemClock.elapsedRealtime()). Does not wake the device. If the device is asleep, the alarm will not be delivered until it next wakes up.
AlarmManager.ELAPSED_REALTIME_WAKEUP
Official Reference: AlarmManager.ELAPSED_REALTIME_WAKEUP
Sets an alarm based on the elapsed time since the device booted. Wakes up the device if it is asleep. This is specified when using SystemClock.elapsedRealtime() to designate the trigger time.
Implementing Notifications Using AlarmManager
Recommended Article: [Kotlin/Android Studio] How to Issue Notifications at a Specified Date and Time! Reminder Function
I am still learning, so if you find any mistakes or shortcomings, I would appreciate it if you could let me know.
Thank you for reading.






