Implementing Alarm manager
July 3, 2021 by Hrithik Sharma
How to implement an alarm in your android application using AlarmManager?
Android AlarmManager
allows you to access system alarm.
With the help of AlarmManager
in android, you can schedule your application to run at a specific time in the future.
AlarmManager
is a bridge between application and Android system alarm service. It can send a broadcast to your app (which can be completely terminated by user) at a scheduled time and your app can then perform any task accordingly.
With the help from PendingIntent
and Intent
, a bundle of information can also be sent together with the system broadcast to your application when alarm goes off.
However, since Android KitKat (API 19) and Android MarshMallow (API 23), Google has added different restrictions on AlarmManager
to reduce the battery usage. Alarm no longer goes off exactly at the assigned time by default. System has the ability to defer any alarm in order to optimise the device performance.
Note: This should be keep in mind that AlarmManager doesn’t keep record of the scheduled alarms after the device is booted. Your application should re-register all the scheduled alarms after the device is booted.
An alarm notification can be sent to the application, at the scheduled time when the BroadcastReceiver
receives the intent, using Notification.Builder
Now it’s time to understand the code behind it :
Step 1. Create a BroadcastReceiver :
-
First create a class that extends
BroadcastReceiver
and implementonReceive()
method in the classBroadcastReceiver
is a class for receiving and handling the broadcast sent to your application. In system alarm case, it receives broadcast from the system alarm service when alarm goes off.public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if ((Intent.ACTION_BOOT_COMPLETED).equals(intent.getAction())){ // reset all alarms } else{ // perform your scheduled task here (eg. send alarm notification) } } }
Whenever your device reboots the
BroadcastReceiver
is called and with the help ofIntent
we can re-register all the alarms using actionACTION_BOOT_COMPLETED
.In the else part you can perform your task (e.g, send alarm notification).
We will further see how to send notification to your application.
-
Register this receiver in your
AndroidManifest.xml
file<receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
is added in <intent-filter>
so that we can handle the situation to re-register all the scheduled alarms when the device will reboot.
Step 2: Setup in activity :
Code in the activity to schedule an alarm at any specific time is explained step by step below:
-
Get
AlarmManager
instanceimport android.app.AlarmManager; AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
AlarmManager
is actually a system service and thus can be retrieved fromContext.getSystemService()
function with parameterContext.ALARM_SERVICE
. -
Prepare for an intent
import android.content.Intent; Intent intent = new Intent(this, AlarmReceiver.class); intent.putExtra("any_data",123);
Android allows a bundle of information to be sent to a target receiver
(i.e. AlarmReceiver
, which is defined in step 1) when alarm goes off. The designated receiver and the corresponding information can be set in Intent
by setting its action
and extra
. These information can later be retrieved at the onReceive()
callback in the designated BroadcastReceiver
and action
field is checked to ensure the correctness of the system broadcast.
-
Prepare for an PendingIntent
import android.app.PendingIntent; PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent
is a reference pointing to a token maintained by the Android system. Thus, it will still be valid if the application is killed by user and can be broadcasted at some moment in the future.
2nd parameter of getBroadcast()
is requestCode which should be unique for every pendingIntent when you want to schedule multiple alarms.
For your information:
There are totally 4 functions for initialising a PendingIntent
but only 1 of them is applicable:
1. PendingIntent.getBroadcast()
— Applicable to AlarmManager
2. PendingIntent.getActivity()
3. PendingIntent.getActivities()
4. PendingIntent.getService()
Flags indicates how system should handle the new and existing PendingIntent
s that have the same Intent
. 0
indicates that system will use its default way to handle the creation of PendingIntent
. The following are some examples:
1. FLAG_UPDATE_CURRENT
2. FLAG_CANCEL_CURRENT
3. FLAG_IMMUTABLE
-
Set the alarm time and sent to system
The best way to set the time of the alarm is by using a
Calendar
objectimport java.util.Calendar; Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, hourOfDay); // set hour cal.set(Calendar.MINUTE, minute); // set minute cal.set(Calendar.SECOND, 0); // set seconds alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),pendingIntent);
The simplest way to set an alarm is using setExactAndAllowWhileIdle()
with parameter RTC_WAKEUP
. This would tell Android fires the alarm exactly at the assigned time no matter the system is in doze mode (idle mode).
If you want to repeat your alarm on a particular Day of Week then:
cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
long interval = 7 * 24 * 60 * 60 * 1000; // interval of 7 days
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), interval , pendingIntent);
Set the day of week you want repeat the alarm to Calendar.DAY_OF_WEEK
and use setRepeating()
method of alarmManager.
Some more methods of alarmManager :
1. alarmManager.set()
2. alarmManager.setExact()
3. alarmManager.setAlarmClock()
4. alarmManager.setInExactRepeating()
5. alarmManager.setRepeating()
6. alarmManager.setTime()
7. alarmManager.setTimeZone()
Canceling of an alarm:
However, it is tricky to cancel a PendingIntent
since it depends on both the Intent
and requestCode
used.
The alarm with PendingIntent
can be cancelled with the following steps:
-
Get
AlarmManager
instanceAlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-
Prepare for the Intent
Intent intent = new Intent(this, AlarmReceiver.class);
-
Prepare for the PendingIntent
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0 , intent, PendingIntent.FLAG_UPDATE_CURRENT);
Note : To cancel a particular scheduled alarm the requestCode
used in PendingIntent
must be same to that which is used to register that alarm.
-
Now cancel the alarm using AlarmManager instance
alarmManager.cancel(pendingIntent);
Handling of an alarm event:
AlarmManager
provides two ways to listen to an alarm broadcast. They are
-
Local listener (AlarmManager.OnAlarmListener)
-
BroadcastReceiver
specified at theIntent
wrapped inside aPendingIntent
.
The implementation of AlarmManager.OnAlarmListener
is similar to the one using PendingIntent
, instead it requires a callback and its corresponding Handler
:
String tag = "TAG";
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), tag, new AlarmManager.OnAlarmListener() {
@Override
public void onAlarm() {
Toast.makeText(OwnerSettingsActivity.this, "AlarmManager.OnAlarmListener", Toast.LENGTH_SHORT).show();
}
},null);
There is a limitation on AlarmManager.OnAlarmListener
over PendingIntent
. It cannot work when the corresponding Activity
or Fragment
is destroyed since the callback object is released at the same time. However, because PendingIntent
is sent to the system alarm service, it can be fired even when the application is killed by user.
Summary
Android provides an alarm service to notify application at any specific time with the corresponding assigned information stored in Intent
.
Along with the evolution of Android system throughout the years, Android applies more controls of alarm service to optimise the battery consumption.
setExactAndAllowWhileIdle()
together with WAKE_UP
type should only be used when the alarm time must be as exact as possible.
App developer should bear in mind to re-register all the alarms again when device is booted since Android does not store any alarms by default.
Hope this article can bring something to you! 😉 See you next time
Thank you for reading 🙌🏼