MAUI 8应用后台时自定义Firebase云消息通知音效问题
问题背景
需要在MAUI 8应用未启动时,自定义Firebase Cloud Messaging(FCM)推送通知的音效。当前后端使用Firebase Admin发送通知,MAUI端通过Plugin.Firebase处理通知。
后端发送通知代码
await FirebaseMessaging.DefaultInstance.SendAsync(new Message() { Token = fcmtoken, Notification = new Notification() { Title = title, Body = body } });
MAUI 8应用处理通知代码
FirebaseCloudMessagingImplementation.ShowLocalNotificationAction = notification => { var intent = PackageManager.GetLaunchIntentForPackage(PackageName); intent.PutExtra(FirebaseCloudMessagingImplementation.IntentKeyFCMNotification, notification.ToBundle()); intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.Immutable | PendingIntentFlags.UpdateCurrent); var builder = new NotificationCompat.Builder(this, channelId) .SetSmallIcon(Android.Resource.Drawable.SymDefAppIcon) .SetContentTitle(notification.Title) .SetContentText(notification.Body) .SetPriority(NotificationCompat.PriorityDefault) .SetAutoCancel(true); System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow(); var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Notify(123, builder.SetContentIntent(pendingIntent).Build()); };
当前问题
应用运行时,通知通过自定义NotificationChannel推送,可自定义音效;但应用未启动时,通知由Google Play Services自动创建的默认渠道推送,无法自定义音效,如何覆盖应用未启动时的通知行为?
核心原因:应用未启动时,FCM通知消息直接由Google Play Services处理,不会触发MAUI中设置的ShowLocalNotificationAction回调。需通过以下两种方式解决:
1. 强制指定自定义通知渠道
确保FCM消息使用预先创建的自定义渠道,该渠道需在应用首次启动时就完成初始化。
步骤1:在MAUI Android项目中创建自定义通知渠道
在MainApplication.cs的OnCreate方法中添加渠道初始化逻辑:
protected override void OnCreate() { base.OnCreate(); InitializeNotificationChannel(); } private void InitializeNotificationChannel() { if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { const string channelId = "custom_fcm_channel"; // 与通知Builder中的channelId保持一致 const string channelName = "FCM推送通知"; const string channelDesc = "接收FCM推送的自定义渠道"; var importance = NotificationImportance.Default; // 创建渠道并设置自定义音效 var channel = new NotificationChannel(channelId, channelName, importance) { Description = channelDesc, Sound = Uri.Parse($"android.resource://{PackageName}/{Resource.Raw.custom_notification_sound}") }; // 配置音效的音频属性 var audioAttributes = new AudioAttributes.Builder() .SetContentType(AudioContentType.Sonification) .SetUsage(AudioUsageKind.Notification) .Build(); channel.SetAudioAttributes(audioAttributes); var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.CreateNotificationChannel(channel); } }
注意:将custom_notification_sound替换为你放在Resources/Raw目录下的音频文件名,且需将该文件的Android资源类型设置为AndroidResource。
步骤2:后端发送消息时指定渠道ID
修改后端FCM消息发送代码,添加AndroidConfig指定自定义渠道ID:
await FirebaseMessaging.DefaultInstance.SendAsync(new Message() { Token = fcmtoken, Notification = new Notification() { Title = title, Body = body }, Android = new AndroidConfig() { Notification = new AndroidNotification() { ChannelId = "custom_fcm_channel" // 与MAUI中创建的渠道ID一致 } } });
此方式下,即使应用未启动,Google Play Services也会使用指定的自定义渠道展示通知,自动继承渠道的音效设置。
2. 改用数据消息完全接管通知逻辑(更灵活)
将后端发送的通知消息改为数据消息,数据消息会被FCM传递到MAUI的MessageReceived回调,无论应用是否启动都会触发(需配置后台服务支持)。
后端发送数据消息示例
await FirebaseMessaging.DefaultInstance.SendAsync(new Message() { Token = fcmtoken, Data = new Dictionary<string, string>() { {"title", title}, {"body", body}, {"sound", "custom_notification_sound"} } });
MAUI中处理数据消息
在MainApplication.cs中注册消息接收回调,自行处理通知展示:
FirebaseCloudMessagingImplementation.MessageReceived += (sender, e) => { if (e.Data.TryGetValue("title", out var title) && e.Data.TryGetValue("body", out var body)) { ShowCustomLocalNotification(title, body); } }; private void ShowCustomLocalNotification(string title, string body) { var intent = PackageManager.GetLaunchIntentForPackage(PackageName); intent.PutExtra(FirebaseCloudMessagingImplementation.IntentKeyFCMNotification, new Bundle()); intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.Immutable | PendingIntentFlags.UpdateCurrent); const string channelId = "custom_fcm_channel"; var builder = new NotificationCompat.Builder(this, channelId) .SetSmallIcon(Android.Resource.Drawable.SymDefAppIcon) .SetContentTitle(title) .SetContentText(body) .SetPriority(NotificationCompat.PriorityDefault) .SetAutoCancel(true) .SetContentIntent(pendingIntent); var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Notify(123, builder.Build()); }
这种方式下,所有消息都会经过你的代码处理,完全控制通知的音效、样式等属性,不受应用运行状态影响。
关键注意事项
- 通知渠道一旦创建,核心属性(如音效)无法修改,只能删除后重建,因此首次创建时需配置正确。
- 自定义音效需符合Android格式要求(如MP3、WAV),文件大小不宜过大。
- Android 13及以上需在
AndroidManifest.xml中添加POST_NOTIFICATIONS权限。
内容的提问来源于stack exchange,提问作者furybg

