前篇文章我们写了关于Toast的前台激活,那么接下来就讲一讲它的后台激活。当通知出现时并不会出现app的界面,但是app能在后台获取到通知中的信息。
关于xaml和Toast通知架构我们在这里就不再赘述了,请参考前两篇博客。然后我们就来创建通知实例。
1 XmlDocument doc = new XmlDocument(); 2 doc.LoadXml(xml); 3 ToastNotification notification = new ToastNotification(doc); //创建通知 4 DateTime statTime = DateTime.Now.AddSeconds(5); //指定应传递 Toast 通知的时间 5 ScheduledToastNotification recurringToast = new ScheduledToastNotification(doc, statTime); //创建计划的 Toast 通知对象 6 ToastNotificationManager.CreateToastNotifier().AddToSchedule(recurringToast); //向计划中添加 Toast 通知
我们为通知做一个计划,使其在5秒后再进行通知。
接下来我们需要创建一个后台任务,我们先创建一个类库,将其命名为Background,这里需要注意下,这个类库的输出类型必须选择Windows运行时组件才不会爆,感谢Edi.Wang,我也是看到他的博客才知道的。
我们接着创建BackgroundTask类,并在类中写以下代码。
1 public sealed class BackgroundTask : IBackgroundTask 2 { 3 public async void Run(IBackgroundTaskInstance taskInstance) 4 { 5 var deferral = taskInstance.GetDeferral(); 6 ToastNotificationActionTriggerDetail details = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail; 7 if (details != null) 8 { 9 // 是否选择“确定” 10 string arg = details.Argument; 11 if (arg == "ok") 12 { 13 // 获取数据 14 string value = details.UserInput["name"] as string; 15 // 保存数据 16 StorageFolder local = ApplicationData.Current.LocalFolder; 17 JsonObject jsonObj = new JsonObject(); 18 jsonObj.SetNamedValue("name", JsonValue.CreateStringValue(value)); 19 StorageFile dataFile = await local.CreateFileAsync("data.json", CreationCollisionOption.ReplaceExisting); 20 await FileIO.WriteTextAsync(dataFile, jsonObj.Stringify(), Windows.Storage.Streams.UnicodeEncoding.Utf8); 21 } 22 } 23 deferral.Complete(); 24 } 25 }
BackgroundTask继承IBackgroundTask接口并实现,注意 ,后台任务类本身和后台任务项目中的所有其他类都需要是处于 sealed 状态的 public 类。Run方法是一个入口点,当触发指定事件时,将调用该入口点,每个后台任务都需要该方法。接下来的工作就简单了,我们将Toast获取到的值保存到一个Json文件中,当下次启动app时读取这个文件。
那么既然要用到后台任务,那么我们就需要在应用清单里面申明一下。首先打开Package.appxmanifest,切到“申明“选项卡,添加后台任务,属性里面勾选“常规”。
入口点EntryPoint属性与注册后台任务时的入口点相同 (namespace.classname)。
当然我们还可以手动添加这些信息。在application节点下添加以下代码。
<Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="Background.BackgroundTask"> <BackgroundTasks> <Task Type="general" /> </BackgroundTasks> </Extension> </Extensions>
好的,接下来就是后台任务的注册。我们将注册封装为一个方法。
1 public static async Task<BackgroundTaskRegistration> RegisterBackgroundTask(Type taskEntryPoint,string taskName,IBackgroundTrigger trigger) 2 { 3 var status = await BackgroundExecutionManager.RequestAccessAsync(); 4 if (status == BackgroundAccessStatus.Unspecified || status == BackgroundAccessStatus.Denied) 5 { 6 return null; 7 } 8 9 foreach (var cur in BackgroundTaskRegistration.AllTasks) 10 { 11 if (cur.Value.Name == taskName) 12 { 13 cur.Value.Unregister(true); 14 } 15 } 16 17 var builder = new BackgroundTaskBuilder 18 { 19 Name = taskName, 20 TaskEntryPoint = taskEntryPoint.FullName 21 }; 22 23 builder.SetTrigger(trigger); 24 25 BackgroundTaskRegistration task = builder.Register(); 26 27 return task; 28 }
接下来就可以注册了。
1 private async Task RegisterBackgroundTask() 2 { 3 var task = await RegisterBackgroundTask( 4 typeof(Background.BackgroundTask), 5 "BackgroundTask", 6 new ToastNotificationActionTrigger() 7 ); 8 }
后台任务基本完成。接下来,只要在app下次启动时读取那个json文件就行。
1 protected override async void OnNavigatedTo(NavigationEventArgs e) 2 { 3 try 4 { 5 // 读入后台保存的内容 6 StorageFolder local = ApplicationData.Current.LocalFolder; 7 StorageFile dataFile = await local.GetFileAsync("data.json"); 8 if (dataFile == null) return; 9 10 string jsstr = await FileIO.ReadTextAsync(dataFile, Windows.Storage.Streams.UnicodeEncoding.Utf8); 11 12 JsonObject jsobj = null; 13 if (JsonObject.TryParse(jsstr, out jsobj)) 14 { 15 string s = jsobj.GetNamedString("name"); 16 ShowText($"您的姓名是:{s}"); 17 } 18 await dataFile.DeleteAsync(); 19 } 20 catch (Exception ex) 21 { 22 Debug.WriteLine($"文件读取异常:{ex.Message},异常类型:{ex.GetType().Name}。"); 23 } 24 } 25 public void ShowText(string msg) 26 { 27 getInfo.Text = msg; 28 }
至此,这个小demo就完成了。 : )
最后,当然是看看效果喽。。。
启动app。点击通知,关闭app。等待5秒后出现通知。
接下来输入信息,点击确定。
再次打开app时,我们可以看到app里面已经出现了Toast通知的信息了。