Closed strooooke closed 5 years ago
Some thinking out loud about the alarm situation:
Current architecture:
ScheduleEntry.COL_SHOW_NOTIFICATION
has the following usages:
refreshNotificationDisplay
- which applies the state found in the DB to the notifications shown. Note that notification display is build to deal with all API levels, including the ones that do not allow for querying currently displayed notifications. So this column gets also used to track whether a notification has been canceled by the user (and thus should not reappear after boot, or get amalgamated with the next reminder to a multi-event notification). On API levels below 23, where NotificationManager.getActiveNotifications
does not exist, we have to do our own bookkeeping to get this behavior. On those above, we might get around to doing this differently, maybe by paying the price of repeat notifications upon boot (that have been dismissed already before shutdown).NO
:
nextAlarmMillis
forward by the snooze amount - triggering cancellation of the notification (by refreshNotificationDisplay
)cancelIntent
on the notification; that one only gets send on manual dismiss).setNextAlarm
, i.e., recalculation.YES
: in processOldEvents
, triggered by the alarm broadcast. Any schedules where nextAlarmMillis
is now in the past get showNotification
flipped to YES
. This is followed by display refresh, and registering the next alarm with the AlarmManager
.Desired state:
AlarmReceiver
must use pre-chewed data from its intent, and possibly NotificationManager.getActiveNotifications
, to update the notification display inline, on the main thread, without any deferred work.PendingIntent
and next alarm time registered with the AlarmManager
. Disambiguate the PendingIntents
via their data (schedule-entry-content-uri).AlarmManager
state from the DB state, and current time. This might be a source of delays or missing alarms, which is sadly unavoidable.didIt
action: ofc the actual session insertion and sync must be triggered, but also notification display must update (also doable by autocancel), but notification display bookkeeping must be written.snooze
action: notification display must update (also doable by autocancel), notification display bookkeeping must be written, and the snooze info must be (a) persisted, so it can be used again after a reboot (b) used during the also-necessary next-alarm enqueuing.Note: when enqueuing work from any BroadcastReceiver
, use goAsync
, and register completion upon completion of the enqueue operation.
We could:
ON_DISPLAY|ACKNOWLEDGED|SNOOZED_UNTIL(millis)
(defaulting to ACKNOWLEDGED
if no previous execution exists, because schedule entry was newly created). Means we'd have to pre-emptively set it to ON_DISPLAY
when enqueuing the alarm - does that work?
(ACKNOWLEDGED
means either "didIt" or "dimissed").Alright, on boot we look at all the schedule entries. For each one, we need to decide whether:
ON_DISPLAY
.SNOOZED(until)
.But, problem is: say we show the notification, deferred work enqueues the next alarm (for "in a week") and switches state to ON_DISPLAY
. Notification gets cancelled. State switches to ACKNOWLEDGED
. Device shuts down. Device boots up again, 1.5 weeks later. Expected state: notification for the new event is shown (from last week, not the one two weeks ago). But isn't.
So, that's not sufficient, we do need to keep info about the next planned alarm time too, so that we can do catch-up on boot.
How about the current schema?
Note: need to reschedule notifications on ACTION_LOCALE_CHANGED (for properly localized texts). Edit: no, we don't! (Well, we could refresh the already-displaying notifications, but that's more of a luxury problem). Can do all localization in the AlarmReceiver, that's fine on the main thread.
Concerns: