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
相关产品推荐
相关产品推荐

