应用被杀死时FCM推送未触发onMessageReceive问题求助
解决FCM杀死状态下onMessageReceived不触发、音效仅播放一次的问题
我来帮你搞定这个问题,核心原因其实和FCM的消息分发机制有关,先给你理清楚:
问题根源
当你同时发送Notification消息和Data消息时,FCM的处理逻辑是这样的:
- 应用前台状态:
onMessageReceived会被触发,你能拿到所有Data和Notification内容 - 应用后台/杀死状态:系统会自动帮你展示Notification消息,而Data消息会被附加到通知的跳转Intent里,不会触发
onMessageReceived
这就是为什么你在应用杀死时,onMessageReceived没执行,音效只播放了一次——那其实是系统默认通知的音效,不是你自己的SoundIntentService触发的。
解决方案
最靠谱的解决方式是只发送纯Data消息,把通知的展示和音效播放完全交给客户端自己处理,这样不管应用处于什么状态,onMessageReceived都会被触发。
1. 调整云服务器的推送消息结构
去掉notification字段,只保留data字段,示例格式如下:
{ "to": "你的设备Token", "data": { "orderId": "12345", "orderType": "外卖", "orderStatus": "待接单" } }
2. 修改MyFirebaseMessagingService的逻辑
在onMessageReceived里自己构建自定义通知,同时启动你的音效服务,确保每次收到推送都能触发音效:
@Override public void onMessageReceived(RemoteMessage remoteMessage) { Log.e("@@", ">>>>>>>>>: Inside CLASS"); Log.e("@@", ">>>>>>>>>: Inside ON MESSAGE RECEIVED"); Map<String, String> data = remoteMessage.getData(); String orderID = data.get("orderId"); String orderType = data.get("orderType"); String orderStatus = data.get("orderStatus"); // 1. 构建自定义通知(适配Android O及以上的渠道要求) Intent activityIntent = new Intent(this, MainActivity.class); // 替换成你的目标Activity activityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, activityIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE ); String channelId = "order_notification_channel"; NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标 .setContentTitle("新订单提醒") .setContentText("订单ID:" + orderID + " | 类型:" + orderType) .setPriority(NotificationCompat.PRIORITY_HIGH) .setAutoCancel(true) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 创建通知渠道(Android O+必须) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( channelId, "订单通知", NotificationManager.IMPORTANCE_HIGH ); notificationManager.createNotificationChannel(channel); } // 展示通知 notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build()); // 2. 启动音效服务(适配Android O+的前台服务要求) Intent soundServiceIntent = new Intent(getApplicationContext(), SoundIntentService.class); // 可传递订单参数给服务 soundServiceIntent.putExtra("orderId", orderID); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(soundServiceIntent); } else { startService(soundServiceIntent); } }
3. 优化SoundIntentService的稳定性
为了确保音效能持续播放且不被系统轻易回收,建议:
- 在
onStartCommand中返回START_STICKY,这样服务被杀死后能尝试重启 - Android O及以上版本中,把服务设为前台服务(显示一个前台通知),避免被系统后台限制杀死
备选方案(不推荐)
如果必须保留Notification消息的发送,那只能在用户点击通知时,在跳转的Activity中获取Data参数,再启动音效服务。但这种方式无法在收到推送时自动播放音效,只能等用户点击,体验不好,所以还是优先用纯Data消息的方案。
内容的提问来源于stack exchange,提问作者smpatel
相关产品推荐
相关产品推荐

