Files
crowd-funder-for-time-pwa/doc/plugin-android-edit-reschedule-alarm-not-firing.md
Jose Olarte III 0e096b1a46 Fix: Android daily notification: single schedule on edit, no double-cancel
Resolves long-standing issue where the second scheduled time (after editing
the reminder) did not fire on Android.

- PushNotificationPermission: add open(..., options?: { skipSchedule }).
  When skipSchedule is true (edit flow), dialog only invokes callback with
  time/message; parent is sole scheduler so the plugin is not called twice.
- AccountViewView: pass { skipSchedule: true } when opening the dialog for
  edit; keep cancel (iOS only) + single scheduleDailyNotification in callback.
- NativeNotificationService: serialize scheduleDailyNotification so only one
  schedule runs at a time (scheduleLock + doScheduleDailyNotification).
- AccountViewView: guard edit-reminder callback with editReminderScheduleInProgress
  so one schedule per user action.
- Gate pre-cancel on Android in edit flow (CONSUMING_APP brief): skip
  cancelDailyNotification before schedule on Android; plugin cancels internally.
- Use single stable reminder id and always pass id on both platforms (plugin 1.1.2+).
- Add doc/plugin-android-edit-reschedule-alarm-not-firing.md for plugin repo
  (cancel-before-reschedule may cancel the PendingIntent used for setAlarmClock).
2026-02-16 21:25:07 +08:00

28 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Plugin: Android — Alarm set after edit doesnt fire (cancel-before-reschedule)
**Context:** Consuming app (TimeSafari) — user sets reminder at 6:57pm (fires), then edits to 7:00pm. Only one `scheduleDailyNotification` call is made (skipSchedule fix). Logs show "Scheduling OS alarm" and "Updated schedule in database" for 19:00, but the notification never fires at 7:00pm.
**Likely cause (plugin):** In `NotifyReceiver.kt`, before calling `setAlarmClock(pendingIntent)` the code:
1. Creates `pendingIntent` with `PendingIntent.getBroadcast(..., requestCode, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE)`.
2. Gets `existingPendingIntent` with `PendingIntent.getBroadcast(..., requestCode, intent, FLAG_NO_CREATE | FLAG_IMMUTABLE)` (same `requestCode`, same `intent`).
3. If not null: `alarmManager.cancel(existingPendingIntent)` and **`existingPendingIntent.cancel()`**.
4. Then calls `alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)`.
On Android, PendingIntent equality for caching is based on requestCode and Intent (action, component, etc.), not necessarily all extras. So `existingPendingIntent` is often the **same** (cached) PendingIntent as `pendingIntent`. Then we call **`existingPendingIntent.cancel()`**, which cancels that PendingIntent for future use. We then use the same (now cancelled) PendingIntent in **`setAlarmClock(..., pendingIntent)`**. On some devices/versions, setting an alarm with a cancelled PendingIntent can result in the alarm not firing.
**Suggested fix (plugin repo):**
- Remove the **`existingPendingIntent.cancel()`** call. Use only **`alarmManager.cancel(existingPendingIntent)`** to clear any existing alarm for this requestCode. That way the PendingIntent we pass to `setAlarmClock` is not cancelled; only the previous alarm is removed.
- Optionally: only run the “cancel existing” block when we know there was a previous schedule (e.g. from DB) for this scheduleId that hasnt fired yet, so we dont cancel when the previous alarm already fired (e.g. user edited after first fire).
**Verification:**
- In the consuming app: set reminder 23 min from now, let it fire, then edit to 23 min from then and save. Capture logcat through the second scheduled time.
- If the receiver never logs at the second time, the OS didnt deliver the alarm; fixing the cancel-before-reschedule logic as above should be tried first in the plugin.
**References:**
- CONSUMING_APP_ANDROID_NOTES.md (double schedule, alarm scheduled but not firing).
- NotifyReceiver.kt around “Cancelling existing alarm before rescheduling” and the following `setAlarmClock` use of `pendingIntent`.