AlarmManager not set or not firing on Marshmallow

2019-07-24 08:39发布

问题:

I have been successfully using the following construct to start an AlarmManager in some of my apps upto Android 5:

    Intent serviceIntent = new Intent(context, MyService.class);
    PendingIntent pi = PendingIntent.getService(context, alarmId, serviceIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    DateTime inMinutes = (new DateTime()).plusMinutes(60);


    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    am.set(AlarmManager.RTC_WAKEUP, inMinutes.getMillis(), pi);

But since Marshmallow, the AlarmManager is either not set or not firing any more after some idle time. It seems like the currently running alarm fires one more time, but then no new alarm will be set.

I read some documentation and it's most probably about Marshmallow Doze. So I implemented the following (and checked that it's actually being executed):

    Intent serviceIntent = new Intent(context, MyService.class);
    PendingIntent pi = PendingIntent.getService(context, alarmId, serviceIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    DateTime inMinutes = (new DateTime()).plusMinutes(minutes);


    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    if(Build.VERSION.SDK_INT >= 23)
        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, inMinutes.getMillis(), pi);
    else {
        if(Build.VERSION.SDK_INT >= 19) {
            am.setExact(AlarmManager.RTC_WAKEUP, inMinutes.getMillis(), pi);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, inMinutes.getMillis(), pi);
        }
    }

It doesn't change anything.

Is there a reliable way to set and fire alarms even on Marshmallow after some idle time?

回答1:

Of course, try with:

       setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)

Doze mode dont start if you set the alarm this way.I tested this on console.

Dont forget that AlarmClock Info have a different PendingIntentthat setAlarmclock.

UPDATE

If you want to make a simple alarm(not alarmclock).

this have to work

    setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation)

But i now that it doesn't. So i started looking and google and i found this. A possible way to add an app to doze whitelist. Maybe setExactAndAllowWhileIdle works.

https://developer.android.com/training/monitoring-device-state/doze-standby.html?hl=es

Users can manually configure the whitelist in Settings > Battery > Battery Optimization. Alternatively, the system provides ways for apps to ask users to whitelist them.

An app can fire the ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent to take the user directly to the Battery Optimization, where they can add the app. An app holding the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission can trigger a system dialog to let the user add the app to the whitelist directly, without going to settings. The app fires a ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent to trigger the dialog. The user can manually remove apps from the whitelist as needed. Before asking the user to add your app to the whitelist, make sure the app matches the acceptable use cases for whitelisting.