fix(android): improve notification scheduling and UX
- Fix cron parsing to correctly calculate next run time based on hour/minute - Always schedule prefetch 5 minutes before notification (even without URL) - Make notifications dismissable with setAutoCancel(true) - Add click action to launch app when notification is tapped - Conditionally require network only when URL is provided for prefetch - Generate mock content when no URL is specified These changes ensure notifications fire at the correct time, are user-friendly (dismissable and clickable), and prefetch works reliably even without a content URL.
This commit is contained in:
@@ -570,24 +570,31 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
|
||||
val nextRunTime = calculateNextRunTime(cronExpression)
|
||||
|
||||
// Schedule AlarmManager notification
|
||||
NotifyReceiver.scheduleExactNotification(context, nextRunTime, config)
|
||||
// Schedule AlarmManager notification as static reminder
|
||||
// (doesn't require cached content)
|
||||
val scheduleId = "daily_${System.currentTimeMillis()}"
|
||||
NotifyReceiver.scheduleExactNotification(
|
||||
context,
|
||||
nextRunTime,
|
||||
config,
|
||||
isStaticReminder = true,
|
||||
reminderId = scheduleId
|
||||
)
|
||||
|
||||
// Schedule prefetch 5 minutes before notification (if URL provided)
|
||||
if (url != null) {
|
||||
val fetchTime = nextRunTime - (5 * 60 * 1000L) // 5 minutes before
|
||||
FetchWorker.scheduleDelayedFetch(
|
||||
context,
|
||||
fetchTime,
|
||||
nextRunTime,
|
||||
url
|
||||
)
|
||||
Log.i(TAG, "Prefetch scheduled: fetchTime=$fetchTime, notificationTime=$nextRunTime")
|
||||
}
|
||||
// Always schedule prefetch 5 minutes before notification
|
||||
// (URL is optional - generates mock content if not provided)
|
||||
val fetchTime = nextRunTime - (5 * 60 * 1000L) // 5 minutes before
|
||||
FetchWorker.scheduleDelayedFetch(
|
||||
context,
|
||||
fetchTime,
|
||||
nextRunTime,
|
||||
url // Can be null - FetchWorker will generate mock content
|
||||
)
|
||||
Log.i(TAG, "Prefetch scheduled: fetchTime=$fetchTime, notificationTime=$nextRunTime, url=${url ?: "none (will generate mock)"}")
|
||||
|
||||
// Store schedule in database
|
||||
val schedule = Schedule(
|
||||
id = "daily_${System.currentTimeMillis()}",
|
||||
id = scheduleId,
|
||||
kind = "notify",
|
||||
cron = cronExpression,
|
||||
clockTime = time,
|
||||
@@ -1563,9 +1570,48 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
}
|
||||
|
||||
private fun calculateNextRunTime(schedule: String): Long {
|
||||
// Simple implementation - for production, use proper cron parsing
|
||||
val now = System.currentTimeMillis()
|
||||
return now + (24 * 60 * 60 * 1000L) // Next day
|
||||
// Parse cron expression: "minute hour * * *" (daily schedule)
|
||||
// Example: "9 7 * * *" = 07:09 daily
|
||||
try {
|
||||
val parts = schedule.trim().split("\\s+".toRegex())
|
||||
if (parts.size < 2) {
|
||||
Log.w(TAG, "Invalid cron format: $schedule, defaulting to 24h from now")
|
||||
return System.currentTimeMillis() + (24 * 60 * 60 * 1000L)
|
||||
}
|
||||
|
||||
val minute = parts[0].toIntOrNull() ?: 0
|
||||
val hour = parts[1].toIntOrNull() ?: 9
|
||||
|
||||
if (minute < 0 || minute > 59 || hour < 0 || hour > 23) {
|
||||
Log.w(TAG, "Invalid time values in cron: $schedule, defaulting to 24h from now")
|
||||
return System.currentTimeMillis() + (24 * 60 * 60 * 1000L)
|
||||
}
|
||||
|
||||
// Calculate next occurrence of this time
|
||||
val calendar = java.util.Calendar.getInstance()
|
||||
val now = calendar.timeInMillis
|
||||
|
||||
// Set to today at the specified time
|
||||
calendar.set(java.util.Calendar.HOUR_OF_DAY, hour)
|
||||
calendar.set(java.util.Calendar.MINUTE, minute)
|
||||
calendar.set(java.util.Calendar.SECOND, 0)
|
||||
calendar.set(java.util.Calendar.MILLISECOND, 0)
|
||||
|
||||
var nextRun = calendar.timeInMillis
|
||||
|
||||
// If the time has already passed today, schedule for tomorrow
|
||||
if (nextRun <= now) {
|
||||
calendar.add(java.util.Calendar.DAY_OF_YEAR, 1)
|
||||
nextRun = calendar.timeInMillis
|
||||
}
|
||||
|
||||
Log.d(TAG, "Calculated next run time: cron=$schedule, nextRun=${java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss", java.util.Locale.US).format(java.util.Date(nextRun))}")
|
||||
return nextRun
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error calculating next run time for schedule: $schedule", e)
|
||||
// Fallback: 24 hours from now
|
||||
return System.currentTimeMillis() + (24 * 60 * 60 * 1000L)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user