AlarmManager установлен как PM, стреляющий в время AM - PullRequest
3 голосов
/ 01 апреля 2020

Проблема

Я использую Android AlarmManager, чтобы периодически запускать уведомления в моем приложении, основываясь на времени, установленном пользователем на экране настроек. Я следовал документации , чтобы реализовать это. Это делается так, как показано ниже:

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
    )
}

Я также использую библиотеку Диалоги материалов , чтобы вызвать диалог времени, как показано ниже:

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

Экран похож на приведенный ниже пример:

Settings Screen

Сам сигнал тревоги срабатывает, но происходит странная ошибка.

Скажите, что сейчас 9 часов вечера, и я установил будильник на 10 часов утра. Я полагаю, что ожидаемое поведение должно состоять в том, чтобы включить будильник на следующий день в 10:00, но как только часы достигают 22:00 иногда , я получаю "ложный положительный результат". (Под иногда я имею в виду, что это поведение даже непоследовательно. Мне удалось повторить его несколько раз, и мои клиенты также жаловались на это).

Примечание: Минимальный уровень API приложения - 21.

То, что я пробовал до сих пор

Сначала я подумал, что объект календаря мог получить неправильный флаг AM / PM или Calendar.HOUR_OF_DAY свойство могло быть неправильным, но когда я проверил эти значения в отладчике, все было в порядке. Так что теперь я понятия не имею, в чем может быть проблема.

Есть ли что-то, чего мне здесь не хватает?

1 Ответ

2 голосов
/ 03 апреля 2020

Я нашел решение этой проблемы.

После выполнения некоторых тестов я заметил, что проблема возникла только тогда, когда я установил время на что-то, предшествующее текущему часу. Затем мне пришло в голову, что, возможно, AlarmManager может автоматически запускать «старые аварийные сигналы», поэтому, возможно, именно поэтому я и получил ложное срабатывание.

Затем я изменил свою функцию 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. Кажется, это решило проблему, так как тревога больше не срабатывает в неподходящее время.

...