Android应用后台状态下无法将推送通知数据保存至Room数据库
解决FCM后台/非活跃状态下无法保存通知至Room的问题
问题核心原因
你的FCM Payload同时包含notification和data字段:
- 应用前台时,
FirebaseMessagingService的onMessageReceived会被触发,能正常拿到所有数据并启动WorkManager保存。 - 应用后台/非活跃时,系统会自动接管
notification字段展示通知,不会触发onMessageReceived,只有用户点击通知时,数据才会通过启动的Activity传递,这时候才有可能处理保存逻辑。
解决方案
方案1:后端调整Payload(推荐)
让后端只发送纯data消息,移除notification字段。这样无论应用处于前台还是后台,onMessageReceived都会被触发,你可以在该方法内正常启动SaveNotificationWorker保存数据。
调整后的示例Payload:
{ "data": { "title": "কথা চলুক সেরা অফারে!", "body": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!", "imageUrl": "https://myapp-dev-static.robi.com.bd/images/payment/bkash.png", "description": "১৯৯ টাকায় ৩০০ মিনিট ৩০ দিন মেয়াদে পেতে ট্যাপ করুন!", "sentAt": "1731929876", "expiredAt": "1731982676", "buttonText": "Open Recharge", "type": "in_app", "url": "myapp-ppd://dashboard", "image": "https://media.giphy.com/media/Ju7l5y9osyymQ/giphy.gif", "token": "XXX" }, "operator": "moon" }
之后在RasaFcmService的onMessageReceived中,自行解析data字段构建通知展示,同时启动SaveNotificationWorker保存数据。
方案2:客户端适配现有Payload(后端无法修改时)
如果后端不能调整Payload,需要处理用户点击通知的场景:
- 在AndroidManifest中配置接收通知点击的Activity,确保其
launchMode设置为singleTop或合适的模式:
<activity android:name=".ui.NotificationClickActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
- 在该Activity的
onCreate或onNewIntent中,解析Intent携带的FCM数据,启动SaveNotificationWorker:
class NotificationClickActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) handleNotificationData(intent) finish() } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent?.let { handleNotificationData(it) } } private fun handleNotificationData(intent: Intent) { val data = intent.extras ?: return val notificationData = parseNotificationData(data) val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>() .setInputData(workDataOf("notification_data" to Gson().toJson(notificationData))) .build() WorkManager.getInstance(this).enqueue(workRequest) } }
- 确保
SaveNotificationWorker能正确解析输入的数据并写入Room。
方案3:检查WorkManager后台执行约束
确认SaveNotificationWorker的执行约束是否过于严格,比如不必要的网络约束导致后台无法执行:
// 错误示例:如果保存Room不需要网络,不要加这个约束 .setRequiredNetworkType(NetworkType.CONNECTED) // 正确示例:仅保留必要约束(如不需要网络则移除) val workRequest = OneTimeWorkRequestBuilder<SaveNotificationWorker>() .build()
测试验证
使用adb命令模拟发送FCM消息,测试后台状态下的保存逻辑:
adb shell am broadcast -a com.google.firebase.MESSAGING_EVENT -n 你的包名/com.google.firebase.messaging.FirebaseMessagingReceiver --es "data" "{\"title\":\"测试标题\",\"body\":\"测试内容\"}"
内容的提问来源于stack exchange,提问作者Aminul Haque Aome
相关产品推荐
相关产品推荐

