feat(reminders): schedule and fire reminders in-house (#75)
Delivery no longer waits to be told. The scan reads `Instances` and `Reminders`, plans every reminder, posts what has come due and arms one exact alarm for the next — replacing both halves of what the provider used to do for us. Reacting to `EVENT_REMINDER` could not be made reliable, only more hopeful. An app that reacts cannot distinguish "nothing was due" from "the broadcast never came", and AOSP's own unbundled calendar carries three workarounds for OEM providers that retarget it or write the alert row late. Etar's fallback was not the answer either: it replaces the alarm but still reads `CalendarAlerts` for what to show, and it disables itself the moment one real broadcast arrives — useless against a broadcast that arrives with no row behind it. Keeping the old receiver alongside was rejected for the same reason it looks attractive: on a healthy device both paths fire, and there is no honest way to suppress one without the latch we just ruled out. So the provider path goes — `EventReminderReceiver`, `ReminderAlertStore`, `ReminderRecovery` and the `CalendarAlerts` writes with it. Reminder delivery no longer needs WRITE_CALENDAR. One alarm exists at a time, re-planned on every firing, so an edit needs no alarm bookkeeping to stay in sync. Every trigger runs the same idempotent scan: the alarm, boot and package-replace (both wipe pending alarms), clock and timezone changes, a provider change while the app is up, launch, and a daily worker for a device that drops the alarm with nothing to announce it. RECEIVE_BOOT_COMPLETED is new and load-bearing — without it reminders stop dead after a restart. `ReminderAlert.alertId` becomes `key`, derived from the reminder rather than a row id that no longer exists, and the notification tag and PendingIntent request codes ride on it, so a re-posted reminder still replaces itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
19
CHANGELOG.md
19
CHANGELOG.md
@@ -40,6 +40,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Search results now show an all-day event's real date. West of UTC — anywhere in
|
||||
the Americas, say — a search hit was dated one day early, disagreeing with the
|
||||
day the month, week and agenda views file the same event under ([#82]).
|
||||
- Reminders no longer depend on Android telling Calendula when they are due.
|
||||
Calendula now works out each reminder's time itself and sets its own alarm for
|
||||
it. On some phones — Samsung's among them — the system's calendar storage never
|
||||
sends the signal a calendar app is meant to wake up on, and no amount of
|
||||
battery or notification settings helps: the reminder is simply never announced.
|
||||
None of that is visible from inside an app that waits to be told, which is why
|
||||
it took a second pass to find ([#75]).
|
||||
|
||||
Reminders also survive things that used to lose them quietly. After a restart
|
||||
or an app update Calendula re-arms its alarms, and a reminder whose moment
|
||||
passed while the phone was off still arrives, as long as the event has not
|
||||
ended yet.
|
||||
|
||||
- All-day reminders now arrive at the time you chose in **Settings →
|
||||
Notifications**, on every occurrence. A yearly birthday could drift an hour
|
||||
either way depending on daylight saving, and all-day reminders on calendars
|
||||
from an account fired in the middle of the night instead of in the morning
|
||||
([#75]).
|
||||
|
||||
- Reminders now arrive for every calendar you have switched on. A calendar that
|
||||
was hidden at system level — switched off in another calendar app, or never
|
||||
switched on after being added — still showed its events and listed their
|
||||
|
||||
Reference in New Issue
Block a user