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

.NET MAUI安卓端OnNewIntent中Intent.Extras为空及后台收不到通知求助

问题描述

按照MAUI推送通知Demo配置后,遇到两个核心问题:

  1. MainActivity中重写的OnNewIntent方法里Intent.Extras为空,导致推送点击后的导航逻辑无法执行
  2. 应用未运行或处于后台时,无法接收推送通知

相关代码如下:

[Service(Exported = true)]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FirebaseService : FirebaseMessagingService
{
    private int badgeNumber = 0;

    public FirebaseService()
    {
    }

    public override void OnNewToken(string token)
    {
        base.OnNewToken(token);

        if (Preferences.ContainsKey(StorageKeys.Public.GCM))
        {
            Preferences.Remove(StorageKeys.Public.GCM);
        }

        Preferences.Set(StorageKeys.Public.GCM, token);
    }

    public override void OnMessageReceived(RemoteMessage message)
    {
        base.OnMessageReceived(message);

        badgeNumber++;

       var notification = message.GetNotification();
       SendNotification(notification.Body, notification.Title, message.Data);
    }

    private void SendNotification(string messageBody, string title, IDictionary<string, string> data)
    {
        var intent = new Intent(this, typeof(MainActivity));
        intent.AddFlags(ActivityFlags.ClearTop);
        intent.AddFlags(ActivityFlags.SingleTop);

        foreach (var key in data.Keys)
        {
            var value = data[key];
            intent.PutExtra(key, value);
        }

        var pendingIntent = PendingIntent.GetActivity(this,MainActivity.NotificationId, intent, PendingIntentFlags.OneShot | PendingIntentFlags.Immutable);

        var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.ChannelId)
            .SetContentTitle(title)
            .SetSmallIcon(Microsoft.Maui.Controls.Resource.Drawable.ic_notification)
            .SetContentText(messageBody)
            .SetChannelId(MainActivity.ChannelId)
            .SetContentIntent(pendingIntent)
            .SetAutoCancel(true)
            .SetPriority((int)NotificationPriority.Max);

        var notificationManager = NotificationManagerCompat.From(this);
        notificationManager.Notify(MainActivity.NotificationId, notificationBuilder.Build());
    }
}

[Activity(Theme = "@style/Maui.SplashTheme", LaunchMode = LaunchMode.SingleTask, MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
    internal static readonly string ChannelId = "BSI Notification Chanel";
    internal static readonly int NotificationId = 19780811;

    public MainActivity()
    {
    }

    public override void OnBackPressed() { }

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

        if (ContextCompat.CheckSelfPermission(this, Android.Manifest.Permission.PostNotifications) == Permission.Denied)
        {
            ActivityCompat.RequestPermissions(this, new String[] { Android.Manifest.Permission.PostNotifications }, 1);
        }

        CreateNotificationChanel();
    }

    protected override void OnNewIntent(Intent? intent)
    {
        base.OnNewIntent(intent);

        if (Intent?.Extras != null)
        {
            foreach (var key in Intent?.Extras.KeySet() ?? [])
            {
                if (key == "NavigateTo")
                {
                    var page = Intent?.Extras.GetString(key);

                    if (Preferences.ContainsKey("NavigateTo"))
                    {
                        Preferences.Remove("NavigateTo");
                    }

                    Preferences.Set("NavigateTo", page);

                    WeakReferenceMessenger.Default.Send(new PushNotificationReceivedMessage(page));
                }
            }
        }
    }

    private void CreateNotificationChanel()
    {
        if (!OperatingSystem.IsOSPlatformVersionAtLeast("android", 26))
        {
            return;
        }

        var channel = new NotificationChannel(ChannelId, "BSI Notification Chanel", NotificationImportance.Default);
        
        var manager = (NotificationManager?)GetSystemService(NotificationService);
        manager?.CreateNotificationChannel(channel);
    }
}

public partial class App : Application
{
    private readonly SecurityService securityService;
    private readonly UserService userService;

    public App(SecurityService securityService, UserService userService)
    {
        this.securityService = securityService;
        this.userService = userService;

        InitializeComponent();

        MainPage = new NavigationPage(new SplashPage());

        WeakReferenceMessenger.Default.Register<PushNotificationReceivedMessage>(this, async (r, m) =>
        {
            await Shell.Current.GoToAsync(m.Value);
        });
}

解决方案

1. 修复OnNewIntent中Intent.Extras为空的问题

问题根源是方法内误用了类成员Intent,而非传入的参数intent。同时调整PendingIntent的标记,确保Extra数据能被正确更新:

修改OnNewIntent方法

protected override void OnNewIntent(Intent? intent)
{
    base.OnNewIntent(intent);
    // 使用传入的intent参数而非类成员Intent
    HandlePushIntent(intent);
}

修改PendingIntent创建逻辑

// 替换OneShot为UpdateCurrent,确保更新Extra数据
var pendingIntent = PendingIntent.GetActivity(this, MainActivity.NotificationId, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);

2. 修复后台/未运行时无法接收推送的问题

Firebase推送分两种类型:

  • 通知消息:后台/未运行时由系统托盘处理,不会触发OnMessageReceived
  • 数据消息:无论应用状态如何,都会触发OnMessageReceived

调整消息处理逻辑

修改OnMessageReceived,兼容两种消息类型,确保从data字段 fallback 通知内容:

public override void OnMessageReceived(RemoteMessage message)
{
    base.OnMessageReceived(message);
    badgeNumber++;

    // 优先取通知消息内容,没有则从data中获取
    string title = message.GetNotification()?.Title ?? message.Data.TryGetValue("title", out var t) ? t : "系统通知";
    string body = message.GetNotification()?.Body ?? message.Data.TryGetValue("body", out var b) ? b : "您有一条新消息";
    
    SendNotification(body, title, message.Data);
}

推送格式要求

发送推送时,优先使用纯数据消息(仅包含data字段),或者确保混合消息的notification字段符合Firebase后台处理规则,避免系统拦截后不触发OnMessageReceived。

3. 补充冷启动时的参数处理

应用完全未运行时,点击推送会触发OnCreate而非OnNewIntent,需要在OnCreate中添加参数处理逻辑:

在MainActivity中添加通用处理方法

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

    if (ContextCompat.CheckSelfPermission(this, Android.Manifest.Permission.PostNotifications) == Permission.Denied)
    {
        ActivityCompat.RequestPermissions(this, new String[] { Android.Manifest.Permission.PostNotifications }, 1);
    }

    CreateNotificationChanel();
    
    // 处理冷启动时的推送参数
    HandlePushIntent(Intent);
}

private void HandlePushIntent(Intent? intent)
{
    if (intent?.Extras != null)
    {
        foreach (var key in intent.Extras.KeySet() ?? [])
        {
            if (key == "NavigateTo")
            {
                var page = intent.Extras.GetString(key);
                if (Preferences.ContainsKey("NavigateTo"))
                {
                    Preferences.Remove("NavigateTo");
                }
                Preferences.Set("NavigateTo", page);
                // 延迟发送消息,确保Shell初始化完成
                Task.Run(async () =>
                {
                    await Task.Delay(1000);
                    WeakReferenceMessenger.Default.Send(new PushNotificationReceivedMessage(page));
                });
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:17:08