AlarmManager 设置为 PM 在 AM 时间触发

AlarmManager set as PM firing at AM time

问题

我正在使用 Android 的 AlarmManager 根据用户在设置屏幕上设置的时间定期在我的应用程序上触发通知。我已经按照 the documentation 来实现它。就像下面的代码片段一样完成:

fun setDailyAlarm(time: Calendar, id: Int) {
    val cal = Calendar.getInstance().apply {
        timeInMillis = System.currentTimeMillis()
        set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY))
        set(Calendar.MINUTE, time.get(Calendar.MINUTE))
    }
    val pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT)

    alarmManager.setRepeating(
        AlarmManager.RTC_WAKEUP,
        cal.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        pi
    )
}

我也在使用 Material Dialogs library 调用时间对话框,如下所示:

MaterialDialog(this).show {
    // time here is a Calendar instance
    timePicker { _, time ->
        setDailyAlarm(time, ALARM_ID)
    }
}

屏幕如下例所示:

警报本身正在触发,但发生了一个奇怪的错误。

假设现在是晚上 9 点,我将闹钟设置为上午 10 点。我相信预期的行为应该是第二天上午 10 点触发警报,但是一旦时钟到达晚上 10 点 有时 我会收到 "false positive"。 (有时我的意思是这种行为甚至不一致。我设法复制了几次,我的客户也抱怨过)。

注意:应用程序的最低 API 级别为 21。

到目前为止我尝试了什么

起初,我认为日历对象可能得到了错误的 AM/PM 标志,或者 Calendar.HOUR_OF_DAY 属性 可能是错误的,但是当我检查那些调试器中的值一切似乎都很好。所以现在我对问题可能是什么一无所知。

我在这里遗漏了什么吗?

我找到了解决这个问题的方法。

在做了一些测试后,我发现只有当我将时间设置为当前时间之前的某个时间时才会出现问题。然后我想到 AlarmManager 可能会自动触发 "old alarms",所以这可能就是我得到误报的原因。

然后我将 setDailyAlarm() 函数更改为以下代码段:

fun setDailyAlarm(time: Calendar, id: Int) {
    val now = Calendar.getInstance()

    val cal = Calendar.getInstance().apply {
        timeInMillis = System.currentTimeMillis()
        set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY))
        set(Calendar.MINUTE, time.get(Calendar.MINUTE))
    }

    if (time.get(Calendar.HOUR_OF_DAY) <= now.get(Calendar.HOUR_OF_DAY)) {
        cal.add(Calendar.DATE, 1)
    }

    val pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT)

    alarmManager.setRepeating(
        AlarmManager.RTC_WAKEUP,
        cal.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        pi
    )
}

TL;DR: 我正在检查所选时间是否早于当前时间,如果是这样,我会在 Calendar 实例在创建 PendingIntent 之前。它似乎已经解决了这个问题,因为警报不再在错误的时间触发。