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

.NET MAUI Android应用后台点击分组通知无法获取数据

问题描述

我正在用.NET MAUI开发Android应用,通过Google Firebase接收推送通知,遇到以下问题:

  • 应用处于后台或被杀死状态时,通知抽屉内的多条通知会自动分组显示
  • 点击未展开的分组通知时,MainActivity的OnNewIntent()方法中,intent?.HasExtra("body")返回false,直接调用Intent.HasExtra("body")结果一致,且OnNewIntent()仅执行一次,无法获取任何通知数据
  • 单条通知后台点击、展开分组后逐个点击通知,均能正常获取数据,intent?.HasExtra("body")返回true
  • 应用前台时无此问题,该现象在Android模拟器和Pixel 7真机上均复现

MainActivity代码

[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
{
    public void OnSuccess(Java.Lang.Object result)
    {
        DeviceInstallationService.Token = result.ToString();
    }

    // 应用后台时点击通知抽屉内的通知会触发此方法
    protected override void OnNewIntent(Intent intent)
    {
        base.OnNewIntent(intent);
        ProcessNotificationsAction(intent);
    }

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        if (DeviceInstallationService.NotificationsSupported)
            FirebaseMessaging.Instance.GetToken().AddOnSuccessListener(this);

        ProcessNotificationsAction(Intent);
    }

    private void ProcessNotificationsAction(Intent intent)
    {
        try
        {
            Task.Run(() =>
            {
                if (intent?.HasExtra("body") == true)
                {
                    var body = intent.GetStringExtra("body");

                    if (!string.IsNullOrEmpty(body))
                    {
                        var id = Guid.Parse(intent.GetStringExtra("id"));
                        var application = intent.GetStringExtra("application");
                        var datePublished = DateTime.SpecifyKind(DateTime.Parse(intent.GetStringExtra("datePublished")), DateTimeKind.Utc);
                        NotificationMessageService.TriggerMessage(id, application, body, intent.HasExtra("url") ? intent.GetStringExtra("url") : null, datePublished);
                    }
                }
            });
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }
    }
}

Firebase发送的消息内容

{
  "message": {
    "notification": {
      "title": "Notification title",
      "body": "This is a test message..."
    },
    "android": {
      "notification": {
        "channel_id": "com.company.app.default"
      }
    },
    "data": {
      "id": "A GUID",
      "application": "App type A",
      "body": "This is a test message...",
      "url": "http://www...",
      "datePublished": "2024-11-08T00:00:00.0000000Z"
    }
  }
}

环境与NuGet版本

  • .NET MAUI - 8.0.82
  • Microsoft.Maui.Controls - 8.0.82
  • Microsoft.Maui.Controls.Compatibility - 8.0.82
  • Xamarin.Firebase.Messaging 124.0.0.1

解决方案

这个问题的核心是:点击未展开的通知分组时,Android系统会发送汇总Intent,而非单个通知的Intent,因此无法获取到data字段内容。以下是三种可行的解决方式:

方式1:配置Firebase通知的分组点击行为

在发送的消息中,为Android通知添加分组相关配置,指定汇总通知的点击行为和携带数据:

{
  "message": {
    "notification": {
      "title": "Notification title",
      "body": "This is a test message..."
    },
    "android": {
      "notification": {
        "channel_id": "com.company.app.default",
        "group": "your_custom_group_id",
        "group_alert_behavior": "summary",
        "summary_notification": {
          "title": "新通知提醒",
          "body": "你有X条未读消息",
          "click_action": "OPEN_MAIN_ACTIVITY"
        }
      },
      "data": {
        "id": "A GUID",
        "application": "App type A",
        "body": "This is a test message...",
        "url": "http://www...",
        "datePublished": "2024-11-08T00:00:00.0000000Z"
      }
    }
  }
}

group_alert_behavior设为summary时,仅汇总通知会触发提醒;点击汇总通知时,会使用summary_notification配置的内容和点击行为。

方式2:在MainActivity中处理汇总Intent

当检测到是汇总Intent时,读取本地存储的最新通知数据进行处理:
修改ProcessNotificationsAction方法:

private void ProcessNotificationsAction(Intent intent)
{
    try
    {
        Task.Run(() =>
        {
            // 判断是否是分组汇总通知的Intent
            if (intent?.Action == "OPEN_MAIN_ACTIVITY" && !intent.HasExtra("body"))
            {
                // 从SharedPreferences读取本地存储的最新通知数据
                var prefs = GetSharedPreferences("NotificationCache", FileCreationMode.Private);
                var lastBody = prefs.GetString("LastBody", null);
                var lastId = prefs.GetString("LastId", null);
                
                if (!string.IsNullOrEmpty(lastBody) && !string.IsNullOrEmpty(lastId))
                {
                    var id = Guid.Parse(lastId);
                    var application = prefs.GetString("LastApp", null);
                    var datePublished = DateTime.SpecifyKind(DateTime.Parse(prefs.GetString("LastDate", "")), DateTimeKind.Utc);
                    var url = prefs.GetString("LastUrl", null);
                    NotificationMessageService.TriggerMessage(id, application, lastBody, url, datePublished);
                }
            }
            else if (intent?.HasExtra("body") == true)
            {
                var body = intent.GetStringExtra("body");
                if (!string.IsNullOrEmpty(body))
                {
                    var id = Guid.Parse(intent.GetStringExtra("id"));
                    var application = intent.GetStringExtra("application");
                    var datePublished = DateTime.SpecifyKind(DateTime.Parse(intent.GetStringExtra("datePublished")), DateTimeKind.Utc);
                    var url = intent.HasExtra("url") ? intent.GetStringExtra("url") : null;
                    NotificationMessageService.TriggerMessage(id, application, body, url, datePublished);
                    
                    // 将当前通知数据存储到本地,供汇总通知点击时使用
                    var prefs = GetSharedPreferences("NotificationCache", FileCreationMode.Private);
                    var editor = prefs.Edit();
                    editor.PutString("LastBody", body);
                    editor.PutString("LastId", id.ToString());
                    editor.PutString("LastApp", application);
                    editor.PutString("LastDate", datePublished.ToString("o"));
                    editor.PutString("LastUrl", url);
                    editor.Apply();
                }
            }
        });
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
}

方式3:仅发送Data消息,自定义通知逻辑

放弃Firebase的默认通知展示,只发送data消息,完全自定义通知的创建和分组逻辑,确保所有通知(包括汇总通知)的Intent都携带所需数据:

{
  "message": {
    "data": {
      "id": "A GUID",
      "application": "App type A",
      "body": "This is a test message...",
      "url": "http://www...",
      "datePublished": "2024-11-08T00:00:00.0000000Z",
      "title": "Notification title"
    },
    "android": {
      "priority": "high"
    }
  }
}

然后在自定义的FirebaseMessagingService的OnMessageReceived方法中,手动创建通知并处理分组逻辑,控制每个通知的Intent内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 13:10:56