【问题标题】:Android Alarm setExactAndAllowWhileIdle unexpected behavior on Samsung三星上的 Android 警报 setExactAndAllowWhileIdle 意外行为
【发布时间】:2016-03-17 15:16: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 秒

什么可能导致这种奇怪的行为?这似乎只发生在三星设备上。

【问题讨论】:

  • 您正在查看手机的 SDK。但根据文档,真正的决定因素是您应用的目标 SDK。因此,如果您的目标 SDK 是 23,这将无法在 23 之前的手机上正常工作。
  • 设备和目标SDK都是23

标签: android service android-alarms


【解决方案1】:

官方文档说明

为了减少滥用,对特定应用程序的警报发出频率有限制。在正常的系统操作下,它不会超过大约每分钟发送这些警报(此时每个此类挂起的警报都会被发送);在低功耗空闲模式下,此持续时间可能会更长,例如 15 分钟。

我怀疑三星进行了修改以使此持续时间甚至超过 15 分钟。它们以进行深度修改而闻名,这往往会导致意外行为。

【讨论】:

  • 警报在很长一段时间内每 10 秒工作一次。有时甚至几天。三星实际上停止警报并破坏服务的情况似乎很少见。这可能在几分钟、几小时或几天后发生。我还没有找到任何类型的模式。我将尝试设计一个解决方法,可能通过另一个警报来检查,然后在必要时重新启动服务。我并不乐观。
【解决方案2】:

您不能在较新版本的 Android 上设置这么短的警报,您应该在日志中看到这一点:

Suspiciously short interval 10000 millis; expanding to 60 seconds

如果您需要短于 60 秒的警报,则需要与 AlarmManager 不同的机制,例如 Handler 或 HandlerThread。

【讨论】:

  • 我认为新的 60 秒规则适用于 setRepeating()?使用 setExactAndAllowWhileIdle 仍然适用于短于 60 秒的警报。并且可以通过在触发初始警报时重新安排新警报来重复它们。我的方法适用于除三星以外的所有设备(到目前为止)
  • 三星也做出了自己的改变,看起来他们至少有 5 分钟的警报时间。尝试不同的设备;如果它有效,那么您将需要查看一个不同的实现来覆盖所有设备。
  • 我知道三星在 5.1 中有自己的打盹模式,但在 6.0 中被 Android 版本取代。 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 也有效,警报每 10 秒触发一次。很少有警报会以更大的延迟触发 - 这就是问题所在。而且我无法确定原因,因此无法解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 2017-12-18
相关资源
最近更新 更多