如何在Xamarin iOS中实现指定时间本地通知触发时播放闹铃音效
Xamarin iOS 本地通知触发闹铃音效及dismiss时自动停止实现方案
实现核心说明
不要使用iOS系统自带的通知音效,系统管控的通知音效无法通过应用代码手动停止,必须自行通过AVAudioPlayer实现音效的播放和停止控制。
1. 前置配置
- 在Info.plist中添加必要权限:
- 通知权限:添加键
NSUserNotificationUsageDescription,值自定义为「需要获取通知权限以推送闹铃提醒」 - 后台音频权限(支持应用后台/被杀死时仍能播放音效):添加键
UIBackgroundModes,类型为数组,包含值audio
- 通知权限:添加键
- 引入依赖命名空间:
using UserNotifications; using AVFoundation; using Foundation;
2. 全局音效管理器实现
定义全局单例类管理音频播放器,避免播放器被GC回收导致播放中断:
public static class AudioPlayerManager { private static AVAudioPlayer _audioPlayer; // 初始化音频播放器,参数为闹铃音效文件的本地路径 public static void Init(string audioFilePath) { // 配置音频会话为播放模式,支持后台播放 var session = AVAudioSession.SharedInstance(); session.SetCategory(AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.MixWithOthers); session.SetActive(true); var audioUrl = NSUrl.FromFilename(audioFilePath); _audioPlayer = AVAudioPlayer.FromUrl(audioUrl); _audioPlayer.NumberOfLoops = -1; // 设置为无限循环播放,直到手动停止 _audioPlayer.PrepareToPlay(); } // 播放闹铃 public static void PlayAlarm() { _audioPlayer?.Play(); } // 停止闹铃 public static void StopAlarm() { if (_audioPlayer != null && _audioPlayer.Playing) { _audioPlayer.Stop(); _audioPlayer.CurrentTime = 0; // 重置播放进度到开头 } } }
3. AppDelegate 初始化配置
在FinishedLaunching方法中申请通知权限、注册通知代理、初始化音效管理器:
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { // 申请通知权限 UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge, (granted, error) => { if (granted) { // 绑定自定义通知代理 UNUserNotificationCenter.Current.Delegate = new CustomNotificationDelegate(); } }); // 初始化音效管理器,将闹铃文件放入iOS项目Resources目录,生成操作设置为BundleResource var alarmPath = NSBundle.MainBundle.PathForResource("你的闹铃文件名", "mp3"); AudioPlayerManager.Init(alarmPath); return base.FinishedLaunching(application, launchOptions); }
4. 本地通知发送逻辑
// 调用示例:在需要触发闹铃的位置调用该方法发送通知 public void ScheduleAlarmNotification(DateTime alarmTime, string title, string content) { var notificationContent = new UNMutableNotificationContent { Title = title, Body = content, CategoryIdentifier = "ALARM_NOTIFICATION" // 注意:不要设置Sound属性,我们自行控制音效播放 }; // 配置通知触发时间 var triggerDate = alarmTime.AddSeconds(-1); // 提前1秒触发,对齐音效播放时间 var trigger = UNCalendarNotificationTrigger.CreateTrigger(triggerDate, false); // 发送通知请求 var requestId = Guid.NewGuid().ToString(); var request = UNNotificationRequest.FromIdentifier(requestId, notificationContent, trigger); UNUserNotificationCenter.Current.AddNotificationRequest(request, null); // 同步安排闹铃播放任务,和通知触发时间对齐 var delay = (long)(alarmTime - DateTime.Now).TotalMilliseconds * 1000000; DispatchQueue.MainQueue.DispatchAfter(new DispatchTime(DispatchTime.Now, delay), () => { AudioPlayerManager.PlayAlarm(); }); }
5. 自定义通知代理,监听dismiss事件
实现UNUserNotificationCenterDelegate,监听用户对通知的操作,用户dismiss通知时自动停止音效:
public class CustomNotificationDelegate : UNUserNotificationCenterDelegate { // 应用在前台时收到通知的回调 public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler) { // 前台展示通知弹窗 completionHandler(UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Badge); // 播放闹铃 AudioPlayerManager.PlayAlarm(); } // 用户对通知执行操作(点击、dismiss)的回调 public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler) { // 用户dismiss通知时停止闹铃 if (response.ActionIdentifier == UNNotificationAction.DismissActionIdentifier) { AudioPlayerManager.StopAlarm(); } // 用户点击通知进入应用时也停止闹铃 else if (response.ActionIdentifier == UNNotificationAction.DefaultActionIdentifier) { AudioPlayerManager.StopAlarm(); // 此处可添加跳转应用内对应页面的逻辑 } completionHandler(); } }
注意事项
- 闹铃音频文件必须放入iOS项目的
Resources目录,且将文件的生成操作设置为BundleResource,否则会找不到文件 - 应用被杀死状态下用户操作通知时,系统会自动唤醒应用执行
DidReceiveNotificationResponse中的停止逻辑,无需额外处理 - iOS 15+对后台运行权限限制更严格,若出现后台无法播放音效的问题,请检查
UIBackgroundModes配置是否正确
内容的提问来源于stack exchange,提问作者Dhruv Gohil
相关产品推荐
相关产品推荐

