My own app uses the exact same technique as shown by Google I/O app of 2016. see source
I need to remind users at a very specific point in time - using a notification.
For this, I use the AlarmManager
to wake the device at the correct point in time:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
} else {
am.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
}
The pendingIntent
is created like this:
final Intent intent = new Intent(MyAlarmService.ACTION_NOTIFY_RIDE, null, this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Now, my MyAlarmService
class is a simple IntentService
handling the wake-up just for the purpose of create a notification for the user.
The message I get in the log is the following:
W/ActivityManager: Background start not allowed: service Intent { act=xxx.xxx.xxx.action.NOTIFY_RIDE flg=0x4 cmp=xxx.xxx.xxx./xxx.xxx.xxx.service.MyAlarmService (has extras) }
Now, Google's own implementation is obviously broken - even though I do not want to do any heavy background work, I cannot use this technique anymore. But HOW am I supposed to wake up the user at a very specific point in time then? (think of my App as an alarm clock)
The answer to my question is plain and simple:
Instead of using a service to display the notification (as Google does in its IO Schedule app!), use a BroadcastReceiver!
I have no idea why Google did use an IntentService, but now on Android O, this is simply not working anymore due to background execution limits.
A BroadcastReceiver though obviously still can run for a brief moment and display a notification.
Bonus points if somebody could tell me why Google used an IntentService in the first place... this took me ages to figure out, because I thought Google knows what they are doing... :(
But HOW am I supposed to wake up the user at a very specific point in time then? (think of my App as an alarm clock)
First, your code will not be exact. If the device is in Doze mode, I would expect at best +/- 10 minutes. If you want exact timing, and your app really is an alarm clock, use setAlarmClock()
.
For your existing code, use getForegroundService()
instead of getService()
on API Level 26+.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With