UWP中如何用IBackgroundTask实现通知跳转至外部应用?
我有两个UWP应用app1和app2,已经为app1实现了硬件变更触发的通知功能,代码如下:
private async void Hardware_Change(object sender, RoutedEventArgs e) { var toastContentBuilder = new ToastContentBuilder() .AddArgument("action", "app2") .AddText("open hardware app") .AddText("Please Open Hardware App") .GetToastContent(); var tost = new ToastNotification(toastContentBuilder.GetXml()); ToastNotificationManager.CreateToastNotifier().Show(tost); Application.Current.Exit(); }
我创建了Windows Runtime Component项目实现IBackgroundTask,并在app1项目中引用该组件,代码如下:
public sealed class LancherBackgroundTask : IBackgroundTask { public async void Run(IBackgroundTaskInstance taskInstance) { var uri = new Uri("app2:"); var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = "app2_packge_family_name"; var success = await Launcher.LaunchUriAsync(uri, options); } }
随后在app1的package.appmanifest中注册了该后台任务,配置如下:
<Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundHelper.LancherBackgroundTask"> <BackgroundTasks> <Task Type="pushNotification"/> </BackgroundTasks> </Extension> </Extensions>
目前遇到的问题:无法通过app1的通知启动app2,每次点击通知都会打开app1,且无法确认IBackgroundTask是否正常运行。
需要解决:如何在UWP中正确使用IBackgroundTask?以及如何实现点击app1的通知直接打开app2而不启动app1?
一、修正后台任务的注册与触发逻辑
你当前注册的后台任务类型是pushNotification,但你的场景是Toast通知点击触发后台任务,需要做以下调整:
修改后台任务的注册类型
在package.appmanifest中,将后台任务类型改为toastNotification,匹配Toast点击的触发场景:<Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundHelper.LancherBackgroundTask"> <BackgroundTasks> <Task Type="toastNotification"/> </BackgroundTasks> </Extension> </Extensions>为Toast通知绑定后台任务触发规则
在显示Toast之前,必须将通知的激活类型设置为后台任务,否则点击会默认启动app1。修改Hardware_Change方法:private void Hardware_Change(object sender, RoutedEventArgs e) { var toastContentBuilder = new ToastContentBuilder() .AddArgument("action", "app2") .AddText("open hardware app") .AddText("Please Open Hardware App"); // 设置Toast激活类型为后台任务 var toastContent = toastContentBuilder.GetToastContent(); toastContent.ActivationType = ToastActivationType.Background; var toast = new ToastNotification(toastContent.GetXml()); // 指定要触发的后台任务入口点(必须与manifest中注册的完全一致) toast.ActivationArguments = "BackgroundHelper.LancherBackgroundTask"; ToastNotificationManager.CreateToastNotifier().Show(toast); Application.Current.Exit(); }
二、完善后台任务的实现逻辑
后台任务中必须处理异步操作的延迟,避免系统提前终止任务,同时添加异常捕获便于排查问题:
public sealed class LancherBackgroundTask : IBackgroundTask { private BackgroundTaskDeferral _deferral; // 用于延迟任务结束,等待异步操作完成 public async void Run(IBackgroundTaskInstance taskInstance) { _deferral = taskInstance.GetDeferral(); // 获取延迟对象 try { // 解析Toast传递的参数,确认触发逻辑是否正确 var triggerDetail = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail; if (triggerDetail != null) { var args = ToastArguments.Parse(triggerDetail.Argument); string action = args.Get("action"); if (action == "app2") { var uri = new Uri("app2:"); var options = new LauncherOptions(); // 替换为app2实际的包家族名称(可在app2的manifest打包页查看) options.TargetApplicationPackageFamilyName = "app2_packge_family_name"; bool success = await Launcher.LaunchUriAsync(uri, options); // 可写入本地日志验证执行状态,例如写入LocalFolder下的日志文件 } } } catch (Exception ex) { // 捕获异常并记录,方便排查启动失败或任务未执行的原因 } finally { _deferral.Complete(); // 完成延迟,通知系统任务结束 } } }
- 必须使用
BackgroundTaskDeferral:异步操作未完成时,后台任务会被系统强制终止,这个对象能延长任务生命周期。 - 添加参数解析和日志:可以明确任务是否触发、参数是否正确,便于调试。
三、验证后台任务是否运行
你可以通过两种方式确认任务执行状态:
- 本地日志记录:在后台任务中写入日志到
ApplicationData.Current.LocalFolder,之后打开app1读取日志文件查看执行情况。 - Visual Studio调试:在调试菜单选择「其他调试目标」->「后台任务」,选择对应的
LancherBackgroundTask设置断点,触发Toast点击后查看断点是否命中。
四、确保app2的协议注册正确
要通过app2:协议启动app2,必须在app2的package.appmanifest中注册该协议:
<Extensions> <uap:Extension Category="windows.protocol"> <uap:Protocol Name="app2"> <uap:DisplayName>App2 Protocol</uap:DisplayName> </uap:Protocol> </uap:Extension> </Extensions>
同时确认app2的包家族名称正确:可在app2的manifest「打包」选项卡查看,或通过代码Package.Current.Id.FamilyName获取。
内容的提问来源于stack exchange,提问作者Shiva_Adasule

