You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:15:05