Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test daily alarms on Android?

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?

like image 457
grapescan Avatar asked Feb 08 '17 07:02

grapescan


People also ask

How to test alarmmanager in Android?

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.

How does your app set exact alarms?

Your app can set exact alarms using one of the following methods. These methods are ordered such that the ones closer to the bottom of the list serve more time-critical tasks but demand more system resources. Invoke an alarm at a nearly precise time in the future, as long as other battery-saving measures aren't in effect.

Can I test if my alarm is set properly?

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.

How can I schedule an alarm every one hour on Android?

You can use blip blip (hourly chime) alarn apk. That can help you to schedule an alarm every one hour on your android devices... It is available on play store..


1 Answers

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
                 [..]
            }
        }
    }
    
like image 117
dieter Avatar answered Oct 13 '22 03:10

dieter