admin管理员组文章数量:1023744
A custom push notification is send from backend. The payload is bellow
Payload
{
"data": {
"notification": {
"title": "কথা চলুক সেরা অফারে!",
"body": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"imageUrl": ".png"
},
"data": {
"title": "কথা চলুক সেরা অফারে!",
"description": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"sentAt": "1731929876", //
"expiredAt": "1731982676",
"buttonText": "Open Recharge",
"type": "in_app",
"url": "myapp-ppd://dashboard",
"image": ".gif"
},
"token": "XXX"
},
"operator": "moon"
}
What I have to do is, is to save the Notification data to my Room Data base. Here is the implementation, I tried
SaveNotificationWorker.kt
@HiltWorker
class SaveNotificationWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override suspend fun doWork(): Result {
val jsonString = inputData.getString("data")
if (jsonString.isNullOrEmpty()) return Result.failure()
return try {
val notificationEntity = Gson().fromJson(jsonString, NotificationEntity::class.java)
notificationRepository.addNotification(notificationEntity)
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
RasaFcmService.kt
@AndroidEntryPoint
class RasaFcmService : FirebaseMessagingService() {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d("fcm", token)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val notificationEntity = parseData(remoteMessage.data)
notificationEntity?.let {
val jsonString = Gson().toJson(notificationEntity)
val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>()
.setInputData(workDataOf("data" to jsonString))
.build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
showNotification(it.id, it.title, it.description)
}
}
private fun parseData(data: Map<String, String>): NotificationEntity? {
return try {
val notificationJson = JSONObject(data)
val title = notificationJson.optString("title")
val description = notificationJson.optString("description")
val sentAt = notificationJson.optLong("sentAt", System.currentTimeMillis() / 1000)
val linkType = if (notificationJson.has("type")) notificationJson.optString("type") else null
val link = if (notificationJson.has("url")) notificationJson.optString("url") else null
val image = if (notificationJson.has("image")) notificationJson.optString("image") else null
val expiredAt = if (notificationJson.has("expiredAt")) notificationJson.optString("expiredAt") else null
val buttonText = notificationJson.optString("buttonText")
NotificationEntity(
title = title,
description = description,
date = sentAt,
isRead = 0,
expiredAt = expiredAt?.toLong(),
buttonText = buttonText,
linkType = linkType,
link = link,
image = image
)
} catch (e: Exception) {
null
}
}
private fun showNotification(id: Int, title: String, description: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "YOUR_CHANNEL_ID"
val channelName = "Your Channel Name"
val intent = Intent(this, SplashActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("notification_id", id)
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, channelId)
.setContentTitle(title)
.setContentText(description)
.setSmallIcon(R.drawable.ic_brand_logo)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(id, notification)
}
}
In this implementation, when app is in foreground, data is saved perfectly in Room. But when app is in background or not in active mood, data is not saved although I want to save it in Room even if app is in background. How to solve this issue?
A custom push notification is send from backend. The payload is bellow
Payload
{
"data": {
"notification": {
"title": "কথা চলুক সেরা অফারে!",
"body": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"imageUrl": "https://myapp-dev-static.robi.bd/images/payment/bkash.png"
},
"data": {
"title": "কথা চলুক সেরা অফারে!",
"description": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"sentAt": "1731929876", //
"expiredAt": "1731982676",
"buttonText": "Open Recharge",
"type": "in_app",
"url": "myapp-ppd://dashboard",
"image": "https://media.giphy/media/Ju7l5y9osyymQ/giphy.gif"
},
"token": "XXX"
},
"operator": "moon"
}
What I have to do is, is to save the Notification data to my Room Data base. Here is the implementation, I tried
SaveNotificationWorker.kt
@HiltWorker
class SaveNotificationWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override suspend fun doWork(): Result {
val jsonString = inputData.getString("data")
if (jsonString.isNullOrEmpty()) return Result.failure()
return try {
val notificationEntity = Gson().fromJson(jsonString, NotificationEntity::class.java)
notificationRepository.addNotification(notificationEntity)
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
RasaFcmService.kt
@AndroidEntryPoint
class RasaFcmService : FirebaseMessagingService() {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d("fcm", token)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val notificationEntity = parseData(remoteMessage.data)
notificationEntity?.let {
val jsonString = Gson().toJson(notificationEntity)
val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>()
.setInputData(workDataOf("data" to jsonString))
.build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
showNotification(it.id, it.title, it.description)
}
}
private fun parseData(data: Map<String, String>): NotificationEntity? {
return try {
val notificationJson = JSONObject(data)
val title = notificationJson.optString("title")
val description = notificationJson.optString("description")
val sentAt = notificationJson.optLong("sentAt", System.currentTimeMillis() / 1000)
val linkType = if (notificationJson.has("type")) notificationJson.optString("type") else null
val link = if (notificationJson.has("url")) notificationJson.optString("url") else null
val image = if (notificationJson.has("image")) notificationJson.optString("image") else null
val expiredAt = if (notificationJson.has("expiredAt")) notificationJson.optString("expiredAt") else null
val buttonText = notificationJson.optString("buttonText")
NotificationEntity(
title = title,
description = description,
date = sentAt,
isRead = 0,
expiredAt = expiredAt?.toLong(),
buttonText = buttonText,
linkType = linkType,
link = link,
image = image
)
} catch (e: Exception) {
null
}
}
private fun showNotification(id: Int, title: String, description: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "YOUR_CHANNEL_ID"
val channelName = "Your Channel Name"
val intent = Intent(this, SplashActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("notification_id", id)
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, channelId)
.setContentTitle(title)
.setContentText(description)
.setSmallIcon(R.drawable.ic_brand_logo)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(id, notification)
}
}
In this implementation, when app is in foreground, data is saved perfectly in Room. But when app is in background or not in active mood, data is not saved although I want to save it in Room even if app is in background. How to solve this issue?
Share Improve this question asked Nov 19, 2024 at 6:33 Aminul Haque AomeAminul Haque Aome 2,62926 silver badges40 bronze badges2 Answers
Reset to default 2Why Push Notification Data Isn’t Saved to Room When the App is in Background
When working with Firebase Cloud Messaging (FCM), the behavior of notifications depends on how the payload is structured. FCM allows two types of payloads: notification payloads and data payloads. Understanding their behavior is crucial to ensure that your app handles notifications and saves data correctly.
- Notification Payload
When the payload contains a notification object, FCM automatically handles the notification display. This means:
• The notification is shown in the system tray by FCM without involving your app.
• The FirebaseMessagingService’s onMessageReceived() method is not triggered if the app is in the background or terminated.
• You cannot directly process the notification payload to save it to the Room database in these cases.
- Data Payload
When the payload contains only a data object:
• The onMessageReceived() method is triggered in all app states (foreground, background, or terminated).
• You have full control to process the data and handle tasks like saving it to Room, displaying a custom notification, etc.
enter code here
- Mixed Payload (Both notification and data)
If the payload includes both notification and data objects:
• FCM prioritizes the notification object for background and terminated states, displaying it automatically in the system tray.
• The data object is ignored, and onMessageReceived() is not called.
Solution
To handle and save push notification data to Room effectively:
• Use only the data payload in your backend’s FCM request. Avoid including the notification object.
• Construct your custom notification in the onMessageReceived() method, allowing you to display the notification and save its content to Room simultaneously.
Example Payloads
Notification Payload (Not Recommended):
{
"notification": {
"title": "New Offer!",
"body": "Click to check out the latest deals."
},
"data": {
"type": "offer",
"url": "https://example/deals"
}
}
• Background Behavior: Auto-shows notification, onMessageReceived() not triggered.
Data Payload (Recommended):
{
"data": {
"title": "New Offer!",
"body": "Click to check out the latest deals.",
"type": "offer",
"url": "https://example/deals"
}
}
• Background Behavior: onMessageReceived() is triggered, giving you full control.
Backend Implementation
Ensure your backend sends only the data object to allow consistent handling of notifications across all app states. This provides flexibility to customize notifications and handle tasks like saving data to Room.
For background tasks use the old way and don't use HILT. Try this in onMessageReceived
//initialize database
//after using the below approach
CoroutineScope(Dispatchers.IO).launch {
//save to database code
}
A custom push notification is send from backend. The payload is bellow
Payload
{
"data": {
"notification": {
"title": "কথা চলুক সেরা অফারে!",
"body": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"imageUrl": ".png"
},
"data": {
"title": "কথা চলুক সেরা অফারে!",
"description": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"sentAt": "1731929876", //
"expiredAt": "1731982676",
"buttonText": "Open Recharge",
"type": "in_app",
"url": "myapp-ppd://dashboard",
"image": ".gif"
},
"token": "XXX"
},
"operator": "moon"
}
What I have to do is, is to save the Notification data to my Room Data base. Here is the implementation, I tried
SaveNotificationWorker.kt
@HiltWorker
class SaveNotificationWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override suspend fun doWork(): Result {
val jsonString = inputData.getString("data")
if (jsonString.isNullOrEmpty()) return Result.failure()
return try {
val notificationEntity = Gson().fromJson(jsonString, NotificationEntity::class.java)
notificationRepository.addNotification(notificationEntity)
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
RasaFcmService.kt
@AndroidEntryPoint
class RasaFcmService : FirebaseMessagingService() {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d("fcm", token)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val notificationEntity = parseData(remoteMessage.data)
notificationEntity?.let {
val jsonString = Gson().toJson(notificationEntity)
val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>()
.setInputData(workDataOf("data" to jsonString))
.build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
showNotification(it.id, it.title, it.description)
}
}
private fun parseData(data: Map<String, String>): NotificationEntity? {
return try {
val notificationJson = JSONObject(data)
val title = notificationJson.optString("title")
val description = notificationJson.optString("description")
val sentAt = notificationJson.optLong("sentAt", System.currentTimeMillis() / 1000)
val linkType = if (notificationJson.has("type")) notificationJson.optString("type") else null
val link = if (notificationJson.has("url")) notificationJson.optString("url") else null
val image = if (notificationJson.has("image")) notificationJson.optString("image") else null
val expiredAt = if (notificationJson.has("expiredAt")) notificationJson.optString("expiredAt") else null
val buttonText = notificationJson.optString("buttonText")
NotificationEntity(
title = title,
description = description,
date = sentAt,
isRead = 0,
expiredAt = expiredAt?.toLong(),
buttonText = buttonText,
linkType = linkType,
link = link,
image = image
)
} catch (e: Exception) {
null
}
}
private fun showNotification(id: Int, title: String, description: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "YOUR_CHANNEL_ID"
val channelName = "Your Channel Name"
val intent = Intent(this, SplashActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("notification_id", id)
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, channelId)
.setContentTitle(title)
.setContentText(description)
.setSmallIcon(R.drawable.ic_brand_logo)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(id, notification)
}
}
In this implementation, when app is in foreground, data is saved perfectly in Room. But when app is in background or not in active mood, data is not saved although I want to save it in Room even if app is in background. How to solve this issue?
A custom push notification is send from backend. The payload is bellow
Payload
{
"data": {
"notification": {
"title": "কথা চলুক সেরা অফারে!",
"body": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"imageUrl": "https://myapp-dev-static.robi.bd/images/payment/bkash.png"
},
"data": {
"title": "কথা চলুক সেরা অফারে!",
"description": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!",
"sentAt": "1731929876", //
"expiredAt": "1731982676",
"buttonText": "Open Recharge",
"type": "in_app",
"url": "myapp-ppd://dashboard",
"image": "https://media.giphy/media/Ju7l5y9osyymQ/giphy.gif"
},
"token": "XXX"
},
"operator": "moon"
}
What I have to do is, is to save the Notification data to my Room Data base. Here is the implementation, I tried
SaveNotificationWorker.kt
@HiltWorker
class SaveNotificationWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override suspend fun doWork(): Result {
val jsonString = inputData.getString("data")
if (jsonString.isNullOrEmpty()) return Result.failure()
return try {
val notificationEntity = Gson().fromJson(jsonString, NotificationEntity::class.java)
notificationRepository.addNotification(notificationEntity)
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
RasaFcmService.kt
@AndroidEntryPoint
class RasaFcmService : FirebaseMessagingService() {
@Inject
lateinit var notificationRepository: NotificationLocalRepository
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d("fcm", token)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val notificationEntity = parseData(remoteMessage.data)
notificationEntity?.let {
val jsonString = Gson().toJson(notificationEntity)
val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>()
.setInputData(workDataOf("data" to jsonString))
.build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
showNotification(it.id, it.title, it.description)
}
}
private fun parseData(data: Map<String, String>): NotificationEntity? {
return try {
val notificationJson = JSONObject(data)
val title = notificationJson.optString("title")
val description = notificationJson.optString("description")
val sentAt = notificationJson.optLong("sentAt", System.currentTimeMillis() / 1000)
val linkType = if (notificationJson.has("type")) notificationJson.optString("type") else null
val link = if (notificationJson.has("url")) notificationJson.optString("url") else null
val image = if (notificationJson.has("image")) notificationJson.optString("image") else null
val expiredAt = if (notificationJson.has("expiredAt")) notificationJson.optString("expiredAt") else null
val buttonText = notificationJson.optString("buttonText")
NotificationEntity(
title = title,
description = description,
date = sentAt,
isRead = 0,
expiredAt = expiredAt?.toLong(),
buttonText = buttonText,
linkType = linkType,
link = link,
image = image
)
} catch (e: Exception) {
null
}
}
private fun showNotification(id: Int, title: String, description: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "YOUR_CHANNEL_ID"
val channelName = "Your Channel Name"
val intent = Intent(this, SplashActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("notification_id", id)
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, channelId)
.setContentTitle(title)
.setContentText(description)
.setSmallIcon(R.drawable.ic_brand_logo)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(id, notification)
}
}
In this implementation, when app is in foreground, data is saved perfectly in Room. But when app is in background or not in active mood, data is not saved although I want to save it in Room even if app is in background. How to solve this issue?
Share Improve this question asked Nov 19, 2024 at 6:33 Aminul Haque AomeAminul Haque Aome 2,62926 silver badges40 bronze badges2 Answers
Reset to default 2Why Push Notification Data Isn’t Saved to Room When the App is in Background
When working with Firebase Cloud Messaging (FCM), the behavior of notifications depends on how the payload is structured. FCM allows two types of payloads: notification payloads and data payloads. Understanding their behavior is crucial to ensure that your app handles notifications and saves data correctly.
- Notification Payload
When the payload contains a notification object, FCM automatically handles the notification display. This means:
• The notification is shown in the system tray by FCM without involving your app.
• The FirebaseMessagingService’s onMessageReceived() method is not triggered if the app is in the background or terminated.
• You cannot directly process the notification payload to save it to the Room database in these cases.
- Data Payload
When the payload contains only a data object:
• The onMessageReceived() method is triggered in all app states (foreground, background, or terminated).
• You have full control to process the data and handle tasks like saving it to Room, displaying a custom notification, etc.
enter code here
- Mixed Payload (Both notification and data)
If the payload includes both notification and data objects:
• FCM prioritizes the notification object for background and terminated states, displaying it automatically in the system tray.
• The data object is ignored, and onMessageReceived() is not called.
Solution
To handle and save push notification data to Room effectively:
• Use only the data payload in your backend’s FCM request. Avoid including the notification object.
• Construct your custom notification in the onMessageReceived() method, allowing you to display the notification and save its content to Room simultaneously.
Example Payloads
Notification Payload (Not Recommended):
{
"notification": {
"title": "New Offer!",
"body": "Click to check out the latest deals."
},
"data": {
"type": "offer",
"url": "https://example/deals"
}
}
• Background Behavior: Auto-shows notification, onMessageReceived() not triggered.
Data Payload (Recommended):
{
"data": {
"title": "New Offer!",
"body": "Click to check out the latest deals.",
"type": "offer",
"url": "https://example/deals"
}
}
• Background Behavior: onMessageReceived() is triggered, giving you full control.
Backend Implementation
Ensure your backend sends only the data object to allow consistent handling of notifications across all app states. This provides flexibility to customize notifications and handle tasks like saving data to Room.
For background tasks use the old way and don't use HILT. Try this in onMessageReceived
//initialize database
//after using the below approach
CoroutineScope(Dispatchers.IO).launch {
//save to database code
}
本文标签: In AndroidCan39t save push notification data to Room when app is in backgroundStack Overflow
版权声明:本文标题:In Android, Can't save push notification data to Room when app is in background - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745583524a2157449.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论