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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:38:13