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

Android FCM:前台时在onMessageReceived中触发默认通知方法

关于FCM前台触发默认通知的解决方案

嘿,这个问题我之前做FCM集成的时候刚好研究过,给你详细捋清楚~

首先直接给结论:没有官方方式直接复用系统后台的默认通知处理逻辑——当应用在前台时,FCM会把消息完全交付给你的FirebaseMessagingService子类,系统不会自动生成通知。不过我们可以手动模拟出和后台默认一致的通知效果,过程并不复杂,只要正确解析FCM消息里的字段就行。

核心思路

系统后台处理FCM通知时,是读取消息中的notification字段(而非data字段)来构建通知的,所以我们只需要在onMessageReceived中提取这些字段,用NotificationCompat.Builder复刻出相同的配置即可。

具体实现步骤

1. 提取FCM通知的核心字段

从RemoteMessage的Notification对象里,我们需要获取这些关键参数:

  • 通知标题:remoteMessage.getNotification().getTitle()
  • 通知内容:remoteMessage.getNotification().getBody()
  • 通知图标:remoteMessage.getNotification().getIcon()(如果消息没指定,就用应用默认图标)
  • 点击跳转行为:系统默认是打开应用主Activity,我们需要构建对应的PendingIntent

2. 适配Android O+的通知通道

Android 8.0及以上必须设置通知通道,我们创建一个和系统默认行为一致的通道:

  • 通道ID可以设为FCM_DEFAULT_CHANNEL(自定义即可)
  • 通道名称设为“FCM通知”
  • 重要性设为IMPORTANCE_DEFAULT,匹配系统默认通知的优先级

3. 完整代码示例

在你的FirebaseMessagingService子类中添加如下代码:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    
    // 只处理包含notification字段的消息(这是系统后台默认处理的类型)
    if (remoteMessage.getNotification() != null) {
        showDefaultFcmNotification(remoteMessage.getNotification());
    }
}

private void showDefaultFcmNotification(RemoteMessage.Notification fcmNotification) {
    // 1. 创建通知通道(Android O+ 必需)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
                "FCM_DEFAULT_CHANNEL",
                "FCM通知",
                NotificationManager.IMPORTANCE_DEFAULT
        );
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        if (notificationManager != null) {
            notificationManager.createNotificationChannel(channel);
        }
    }
    
    // 2. 创建打开主Activity的PendingIntent
    Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
    if (launchIntent != null) {
        launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                launchIntent,
                PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT
        );
        
        // 3. 构建通知
        int iconResId = fcmNotification.getIcon() != null 
                ? getResources().getIdentifier(fcmNotification.getIcon(), "drawable", getPackageName()) 
                : R.mipmap.ic_launcher;
        
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "FCM_DEFAULT_CHANNEL")
                .setSmallIcon(iconResId)
                .setContentTitle(fcmNotification.getTitle())
                .setContentText(fcmNotification.getBody())
                .setAutoCancel(true) // 点击通知后自动消失
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
        
        // 4. 显示通知
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        // 用时间戳作为通知ID,避免重复通知被覆盖
        notificationManager.notify((int) System.currentTimeMillis(), builder.build());
    }
}

4. 额外细节补充

  • 如果你的FCM消息包含click_action字段,需要根据该字段指定的Activity类名来构建Intent,而不是默认的主Activity,这样更贴合系统默认行为。
  • 通知的声音、振动:NotificationCompat.Builder默认会继承通道的设置,我们创建的IMPORTANCE_DEFAULT通道会使用设备的默认通知声音和振动,无需额外配置。
  • 通知ID:用时间戳可以避免相同内容的通知被覆盖,如果你希望相同类型的通知被替换,可以固定一个ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:15:06