Android中FCM通知:应用前台时如何显示全部通知
解决Android FCM前台通知互相覆盖的问题
通知互相覆盖的核心原因是多次发送通知时使用了相同的通知ID——Android系统会用新通知替换掉同ID的旧通知。要让前台显示所有通知,关键是为每个通知分配唯一的ID,具体实现步骤如下:
1. 为每个通知生成唯一ID
可以通过两种方式获取/生成唯一ID:
- 从FCM消息的自定义数据中获取:如果服务器在发送FCM消息时,在
data字段中携带唯一的消息标识(比如message_id),直接用这个值作为通知ID。 - 本地生成唯一值:如果服务器没有提供唯一标识,可在本地用随机数、时间戳或UUID生成。
2. 前台消息的处理逻辑
当应用处于前台时,FCM不会自动弹出通知,需要在FirebaseMessagingService的onMessageReceived方法中手动构建并发送通知,同时传入唯一ID。
完整代码示例
第一步:实现应用前台状态判断
在自定义Application类中注册生命周期回调,跟踪应用是否在前台:
public class MyApp extends Application implements Application.ActivityLifecycleCallbacks { private static boolean isAppForeground = false; @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(this); } @Override public void onActivityResumed(Activity activity) { isAppForeground = true; } @Override public void onActivityPaused(Activity activity) { isAppForeground = false; } // 其余生命周期方法留空实现即可 @Override public void onActivityCreated(Activity activity) {} @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityStopped(Activity activity) {} @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityDestroyed(Activity activity) {} public static boolean isAppInForeground() { return isAppForeground; } }
第二步:在FirebaseMessagingService中处理前台通知
public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); if (MyApp.isAppInForeground()) { // 提取通知内容 String title = remoteMessage.getNotification() != null ? remoteMessage.getNotification().getTitle() : "通知"; String body = remoteMessage.getNotification() != null ? remoteMessage.getNotification().getBody() : ""; // 获取/生成唯一通知ID int notificationId; // 优先使用服务器传来的message_id if (remoteMessage.getData().containsKey("message_id")) { try { notificationId = Integer.parseInt(remoteMessage.getData().get("message_id")); } catch (NumberFormatException e) { // 解析失败则生成随机ID notificationId = new Random().nextInt(Integer.MAX_VALUE); } } else { // 本地生成唯一ID,这里用时间戳 notificationId = (int) System.currentTimeMillis(); } // 构建通知(确保已创建对应通知渠道) NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "YOUR_CHANNEL_ID") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(title) .setContentText(body) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setAutoCancel(true); // 发送通知,传入唯一ID NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(notificationId, builder.build()); } } }
3. 注意事项
- 通知渠道:Android 8.0(API 26)及以上必须创建通知渠道,否则通知无法显示。可在应用启动时初始化渠道:
private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "通知渠道名称"; String description = "通知渠道描述"; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel("YOUR_CHANNEL_ID", name, importance); channel.setDescription(description); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } }
- 数据消息 vs 通知消息:如果服务器发送的是纯
data消息,无论应用前后台都会触发onMessageReceived,处理逻辑和上述一致;如果是notification消息,后台时FCM会自动显示通知,前台则需要手动处理。
内容的提问来源于stack exchange,提问作者Mohamed hassan
相关产品推荐
相关产品推荐

