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

FCM集成问题:后台/进程杀死时onMessageReceived未触发及前台推送空白

分析与解决方案

咱们逐个拆解你遇到的核心问题:后台/进程杀死时onMessageReceived不触发、前台推送通知空白、点击通知直接启动启动页,这些问题大多和FCM的payload处理规则、代码里的空指针异常(NPE)以及系统通知逻辑有关。


1. 前台推送空白+onMessageReceived异常崩溃

你的代码里有个致命的NPE问题!因为后端发送的是纯data payload,没有notification字段,所以remoteMessage.getNotification()会返回null,这行代码直接导致onMessageReceived方法崩溃,后续的通知创建逻辑完全没执行:

// 这行代码会抛出NPE,必须移除!
Log.e("remote message >>", remoteMessage.getNotification().getBody() + "");

修复方案:
直接删除这行调用remoteMessage.getNotification()的代码,确保onMessageReceived能正常执行到handleDataMessage方法,进而创建本地通知。


2. 后台/进程杀死时onMessageReceived不调用+点击通知进启动页

FCM对纯data payload的处理规则是:

  • 应用前台:onMessageReceived会被正常调用,由你自己处理消息和创建通知。
  • 应用后台/进程杀死:系统会自动接收消息,并将data字段的参数附加到启动Activity的Intent中,此时onMessageReceived不会被调用(这是FCM的默认行为)。

你看到点击通知直接进启动页,是因为系统默认把启动页(Launcher Activity)作为通知的跳转目标,而你没有在启动页里处理这些附加的参数。

修复方案:
在你的启动页(比如SplashActivity,或者被设置为Launcher的Activity)的onCreate方法中,读取Intent里的extras,处理FCM传递的data参数:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    // 处理FCM传递的data payload参数
    Intent incomingIntent = getIntent();
    if (incomingIntent != null && incomingIntent.getExtras() != null) {
        Bundle extras = incomingIntent.getExtras();
        // 注意key要和后端发送的一致:"job_id"、"stage"
        int jobId = extras.getInt("job_id", 0);
        String stage = extras.getString("stage", "");

        if (jobId > 0 && !stage.isEmpty()) {
            // 跳转到目标页面并传递参数
            Intent homeIntent = new Intent(this, VendorHomeActivity.class);
            homeIntent.putExtra("jobId", jobId);
            homeIntent.putExtra("stage", stage);
            homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(homeIntent);
            finish(); // 结束启动页
        }
    }
}

3. 通知渠道的合法性问题

你的代码里创建通知时用了空字符串作为channelId,在Android 8.0(API 26)及以上版本,这会导致通知无法正常显示:

String channelId = ""; // 空渠道ID不合法

修复方案:
创建一个合法的通知渠道ID,确保渠道创建逻辑正确:

// 修改localNotification方法中的渠道相关代码
String channelId = "fyxt_notification_channel"; // 自定义渠道ID
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.drawable.fyxt_logo)
        .setContentTitle(title)
        .setContentText(message)
        .setAutoCancel(true)
        .setSound(defaultSoundUri)
        .setContentIntent(resultPendingIntent);

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    // 创建通知渠道
    NotificationChannel channel = new NotificationChannel(
            channelId,
            "FYXT 通知", // 渠道名称(用户可见)
            NotificationManager.IMPORTANCE_DEFAULT
    );
    channel.setDescription("应用推送通知渠道"); // 渠道描述(用户可见)
    notificationManager.createNotificationChannel(channel);
}

4. 额外的细节优化

  • BroadcastReceiver的生命周期管理:确保你的Activity在onResume时注册广播接收器,onPause时注销,避免内存泄漏:
    @Override
    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(
                notificationReceiver,
                new IntentFilter(Constants.PUSH_NOTIFICATION_INTENT)
        );
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(notificationReceiver);
    }
    
  • PendingIntent的Flags:如果需要确保每次点击通知都能传递最新的参数,可以使用PendingIntent.FLAG_UPDATE_CURRENT替代FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:48:11