Browse Source

fix(android): create NotificationContentEntity in FetchWorker for prefetch

Fix issue where prefetch worker saved content to ContentCache but didn't
create NotificationContentEntity, causing notification worker to skip
notifications with "content_not_found" error.

Changes:
- Extract notificationTime from input data in doWork()
- Create NotificationContentEntity with matching notification_id when
  notificationTime > 0 (prefetch operations)
- Add parsePayload() helper to extract title/body from JSON or plain text
- Save entity to Room database so notification worker can find it

The notification_id format matches NotifyReceiver.kt: "notify_${notificationTime}",
ensuring the notification worker can retrieve content when the alarm fires.

Fixes issue where alarms triggered correctly but notifications were skipped
because DailyNotificationWorker couldn't find content in storage.
master
Matthew Raymer 2 days ago
parent
commit
a5fdf8c5b9
  1. 61
      android/src/main/java/com/timesafari/dailynotification/FetchWorker.kt

61
android/src/main/java/com/timesafari/dailynotification/FetchWorker.kt

@ -10,6 +10,7 @@ import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.TimeUnit
import org.json.JSONObject
/**
* WorkManager implementation for content fetching
@ -177,9 +178,10 @@ class FetchWorker(
val timeout = inputData.getInt("timeout", 30000)
val retryAttempts = inputData.getInt("retryAttempts", 3)
val retryDelay = inputData.getInt("retryDelay", 1000)
val notificationTime = inputData.getLong("notificationTime", 0L)
try {
Log.i(TAG, "Starting content fetch from: $url")
Log.i(TAG, "Starting content fetch from: $url, notificationTime=$notificationTime")
val payload = fetchContent(url, timeout, retryAttempts, retryDelay)
val contentCache = ContentCache(
@ -194,6 +196,40 @@ class FetchWorker(
val db = DailyNotificationDatabase.getDatabase(applicationContext)
db.contentCacheDao().upsert(contentCache)
// If this is a prefetch for a specific notification, create NotificationContentEntity
// so the notification worker can find it when the alarm fires
if (notificationTime > 0) {
try {
val notificationId = "notify_$notificationTime"
val (title, body) = parsePayload(payload)
val entity = com.timesafari.dailynotification.entities.NotificationContentEntity(
notificationId,
"1.0.2", // Plugin version
null, // timesafariDid - can be set if available
"daily",
title,
body,
notificationTime,
java.time.ZoneId.systemDefault().id
)
entity.priority = 0 // default priority
entity.vibrationEnabled = true
entity.soundEnabled = true
entity.deliveryStatus = "pending"
entity.createdAt = System.currentTimeMillis()
entity.updatedAt = System.currentTimeMillis()
entity.ttlSeconds = contentCache.ttlSeconds.toLong()
// Save to Room database so notification worker can find it
db.notificationContentDao().insertNotification(entity)
Log.i(TAG, "Created NotificationContentEntity: id=$notificationId, scheduledTime=$notificationTime")
} catch (e: Exception) {
Log.e(TAG, "Failed to create NotificationContentEntity", e)
// Continue - at least ContentCache was saved
}
}
// Record success in history
db.historyDao().insert(
History(
@ -292,4 +328,27 @@ class FetchWorker(
private fun generateId(): String {
return "fetch_${System.currentTimeMillis()}_${(1000..9999).random()}"
}
/**
* Parse payload to extract title and body
* Handles both JSON and plain text payloads
*
* @param payload Raw payload bytes
* @return Pair of (title, body)
*/
private fun parsePayload(payload: ByteArray): Pair<String, String> {
return try {
val payloadString = String(payload, Charsets.UTF_8)
// Try to parse as JSON
val json = JSONObject(payloadString)
val title = json.optString("title", "Daily Notification")
val body = json.optString("body", json.optString("content", payloadString))
Pair(title, body)
} catch (e: Exception) {
// Not JSON, use as plain text
val text = String(payload, Charsets.UTF_8)
Pair("Daily Notification", text)
}
}
}

Loading…
Cancel
Save