Android 三星上的警报 setExactAndAllowWhileIdle 意外行为
Android Alarm setExactAndAllowWhileIdle unexpected behavior on Samsung
我的 android 应用是 运行 重复闹钟,在 Marshmallow 上使用 setExactAndAllowWhileIdle。警报每 10 秒发生一次,并通过使用权限 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 避免打瞌睡模式(设备已同意忽略此应用的电池优化)
public void startAlarm(Intent alarmIntent, int delayMs, int alarmId) {
PendingIntent recurringAlarm = PendingIntent.getBroadcast(context.getApplicationContext(), alarmId,
alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
alarms.cancel(recurringAlarm);
if (Build.VERSION.SDK_INT >= 23) {
alarms.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
} else if (Build.VERSION.SDK_INT >= 19) {
alarms.setExact(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
} else {
alarms.set(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
}
}
此警报启动服务。然后,该服务使用相同的方法(上文)创建另一个持续 10 秒的警报。我推测这个警报会每 10 秒发生一次,因为打瞌睡模式被忽略了,但在极少数情况下警报会被推迟更长的时间:
- 53 分 6 秒
- 18 分 40 秒
- 54分37分19秒
- 1 天 48 分 30 秒
是什么导致了这种奇怪的行为?这似乎只发生在三星设备上。
您不能在较新版本的 Android 上设置这么短的警报,您应该在日志中看到:
Suspiciously short interval 10000 millis; expanding to 60 seconds
如果您需要短于 60 秒的警报,则需要不同于 AlarmManager 的机制,例如 Handler 或 HandlerThread。
官方文档指出
To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched); when in low-power idle modes this duration may be significantly longer, such as 15 minutes.
我怀疑三星做了修改,使这个持续时间甚至超过了 15 分钟。他们以进行深远的修改而闻名,这往往会导致意外行为。
我的 android 应用是 运行 重复闹钟,在 Marshmallow 上使用 setExactAndAllowWhileIdle。警报每 10 秒发生一次,并通过使用权限 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 避免打瞌睡模式(设备已同意忽略此应用的电池优化)
public void startAlarm(Intent alarmIntent, int delayMs, int alarmId) {
PendingIntent recurringAlarm = PendingIntent.getBroadcast(context.getApplicationContext(), alarmId,
alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
alarms.cancel(recurringAlarm);
if (Build.VERSION.SDK_INT >= 23) {
alarms.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
} else if (Build.VERSION.SDK_INT >= 19) {
alarms.setExact(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
} else {
alarms.set(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis() + delayMs, recurringAlarm);
}
}
此警报启动服务。然后,该服务使用相同的方法(上文)创建另一个持续 10 秒的警报。我推测这个警报会每 10 秒发生一次,因为打瞌睡模式被忽略了,但在极少数情况下警报会被推迟更长的时间:
- 53 分 6 秒
- 18 分 40 秒
- 54分37分19秒
- 1 天 48 分 30 秒
是什么导致了这种奇怪的行为?这似乎只发生在三星设备上。
您不能在较新版本的 Android 上设置这么短的警报,您应该在日志中看到:
Suspiciously short interval 10000 millis; expanding to 60 seconds
如果您需要短于 60 秒的警报,则需要不同于 AlarmManager 的机制,例如 Handler 或 HandlerThread。
官方文档指出
To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched); when in low-power idle modes this duration may be significantly longer, such as 15 minutes.
我怀疑三星做了修改,使这个持续时间甚至超过了 15 分钟。他们以进行深远的修改而闻名,这往往会导致意外行为。