如何使用UWP应用检测Windows 10中其他应用触发的Toast通知
UWP Toast通知监听功能修复方案
1. 补充应用清单权限配置
仅在系统层面开启通知权限无法满足监听要求,必须在项目的Package.appxmanifest文件中显式声明通知监听能力:
- 在根节点
<Package>中补充uap7命名空间声明:
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7" IgnorableNamespaces="uap uap7">
- 在
<Capabilities>节点下添加监听权限:
<Capabilities> <uap7:Capability Name="userNotificationListener" /> </Capabilities>
2. 修复现有代码逻辑缺陷
你当前的代码存在三处核心问题导致无法拿到通知列表更新:
- 授权请求
RequestAccessAsync不需要放在循环内重复调用,仅需在功能首次触发时调用一次即可,重复调用会导致接口返回异常缓存 - 当检测到通知数为0时直接执行
break退出了循环,后续不会再执行检测逻辑,自然无法捕获新弹出的通知 - 无间隔的高频循环会占用大量UI线程资源,同时会触发系统接口限流,导致返回的通知列表长期不变
3. 推荐实现方案:使用系统事件替代轮询
UserNotificationListener自带NotificationChanged事件,会在系统通知状态变更时主动触发,无需主动轮询,效率更高且不会遗漏通知,参考实现代码如下:
// 将listener声明为类全局变量,避免被GC回收导致事件失效 private Windows.UI.Notifications.Management.UserNotificationListener _notificationListener; private Windows.Media.Playback.MediaPlayer _mediaPlayer = new Windows.Media.Playback.MediaPlayer(); private bool _isListening = false; private async void Button_Click(object sender, RoutedEventArgs e) { if (_isListening) return; switchStatus = "ON"; this.Status.Text = switchStatus; _notificationListener = Windows.UI.Notifications.Management.UserNotificationListener.Current; var accessStatus = await _notificationListener.RequestAccessAsync(); switch (accessStatus) { case Windows.UI.Notifications.Management.UserNotificationListenerAccessStatus.Allowed: // 绑定通知变更事件 _notificationListener.NotificationChanged += OnNotificationChanged; _isListening = true; break; case Windows.UI.Notifications.Management.UserNotificationListenerAccessStatus.Denied: // 自定义逻辑提示用户前往系统设置开启通知访问权限 break; case Windows.UI.Notifications.Management.UserNotificationListenerAccessStatus.Unspecified: // 自定义逻辑引导用户重新授权 break; } } private async void OnNotificationChanged(Windows.UI.Notifications.Management.UserNotificationListener sender, Windows.UI.Notifications.Management.UserNotificationChangedEventArgs args) { // 仅处理新添加的Toast通知事件 if (args.ChangeKind != Windows.UI.Notifications.Management.UserNotificationChangedKind.Added) return; var toastNotifications = await sender.GetNotificationsAsync(Windows.UI.Notifications.NotificationKinds.Toast); if (toastNotifications.Count <= 0) return; // 如需操作UI元素,需调度到UI线程执行 await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { try { _mediaPlayer.Source = Windows.Media.Core.MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/audio.mp3")); _mediaPlayer.Play(); playing = true; } catch (Exception) { // 自定义异常处理逻辑 } }); }
4. 额外检查项
- 确认项目Assets目录下的audio.mp3文件属性:「生成操作」设置为「内容」,「复制到输出目录」设置为「如果较新则复制」
- 如需过滤掉已经存入通知中心的历史通知,仅捕获正在弹出的Toast,可以过滤
UserNotification的DismissalTime属性,仅保留DismissalTime == null的活跃通知
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

