如何以编程方式移除锁屏状态下接收的UWP Toast通知?
解决锁屏来电场景Toast通知无法在应用激活时自动隐藏的问题
我完全懂这种困扰——带循环音频的来电场景Toast,在锁屏接收后,就算打开应用也没法自动消失,还一直响铃,确实太影响使用体验了。咱们来拆解问题,一步步解决:
问题根源
你用了scenario="incomingCall"的Toast场景,这类通知系统会赋予更高的优先级,锁屏触发后,常规的_ToastNotifier.Hide(notification)和ToastNotificationManager.History.Remove(tag)可能因为系统状态(锁屏→前台的切换延迟)而失效,加上循环音频是系统托管的,也需要同步处理才能停止。
具体解决方案
1. 确保通知发送时设置唯一Tag
首先,发送通知时必须指定Tag属性,这是后续精准定位并移除通知的关键:
var toastContent = new ToastContent() { Scenario = ToastScenario.IncomingCall, Audio = new ToastAudio() { Src = new Uri("ms-winsoundevent:Notification.Looping.Call"), Loop = true, Silent = false }, // 填充你的通知内容(标题、按钮等) }; var toastNotification = new ToastNotification(toastContent.GetXml()); toastNotification.Tag = "unique-incoming-call-tag"; // 给通知设置唯一标识 ToastNotificationManager.CreateToastNotifier().Show(toastNotification);
2. 在应用激活时执行清除逻辑
在应用从后台/锁屏切换到前台时,触发通知清除和音频停止操作。建议在主页面的Activated事件或者App.xaml.cs的激活方法中处理:
private async void MainPage_Activated(object sender, WindowActivatedEventArgs e) { // 仅当应用从非激活状态切换到激活时执行 if (e.WindowActivationState != WindowActivationState.Deactivated) { string targetTag = "unique-incoming-call-tag"; // 对应之前设置的Tag var notifier = ToastNotificationManager.CreateToastNotifier(); // 如果你保存了发送时的ToastNotification实例,先尝试隐藏 if (YourSavedNotificationInstance != null) { notifier.Hide(YourSavedNotificationInstance); } // 关键:添加短延迟,等待系统完成锁屏→前台的状态同步 await Task.Delay(150); // 从通知历史中移除指定Tag的通知 ToastNotificationManager.History.Remove(targetTag); // 可选:如果音频仍未停止,用静音音频打断循环(应急方案) var mediaPlayer = new MediaPlayer(); mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Silent.wav")); mediaPlayer.Play(); await Task.Delay(50); mediaPlayer.Pause(); } }
3. 额外注意事项
- 不要省略延迟操作:刚激活应用时,系统还在处理锁屏状态的资源释放,立即调用清除API大概率无效,100-200ms的延迟刚好适配状态切换节奏。
- 保存通知实例:如果可以,在发送通知时把
ToastNotification实例保存到全局变量中,后续调用Hide()会更直接有效。 - 测试边界情况:比如应用在后台时收到锁屏通知,再激活应用,确保逻辑依然生效。
这个方案通过状态同步延迟+双重清除(Hide+History.Remove)的组合,能有效解决锁屏来电通知无法自动隐藏的问题,同时处理循环音频的停止问题。
内容的提问来源于stack exchange,提问作者Lance
相关产品推荐
相关产品推荐

