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

添加click_action后Android FCM后台/杀死状态无法接收推送求助

我来帮你捋清楚这个问题,FCM的消息类型差异就是核心原因!

问题根源:FCM两种消息类型的处理逻辑差异

FCM有两种核心消息类型,它们的分发逻辑完全不同:

  • Notification消息:当App处于后台/被杀死状态时,系统会直接接管并自动展示通知,不会触发你的onMessageReceived()方法;只有App在前台时,才会走到onMessageReceived()。
  • Data消息:无论App处于什么状态(前台/后台/杀死),都会完整传递到onMessageReceived(),所有通知展示、跳转逻辑都由你自己控制。

从你提供的Bundle内容来看,当前的消息是混合类型(包含gcm.notification.*前缀的字段),所以后台/杀死状态下系统直接展示通知,但你的自定义逻辑(比如prepareIntent()里的Session判断)根本没机会执行,甚至可能因为系统处理click_action时的状态问题,导致看起来像是没收到通知。

解决方案:改用纯Data类型消息

要彻底解决这个问题,最佳方案是让服务器发送纯Data消息,把所有需要的参数(包括原本Notification里的title、body、click_action,还有你的业务参数userId、flag等)都放到data字段里。这样不管App状态如何,都会走到onMessageReceived(),你可以完全控制通知的展示和跳转。

1. 调整服务器端消息格式

把原本的Notification字段全部移到data中,示例JSON格式如下:

{
  "to": "DEVICE_TOKEN",
  "data": {
    "title": "Someone try to login with your credentials",
    "body": "TEST MESSAGE",
    "click_action": "com.my.push.activities.OPEN_NOTIFICATION_LIST",
    "notification_id": "1140",
    "notificationId": "2047669",
    "userId": "140128",
    "flag": "0",
    // 其他业务参数...
  }
}

2. 修改客户端代码

纯Data消息的remoteMessage.getNotification()会返回null,所以你需要从remoteMessage.getData()里获取所有参数:

调整prepareIntent()方法
public Intent prepareIntent(RemoteMessage remoteMessage) {
    Map<String, String> response = remoteMessage.getData();
    Intent intent;
    
    if (SessionContext.isLoggedIn()) {
        String clickAction = response.get("click_action");
        // 统一用click_action构建Intent,同时添加默认category确保能找到目标页面
        intent = new Intent(clickAction);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        
        // 传递业务参数到目标页面
        intent.putExtra("userId", response.get("userId"));
        intent.putExtra("flag", response.get("flag"));
    } else {
        intent = new Intent(this, LoginActivity.class);
    }
    
    // 添加Flag确保跳转逻辑符合预期(比如清除栈顶、新建任务)
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    return intent;
}
调整showNotification()方法

从data中获取通知标题、内容,不再依赖remoteMessage.getNotification():

public void showNotification(RemoteMessage remoteMessage) {
    try {
        Map<String, String> response = remoteMessage.getData();
        
        Intent intent = prepareIntent(remoteMessage);
        PendingIntent pIntent = PendingIntent.getActivity(this, 
                Integer.parseInt(response.get("notificationId")), // 用唯一ID区分不同通知的PendingIntent
                intent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // 适配Android 12+的Flag
        
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "D4E_ANDROID")
                .setContentTitle(response.get("title"))
                .setContentText(response.get("body"))
                .setSmallIcon(R.drawable.d4e_logo)
                .setContentIntent(pIntent)
                .setAutoCancel(true)
                .addAction(R.drawable.view_icon, "View", pIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        notificationManager.notify(Integer.parseInt(response.get("notificationId")), builder.build());
    } catch (Exception exception) {
        Log.e("OnREC", exception.toString());
    }
}

3. 确保目标Activity配置正确

在AndroidManifest.xml中,给click_action对应的Activity添加intent-filter,保证系统能找到它:

<activity android:name=".activities.NotificationListActivity">
    <intent-filter>
        <action android:name="com.my.push.activities.OPEN_NOTIFICATION_LIST" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

为什么不推荐在Notification消息里用click_action?

虽然FCM允许在Notification消息里设置click_action,但这种方式的控制权在系统手上:

  • 当App被杀死时,系统会直接启动对应的Activity,但不会经过你自定义的Session判断逻辑(比如你代码里的SessionContext.isLoggedIn()),可能导致未登录用户直接进入需要权限的页面。
  • 系统展示的通知样式相对固定,无法完全自定义(比如你代码里的自定义Action按钮)。

而纯Data消息完全由你控制,能适配所有场景,逻辑更统一,也更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:23:44