Android AlarmManager.set(…): notification never re

2019-08-12 04:10发布

I'm attempting to use AlarmManager to schedule a delayed check in my app. (Specifically, N minutes after a user approaches a location, I want to check whether they're still there, and if so send them a notification.)

I've implemented this by checking to see whether they've entered the region in my location update receiver and, if they have, scheduling like so:

Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, getGeofenceDelaySeconds());
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
Log.v("Scheduling notification check for "+c.getTime());

When the battery level is high (say, 50%), everything works like a charm. But when it's low (say, 10%), I get location updates, they schedule the alarm seemingly-successfully, but that alarm never actually triggers!

What gives? Does Android stop sending certain types of updates when it's trying to conserve power? How can I work around this (short of actually keeping my app active for the duration of the delay, which causes obvious issues with battery life)?

1条回答
啃猪蹄的小仙女
2楼-- · 2019-08-12 04:22

It turns out that this is related to the use of the real-time clock.

Although I could not find the documentation it quotes (it's not in AlarmManager), this StackOverflow answer suggests that AlarmManager.RTC_WAKEUP alarms do not trigger if the phone is in power-saving mode. AlarmManager.ELAPSED_REALTIME_WAKEUP alarms do not seem to suffer this problem, so I was able to fix the issue by switching to:

Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);

long millis = SystemClock.elapsedRealtime() + 1000 * getGeofenceDelaySeconds();
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, millis, pi);
查看更多
登录 后发表回答