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

FCM通知+数据负载推送:后台/关闭状态下无法接收数据求助

解决FCM后台/关闭状态下无法获取通知消息中data负载的问题

我太懂你这个困扰了——之前我也踩过FCM这个坑!你遇到的情况本质是FCM对同时包含notification和data字段的消息有特殊的分发逻辑,咱们一步步拆解解决:

问题根源

当你的推送消息同时包含notification和data部分时:

  • 应用前台运行:onMessageReceived会收到完整的消息(包括notification和data),你可以正常解析所有数据;
  • 应用后台/关闭状态:FCM会自动把notification部分直接展示到系统通知栏,而data字段不会主动传递到onCreate/onNewIntent的Intent里——只有当用户点击这条系统通知打开应用时,data数据才会被附加到启动Intent的extras中。如果用户是通过桌面图标直接打开应用,那Intent里就没有这些数据。

而纯data消息之所以正常,是因为FCM会把这类消息直接传递到onMessageReceived,不管应用处于什么状态,完全由你自己控制处理逻辑。

解决方案(两种可选)

方案1:调整推送消息结构(推荐)

把所有自定义数据都放到data字段里,notification字段要么只保留最基础的展示内容,要么干脆去掉,自己在代码里构建系统通知。这样不管应用状态如何,所有数据都会直接到onMessageReceived,你可以统一处理。

修改后的推送请求体示例:

{
  "data": {
    "body": "here is body",
    "title": "Title",
    "type": "LOGIN",
    "intercomMessage": "test"
  },
  "to": "#push_token"
}

然后在FirebaseMessagingService的onMessageReceived里处理:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    // 获取所有data数据
    Map<String, String> data = remoteMessage.getData();
    String type = data.get("type");
    String intercomMessage = data.get("intercomMessage");
    String title = data.get("title");
    String body = data.get("body");

    // 手动构建系统通知(如果需要展示的话)
    showNotification(title, body, type, intercomMessage);
}

private void showNotification(String title, String body, String type, String intercomMessage) {
    // 这里写你的通知构建逻辑,比如使用NotificationCompat.Builder
    Intent intent = new Intent(this, MainActivity.class);
    intent.putExtra("type", type);
    intent.putExtra("intercomMessage", intercomMessage);
    // 设置启动模式,避免重复创建Activity
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    
    // 构建PendingIntent等...
    // 最后调用NotificationManagerCompat.notify()展示通知
}

方案2:保留notification字段,客户端适配处理

如果必须保留notification字段,那就要在客户端处理点击通知后的Intent数据:

  1. 确保你的启动Activity的启动模式是singleTop或singleTask(在AndroidManifest.xml里设置):
<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  1. 在启动Activity里重写onCreate和onNewIntent方法,提取data数据:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 处理冷启动(应用从关闭状态打开)的情况
    parseNotificationData(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    // 更新当前的Intent,避免拿到旧数据
    setIntent(intent);
    // 处理热启动(应用在后台,点击通知唤起)的情况
    parseNotificationData(intent);
}

private void parseNotificationData(Intent intent) {
    if (intent != null && intent.getExtras() != null) {
        // 提取FCM传递的data字段数据
        String type = intent.getStringExtra("type");
        String intercomMessage = intent.getStringExtra("intercomMessage");
        String title = intent.getStringExtra("title");
        String body = intent.getStringExtra("body");
        
        // 这里处理你的业务逻辑,比如根据type跳转页面
        if ("LOGIN".equals(type)) {
            // 执行登录相关的操作
        }
    }
}

需要注意:这种方法只有用户点击系统通知打开应用时才会拿到data数据,如果用户直接打开应用,Intent里是没有这些数据的。

内容的提问来源于stack exchange,提问作者wingear

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:39:56