9

One of my pet projects shows notifications on specific dates defined by user. I use

AlarmManger.setRepeating(AlarmManager.RTC_WAKEUP, millis, AlarmManager.INTERVAL_DAY, pendingIntent)

to schedule daily alarm which launches app to decide if it should show notification today.

The problem is that sometimes daily alarm stops working. I know a number of reasons for that (device reboot, date/time change, app reinstall, doze mode) and I am sure there are some reasons I did not find yet (ideas are welcome!).

My question is how to test alarms properly against all possible risks? Do instrumentation tests fit here?

grapescan
  • 241
  • 1
  • 4
  • 9

2 Answers2

10

My question is how to test alarms properly against all possible risks? Do instrumentation tests fit here?

Since AlarmManager is part of Android OS and therefore well tested, you don't have to do any instrumentation or unit tests to test it. You can test your services called by an alarm, but there is no need to test whether your alarm set properly or not.

There are only a few situations where your alarm is dropped, get invalid or ignored. You called them already:

  • on reboot
  • on time change
  • on doze mode

Now what you can do, is to use the system notifications (OS broadcasts) to reconfigure your alarms.

On reboot
Alarm are dropped on device shutdown, so set it again on reboot

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            // set repeating alarm 
            MyAlarmMangerSupport.set(context);
        }
    }
}

On time change
The same procedure on time change:

public class TimeChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (Intent.ACTION_TIME_CHANGED.equals(action ) || Intent.ACTION_TIMEZONE_CHANGED.equals(action )) {
            // cancel previous alarm and set a new one
            MyAlarmMangerSupport.cancelAndSet(context);
        }
    }
}

On doze mode
I believe there is no need to show any irrelevant notifications if a device entered the doze mode Anyway, there is a way to get an alarm fired even if a device is in doze.

It's important to know, that doze mode is a new feature starting from API level 23.

  1. Users have to whitelist your app and disable Battery Optimization for your app.

  2. Use setExactAndAllowWhileIdle method to set your alarm for devices with android level 23+:

    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, period, pendingIntent);
    

    Important: This as an single shot alarm you have to set it again in your alarm receiver:

    public class AlarmReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
    
            if ("my-Pet-Notification".equals(action )) {
                 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                     // set repeating alarm, calls setExactAndAllowWhileIdle
                     MyAlarmMangerSupport.set(context);
                 }
    
                 //execute service to show notification
                 [..]
            }
        }
    }
    
Community
  • 1
  • 1
dieter
  • 7,789
  • 5
  • 40
  • 64
0

Register again your alarm manger when device reboot and date/time change work properly.

Gautam
  • 1,276
  • 12
  • 30