Android 8后台应用中Firebase通知转发至onMessageReceived的正确方式
解决方案:将后台FCM通知转发至
onMessageReceived() 我来帮你搞定这个FCM后台通知的问题!首先得明确为什么之前用弃用的WakefulBroadcastReceiver方案不够理想,以及现在官方推荐的正确做法:
核心原理先搞懂
FCM的推送分为两种payload类型,它们在应用后台时的处理逻辑完全不同:
- Notification payload:包含
notification字段的推送,应用后台时会被系统直接接管,自动显示通知,不会触发你的MyFirebaseMessagingService.onMessageReceived()。 - Data payload:只包含
data字段的推送,不管应用在前台还是后台,都会直接触发onMessageReceived(),所有逻辑由你自己控制。
方案1:发送纯Data消息(推荐)
这是最可靠的方式,能让所有推送都走到你的onMessageReceived()方法,完全绕过系统的自动处理。
推送结构示例
不管你用Firebase控制台还是API发送,只需要构造纯Data的payload:
{ "to": "目标设备的token", "data": { "title": "自定义通知标题", "body": "自定义通知内容", "any_custom_key": "自定义参数" } }
你的Service代码无需大改
现在你的MyFirebaseMessagingService已经能处理Data payload了,只需要确保displayNotification()方法能正确解析remoteMessage.getData()里的字段:
private void displayNotification(RemoteMessage remoteMessage) { // 从data里取出自定义字段 String title = remoteMessage.getData().get("title"); String body = remoteMessage.getData().get("body"); // 这里写你的通知构建逻辑 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(title) .setContentText(body) .setPriority(NotificationCompat.PRIORITY_DEFAULT); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(1, builder.build()); }
方案2:如果必须用Notification+Data混合payload
如果业务需求必须同时发送notification和data字段,那应用后台时系统会显示通知,data里的参数会附加到通知点击后的启动Intent中。你需要在目标Activity里获取这些参数,再做后续处理:
在Activity中获取Data参数
在你的主Activity(或者通知点击跳转的Activity)里,重写onCreate()和onNewIntent()来获取数据:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handleFCMData(getIntent()); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); handleFCMData(intent); } private void handleFCMData(Intent intent) { if (intent != null && intent.getExtras() != null) { // 取出data里的参数 String customData = intent.getExtras().getString("any_custom_key"); // 这里可以把数据转发到MyFirebaseMessagingService,或者直接处理 // 比如发送一个本地广播,或者启动Service处理 } }
替代弃用的WakefulBroadcastReceiver
如果你之前用WakefulBroadcastReceiver是为了唤醒后台Service执行任务,现在官方推荐用以下方式:
- 短任务:直接在
onMessageReceived()里处理(注意不要做耗时操作,否则会被系统杀死)。 - 长任务:使用
WorkManager来调度后台任务,或者启动Foreground Service(Android O及以上必须显示前台通知):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(new Intent(this, YourLongRunningService.class)); } else { startService(new Intent(this, YourLongRunningService.class)); }
清单文件检查
你当前的Service配置是正确的,确保没有多余的旧BroadcastReceiver配置干扰:
<service android:name=".firebase.MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service>
内容的提问来源于stack exchange,提问作者matdev
相关产品推荐
相关产品推荐

