fix: update database schedule nextRunAt after scheduling alarm in rollover
- Add database schedule update after successfully scheduling alarm - Update existing schedule's nextRunAt or create new schedule entry - Extract cron expression and clockTime from trigger time - This ensures getNotificationStatus() returns correct nextNotificationTime after rollover Previously, scheduleExactNotification() scheduled the alarm correctly but didn't update the database schedule's nextRunAt. This caused getNotificationStatus() to return stale data, making the UI show the old notification time even though the alarm was correctly rescheduled for tomorrow. The fix: - After successfully scheduling the alarm, update or create the schedule in the database - Set nextRunAt to the triggerAtMillis value - Extract hour:minute from trigger time to populate cron and clockTime fields - Use runBlocking to call suspend function from non-suspend context - Log but don't fail if DB update fails (alarm is already scheduled) This matches the pattern used in ReactivationManager for boot/app launch recovery.
This commit is contained in:
@@ -396,6 +396,51 @@ class NotifyReceiver : BroadcastReceiver() {
|
|||||||
)
|
)
|
||||||
Log.i(TAG, "Inexact alarm scheduled (fallback): triggerAt=$triggerAtMillis, requestCode=$requestCode")
|
Log.i(TAG, "Inexact alarm scheduled (fallback): triggerAt=$triggerAtMillis, requestCode=$requestCode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update database schedule with new nextRunAt so getNotificationStatus() returns correct value
|
||||||
|
// This is critical for rollover scenarios where the UI needs to show the updated time
|
||||||
|
try {
|
||||||
|
runBlocking {
|
||||||
|
val db = DailyNotificationDatabase.getDatabase(context)
|
||||||
|
val existingSchedule = db.scheduleDao().getById(stableScheduleId)
|
||||||
|
|
||||||
|
// Calculate cron expression from trigger time (HH:mm format)
|
||||||
|
val calendar = java.util.Calendar.getInstance().apply {
|
||||||
|
timeInMillis = triggerAtMillis
|
||||||
|
}
|
||||||
|
val hour = calendar.get(java.util.Calendar.HOUR_OF_DAY)
|
||||||
|
val minute = calendar.get(java.util.Calendar.MINUTE)
|
||||||
|
val cronExpression = "${minute} ${hour} * * *"
|
||||||
|
val clockTime = String.format("%02d:%02d", hour, minute)
|
||||||
|
|
||||||
|
if (existingSchedule != null) {
|
||||||
|
// Update existing schedule with new nextRunAt
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
db.scheduleDao().updateRunTimes(stableScheduleId, existingSchedule.lastRunAt, triggerAtMillis)
|
||||||
|
Log.d(SCHEDULE_TAG, "Updated schedule in database: id=$stableScheduleId, nextRunAt=$triggerAtMillis")
|
||||||
|
} else {
|
||||||
|
// Create new schedule entry for rollover scenarios
|
||||||
|
// This ensures getNotificationStatus() can find the schedule
|
||||||
|
val newSchedule = DatabaseSchema.Schedule(
|
||||||
|
id = stableScheduleId,
|
||||||
|
kind = "notify",
|
||||||
|
cron = cronExpression,
|
||||||
|
clockTime = clockTime,
|
||||||
|
enabled = true,
|
||||||
|
lastRunAt = null,
|
||||||
|
nextRunAt = triggerAtMillis,
|
||||||
|
jitterMs = 0,
|
||||||
|
backoffPolicy = "exp",
|
||||||
|
stateJson = null
|
||||||
|
)
|
||||||
|
db.scheduleDao().upsert(newSchedule)
|
||||||
|
Log.d(SCHEDULE_TAG, "Created schedule in database: id=$stableScheduleId, nextRunAt=$triggerAtMillis")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Log but don't fail - alarm is already scheduled, DB update is best-effort
|
||||||
|
Log.w(SCHEDULE_TAG, "Failed to update schedule in database: $stableScheduleId (alarm still scheduled)", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user