Xamarin中如何控制Firebase Cloud Messaging后台通知的显示与隐藏
在Xamarin中控制FCM后台通知的显示与隐藏
嘿,这个需求完全可以实现!针对你说的场景——后台时过滤无关消息避免骚扰,前台正常处理,我来给你拆解几个可行的方案:
方案一:使用FCM数据消息而非通知消息,客户端自主控制
FCM的消息分为两种:
- 通知消息(Notification Payload):后台时系统会自动弹出通知,前台才会触发
OnMessageReceived; - 数据消息(Data Payload):无论前台还是后台,都会直接触发
OnMessageReceived,不会自动弹通知。
所以核心思路是:服务器只发送数据消息,把通知的控制权完全交给客户端。你可以在消息里携带自定义字段(比如isRelevantToUser)标记这条消息是否和当前用户相关,然后在OnMessageReceived里判断应用状态和消息相关性,决定是否显示通知。
代码示例(Xamarin Android)
[Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class MyFirebaseMessagingService : FirebaseMessagingService { public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); // 从消息数据中获取是否和当前用户相关的标记 var isRelevant = message.Data.TryGetValue("isRelevant", out string relevantStr) && bool.Parse(relevantStr); // 判断应用是否处于后台 var isBackground = !IsAppInForeground(); if (isBackground) { if (isRelevant) { // 只有相关的消息,才手动构建通知显示 ShowCustomNotification(message); } // 无关消息直接静默,不做任何处理 } else { // 前台状态,直接把消息推送到聊天界面 UpdateChatInterface(message); } } // 辅助方法:判断应用是否在前台运行 private bool IsAppInForeground() { var activityManager = (ActivityManager)GetSystemService(Context.ActivityService); var runningProcesses = activityManager.RunningAppProcesses; if (runningProcesses == null) return false; foreach (var process in runningProcesses) { if (process.ProcessName.Equals(PackageName, StringComparison.Ordinal) && process.Importance == Android.App.Importance.Foreground) { return true; } } return false; } // 手动构建并显示通知的方法 private void ShowCustomNotification(RemoteMessage message) { // 创建跳转回主界面的Intent var intent = new Intent(this, typeof(MainChatActivity)); intent.AddFlags(ActivityFlags.ClearTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot); // 构建通知内容 var notificationBuilder = new NotificationCompat.Builder(this, "chat_notification_channel") .SetSmallIcon(Resource.Drawable.ic_chat_notification) .SetContentTitle(message.Data["title"]) .SetContentText(message.Data["body"]) .SetAutoCancel(true) .SetPriority((int)NotificationPriority.High) .SetContentIntent(pendingIntent); // 显示通知 var notificationManager = NotificationManager.FromContext(this); notificationManager.Notify(new Random().Next(), notificationBuilder.Build()); } // 更新聊天界面的方法(根据你的UI逻辑实现) private void UpdateChatInterface(RemoteMessage message) { // 这里写前台时更新聊天列表、显示消息气泡的逻辑 MessagingCenter.Send(this, "NewChatMessage", message.Data); } }
方案二:服务器端前置判断,按需发送FCM
如果你的服务器能实时获取用户的应用状态(比如通过WebSocket心跳、或者客户端定期上报的在线状态),可以在发送FCM前先做判断:
- 如果用户A处于后台,且消息和A无关 → 不发送这条FCM;
- 如果用户A处于前台,或者消息和A相关 → 正常发送FCM(可以是通知消息或数据消息)。
这种方式从源头减少了不必要的消息推送,更节省资源,但依赖服务器对用户状态的实时感知能力。
注意事项:Android 8.0+的通知渠道
如果使用方案一手动构建通知,必须先创建对应的通知渠道(Android 8.0及以上要求),否则通知不会显示。可以在MyFirebaseMessagingService的OnCreate方法中添加渠道创建逻辑:
public override void OnCreate() { base.OnCreate(); if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel( "chat_notification_channel", "聊天消息通知", NotificationImportance.Default) { Description = "接收聊天相关的通知提醒" }; var notificationManager = GetSystemService(NotificationService) as NotificationManager; notificationManager?.CreateNotificationChannel(channel); } }
总结
推荐优先使用方案一,因为客户端自主控制的方式更灵活,不需要依赖服务器的状态感知能力,能完美实现你要的“后台无关消息静默、前台正常处理”的需求。
内容的提问来源于stack exchange,提问作者King Chan
相关产品推荐
相关产品推荐

