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数据:
- 确保你的启动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>
- 在启动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
相关产品推荐
相关产品推荐

