diff --git a/android/src/main/java/com/timesafari/dailynotification/NotifyReceiver.kt b/android/src/main/java/com/timesafari/dailynotification/NotifyReceiver.kt index 5d23eb2..e291701 100644 --- a/android/src/main/java/com/timesafari/dailynotification/NotifyReceiver.kt +++ b/android/src/main/java/com/timesafari/dailynotification/NotifyReceiver.kt @@ -420,9 +420,11 @@ class NotifyReceiver : BroadcastReceiver() { // First, try to find schedule by the provided stableScheduleId var scheduleToUpdate = db.scheduleDao().getById(stableScheduleId) - // If not found by ID, find the existing enabled notify schedule (for rollover scenarios) - // getNotificationStatus() finds schedules with kind="notify" && enabled=true - if (scheduleToUpdate == null) { + // If not found by ID, only use "first enabled notify" fallback when this is NOT + // a rollover id (daily_rollover_*). Rollover work may use a different notification_id + // (e.g. from recovery); updating the app's schedule row here would overwrite + // nextRunAt with the rollover time and can leave the app's alarm in a bad state. + if (scheduleToUpdate == null && !stableScheduleId.startsWith("daily_rollover_")) { val allSchedules = db.scheduleDao().getAll() scheduleToUpdate = allSchedules.firstOrNull { it.kind == "notify" && it.enabled } } diff --git a/docs/CONSUMING_APP_ANDROID_NOTES.md b/docs/CONSUMING_APP_ANDROID_NOTES.md new file mode 100644 index 0000000..bb3ec68 --- /dev/null +++ b/docs/CONSUMING_APP_ANDROID_NOTES.md @@ -0,0 +1,37 @@ +# Consuming App Notes — Android Daily Notifications + +Brief notes for apps that integrate the daily notification plugin on Android. + +--- + +## Double schedule (rapid successive calls) + +If your app calls `scheduleDailyNotification` twice in quick succession (e.g. within a few hundred ms) for the same reminder, the second call cancels the alarm just set and reschedules. On some devices or OEMs this can contribute to the alarm not firing. + +**Recommendation:** Debounce or guard in the edit-reminder success path so you only call `scheduleDailyNotification` once per user action (e.g. wait for the first call to resolve before allowing another, or coalesce rapid calls). + +--- + +## Alarm scheduled but not firing (e.g. 6:04) + +When logs show "Scheduling OS alarm" and "Updated schedule in database" but the notification never appears: + +1. **Confirm the broadcast is delivered** + Run logcat including the receiver: + ```bash + adb logcat -v time -s DNP-SCHEDULE:V DailyNotificationWorker:V DailyNotificationReceiver:V + ``` + At the scheduled time, check whether `DailyNotificationReceiver` logs anything. If the Receiver runs, the issue is downstream (WorkManager / display). If it does not run, the OS did not deliver the alarm (Doze, OEM, or alarm replacement). + +2. **Avoid double schedule** + Ensure the app is not calling `scheduleDailyNotification` twice in quick succession for the same reminder (see above). + +3. **Plugin fix (v1.1.5+)** + The plugin no longer overwrites the app’s schedule row when handling rollover work that uses a `daily_rollover_*` id, so the app’s `nextRunAt` stays correct after a notification fires. + +--- + +## References + +- [ACTION_PLAN_INTEGRATION_FIXES.md](./ACTION_PLAN_INTEGRATION_FIXES.md) — plugin and app integration checklist +- [CONSUMING_APP_OPTIONAL_ANDROID_ID_CLEANUP.md](./CONSUMING_APP_OPTIONAL_ANDROID_ID_CLEANUP.md) — optional cleanup of stale schedule rows