Android O 和背景限制阻止简单的警报通知
Android O and background limits prevents simple alarm notification
我自己的应用程序使用与 2016 年 Google I/O 应用程序完全相同的技术。see source
我需要在非常具体的时间点提醒用户 - 使用通知。
为此,我使用 AlarmManager
在正确的时间点唤醒设备:
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);
}
pendingIntent
是这样创建的:
final Intent intent = new Intent(MyAlarmService.ACTION_NOTIFY_RIDE, null, this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
现在,我的 MyAlarmService
class 是一个简单的 IntentService
处理唤醒,目的只是为了为用户创建通知。
我在日志中得到的信息如下:
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) }
现在,Google 自己的实现显然已损坏 - 尽管我不想做任何繁重的后台工作,但我不能再使用这种技术了。但是我应该如何在非常特定的时间点唤醒用户呢? (把我的 App 想象成一个闹钟)
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)
首先,您的代码不准确。如果设备处于打瞌睡模式,我预计最多 +/- 10 分钟。如果您想要准确的时间,并且您的应用确实是一个闹钟,请使用 setAlarmClock()
.
对于您现有的代码,在 API 级别 26+ 上 use getForegroundService()
而不是 getService()
。
您甚至可以考虑定期将 SyncAdapter/Job Scheduler 运行
执行相同的业务逻辑。
并设置一个新的定期同步,您可以在应用程序启动本身上首次使用。
我的问题的答案简单明了:
不使用服务来显示通知(如 Google 在其 IO Schedule 应用程序中所做的那样!),而是使用 BroadcastReceiver!
我不知道为什么 Google 确实使用了 IntentService,但现在在 Android 哦,由于后台执行限制,这根本不再工作了。
BroadcastReceiver 显然仍然可以 运行 片刻并显示通知。
如果有人能告诉我为什么 Google 首先使用 IntentService,我会加分……这让我花了很长时间才弄清楚,因为我认为 Google 知道他们在做什么。 ..:(
我自己的应用程序使用与 2016 年 Google I/O 应用程序完全相同的技术。see source
我需要在非常具体的时间点提醒用户 - 使用通知。
为此,我使用 AlarmManager
在正确的时间点唤醒设备:
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);
}
pendingIntent
是这样创建的:
final Intent intent = new Intent(MyAlarmService.ACTION_NOTIFY_RIDE, null, this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
现在,我的 MyAlarmService
class 是一个简单的 IntentService
处理唤醒,目的只是为了为用户创建通知。
我在日志中得到的信息如下:
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) }
现在,Google 自己的实现显然已损坏 - 尽管我不想做任何繁重的后台工作,但我不能再使用这种技术了。但是我应该如何在非常特定的时间点唤醒用户呢? (把我的 App 想象成一个闹钟)
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)
首先,您的代码不准确。如果设备处于打瞌睡模式,我预计最多 +/- 10 分钟。如果您想要准确的时间,并且您的应用确实是一个闹钟,请使用 setAlarmClock()
.
对于您现有的代码,在 API 级别 26+ 上 use getForegroundService()
而不是 getService()
。
您甚至可以考虑定期将 SyncAdapter/Job Scheduler 运行 执行相同的业务逻辑。 并设置一个新的定期同步,您可以在应用程序启动本身上首次使用。
我的问题的答案简单明了:
不使用服务来显示通知(如 Google 在其 IO Schedule 应用程序中所做的那样!),而是使用 BroadcastReceiver!
我不知道为什么 Google 确实使用了 IntentService,但现在在 Android 哦,由于后台执行限制,这根本不再工作了。
BroadcastReceiver 显然仍然可以 运行 片刻并显示通知。
如果有人能告诉我为什么 Google 首先使用 IntentService,我会加分……这让我花了很长时间才弄清楚,因为我认为 Google 知道他们在做什么。 ..:(