Android AlarmManager setExact() 不准确

新手上路,请多包涵

我需要每 10 分钟计划一次计划任务。

在 Lollipop 和更高版本中 setRepeating() 是不准确的,我使用 setExact() 并且(在触发警报时)我在 10 分钟内设置了新的精确警报。

 private void setAlarm(long triggerTime, PendingIntent pendingIntent) {
        int ALARM_TYPE = AlarmManager.ELAPSED_REALTIME_WAKEUP;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(ALARM_TYPE, triggerTime, pendingIntent);
        } else {
            alarmManager.set(ALARM_TYPE, triggerTime, pendingIntent);
        }
    }

triggerTime 计算 SystemClock.elapsedRealtime() + 600_000;

当警报响起时,我首先计划新的,然后才运行我的预定任务。

 setAlarm();
mySheduledTask;

我的清单中确实有 WAKE_LOCK 权限。

当我在 Android 4 上测试它时 - 它运行完美(偏差可能是 12-15 毫秒)。

但是当我在小米红米 Note 3 Pro (5.1.1) 上运行应用程序时 - 偏差最多可达 15 秒!

例如,我在我的日志文件中看到:第一次运行是在 1467119934477(RTC 时间),第二次运行是在 1467120541683。差异是 607_206 毫秒,而不是计划的 600_000

我错过了什么? 什么是模拟系统警报行为的方法(这是可以描述我的策略的最接近的用例)?

附言。 我将 IntentService 用于 PendingIntent = PendingIntent.getService(context, 0, myIntent, 0);

原文由 Goltsev Eugene 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 816
1 个回答

操作系统会根据您指定的时间来选择警报的工作方式。因此,当手机进入“半睡眠”模式时,它不必在您希望的时间使用资源。基本上,它等待操作系统为它打开的“窗口”,然后您要运行的警报才会运行,这就是您遇到时间间隔的原因。

这是在 Marshmallow OS 上引入的,并将在 Nougat OS 上继续,作为谷歌试图改进设备电池的一部分。

事情是这样的,你有两个选择:

  1. 接受时间延迟(但可以考虑使用 JobScheduler 更推荐,可以节省电池电量)。
  2. 使用 setExactAndAllowWhileIdle 这可能会导致你的电池问题(小心使用,太多的警报会对你的电池不利)。此方法不重复,因此您必须声明要在 pendingIntent 打开的服务上运行的下一个作业。

如果您选择选项 2,那么这里是开始:

 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
int ALARM_TYPE = AlarmManager.RTC_WAKEUP;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    am.setExactAndAllowWhileIdle(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
    am.setExact(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else
    am.set(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);

原文由 Dus 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题