继续加油
前面讲到在Task中无法使用DeviceWatcher来枚举蓝牙设备,那么解决方法同样在官方Demo中有
就是需要再注册一个接收枚举事件的Task,那么步骤其实和注册一个接收Windows Hello事件的Task的方法是一样的
string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" }; DeviceWatcherEventKind[] triggerEventKinds = { DeviceWatcherEventKind.Add, DeviceWatcherEventKind.Remove, DeviceWatcherEventKind.Update }; DeviceWatcher deviceWatcher = null; deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:="{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}")", requestedProperties, DeviceInformationKind.AssociationEndpoint); DeviceWatcherTrigger deviceWatcherTrigger = deviceWatcher.GetBackgroundTrigger(triggerEventKinds); BackgroundTaskBuilder taskBuilder; taskBuilder = new BackgroundTaskBuilder(); taskBuilder.Name = strTaskPerName + g_strTaskPostName; taskBuilder.TaskEntryPoint = strEntryPoint; taskBuilder.SetTrigger(deviceWatcherTrigger); BackgroundTaskRegistration backgroundTaskRegistration = taskBuilder.Register();
对应的Task的Run函数里面是这样的
public void Run(IBackgroundTaskInstance taskInstance) { Debug.WriteLine("BackgroundDeviceWatcher.Run called"); uint eventCount = 0; ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; DeviceWatcherTriggerDetails triggerDetails = (DeviceWatcherTriggerDetails)taskInstance.TriggerDetails; Debug.WriteLine(String.Format("Trigger contains {0} events", triggerDetails.DeviceWatcherEvents.Count)); foreach (DeviceWatcherEvent e in triggerDetails.DeviceWatcherEvents) { switch (e.Kind) { case DeviceWatcherEventKind.Add: Debug.WriteLine("Add: " + e.DeviceInformation.Id); break; case DeviceWatcherEventKind.Update: Debug.WriteLine("Update: " + e.DeviceInformationUpdate.Id); break; case DeviceWatcherEventKind.Remove: Debug.WriteLine("Remove: " + e.DeviceInformationUpdate.Id); break; } }; if (null != settings.Values["eventCount"] && settings.Values["eventCount"].GetType() == typeof(uint)) { eventCount = (uint)settings.Values["eventCount"]; } // Add the number of events for this trigger to the number of events received in the past eventCount += (uint)triggerDetails.DeviceWatcherEvents.Count; Debug.WriteLine(eventCount + " events processed for lifetime of trigger"); settings.Values["eventCount"] = eventCount; }
还是很简单的是吧!
我一开始做了个测试,就是这两个Task任务我写在同一个工程里,代码如下
public sealed class MyHelloWinTask : IBackgroundTask { static int i = 0; public void Run(IBackgroundTaskInstance taskInstance) { i++; } }
我发现这两个Task是同一个进程,并且当变量 i 是static变量的时候是可以累加的,所以我天真的以为注册的两个Task是同一个进程的不同的 MyHelloWinTask 实例对象,所以只要是静态对象那么数据就可以在两个Task之间共享。
所以我的做法就是
public sealed class MyHelloWinTask : IBackgroundTask { static private List DeviceList = new List(); public void Run(IBackgroundTaskInstance taskInstance) { // 标记任务延迟完成 var deferral = taskInstance.GetDeferral(); // 可以根据注册Task的时候的名字判断是什么事件 if (String.Equals(taskInstance.Task.Name, "MyHelloWinTask_Unlock")) { // 解锁设备就去解锁 从List中获取所有设备和解锁设备进行比较 } else { 收到的数据加入List DeviceList } // 标记任务完成了 deferral.Complete(); } }
这样子就可能承接 上一篇中的逻辑继续下去,并且在我写好对应代码之后,事情也是按照这个预期进行的。
当我以为这个项目完成的时候,我突然发现他失灵了。
我再次探究之后发现,如果你的界面进程开着,或者使用VS在调试的时候,这两个Task的确是同一个进程,但是一旦你把桌面进程关闭了,或者是在你开机的时候他们必然是两个独立的进程。所以就无法简单的通过static变量来通讯了。
于是就想解决方法啦,无非就是进程间的通讯。于是我就去找UWP怎么进行进程间的通讯啊什么什么的,找了好久才漠然回首到其实可以使用 DeviceConfigurationData 通讯的,反正现在DeviceConfigurationData存的是json数据也不差多加个变量,DeviceConfigurationData 的长度最多可以是4K
于是就多加了个CanUnlok变量。
思路就又变了
在DeviceEumTask启动的时候将所有解锁设备的UnLock设为False,然后当枚举到一个蓝牙设备的时候检查有没有对应的解锁设备,有对应的解锁设备那么这个解锁设备的CanUnlock就设置为True,如果接到设备更新或者删除事件那么更新对应的CanUnlock
在LoginTask中当接收到解锁事件的时候枚举所有解锁设备看他们的属性中Unlock是否为True,为Ture就直接使用它解锁Windows。
但是这个逻辑也有问题,那就是配对的蓝牙设备即使设备不在旁边也总是能枚举到,没配对的设备Task又枚举不到。
我研究了设备的IsConnected属性,发现这个属性不是很准。。这个问题暂时还没解决。。
现在工程的代码就是按照这个逻辑写的