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

Android应用后台/被杀时无法从FCM通知中提取数据问题求解

FCM后台/进程被杀场景无法提取推送数据解决方案

这个问题本质是FCM的消息类型分发逻辑差异导致的,可按以下方案解决:

问题原因

FCM推送分为两类消息,不同场景下的分发逻辑不同:

  • 通知类型消息:应用前台时走自定义FirebaseMessagingService的onMessageReceived回调,可直接提取数据;应用后台/进程被杀时,通知由系统通知栏直接托管,点击默认打开启动页,自定义数据不会主动传入业务Activity
  • 数据类型消息:所有场景都走onMessageReceived回调,可自主控制通知弹出和数据传递,完全不受前后台状态影响

解决方案

方案1:推送端统一使用数据类型消息(优先推荐)

推送payload不携带notification字段,仅传递data字段,所有场景都由应用自身控制通知弹出和数据传递:

// FirebaseMessagingService的onMessageReceived示例代码
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    // 提取自定义数据
    Map<String, String> data = remoteMessage.getData();
    // 构造跳转Intent,将数据塞入bundle
    Intent intent = new Intent(this, TargetActivity.class);
    for (Map.Entry<String, String> entry : data.entrySet()) {
        intent.putExtra(entry.getKey(), entry.getValue());
    }
    PendingIntent pendingIntent = PendingIntent.getActivity(
        this, 
        0, 
        intent, 
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
    );
    // 自定义弹出通知
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel("fcm_push", "消息推送", NotificationManager.IMPORTANCE_HIGH);
        notificationManager.createNotificationChannel(channel);
    }
    Notification notification = new NotificationCompat.Builder(this, "fcm_push")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(data.get("title"))
            .setContentText(data.get("content"))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .build();
    notificationManager.notify((int) System.currentTimeMillis(), notification);
}

方案2:必须使用带notification的混合推送时适配启动页

如果推送端无法修改消息类型,点击通知后系统会把所有data字段内容塞入启动页的Intent extras中,在启动页中接收后再转发到业务页面即可:

// 启动页Activity示例代码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
    handlePushData(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handlePushData(intent);
}

private void handlePushData(Intent intent) {
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            // 过滤FCM系统自带字段,仅提取自定义业务数据
            if (!key.startsWith("google.") && !key.startsWith("gcm.")) {
                String value = extras.getString(key);
                // 拿到数据后自行处理跳转逻辑
            }
        }
    }
}

注意事项

  • Android 12及以上创建PendingIntent时必须显式指定FLAG_IMMUTABLE或FLAG_MUTABLE,否则数据会丢失
  • 部分定制ROM会限制进程被杀后冷启动的Intent数据传递,优先选择方案1可完全规避系统托管逻辑

内容的提问来源于stack exchange,提问作者Code Learner.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 20:45:03