Windows Hello 浅尝(3)

继续加油

前面讲到在Task中无法使用DeviceWatcher来枚举蓝牙设备,那么解决方法同样在官方Demo中有

地址: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing

就是需要再注册一个接收枚举事件的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属性,发现这个属性不是很准。。这个问题暂时还没解决。。

现在工程的代码就是按照这个逻辑写的

项目地址: http://git.oschina.net/alwaysking/MyHelloWin

原文地址:https://www.cnblogs.com/alwaysking/p/7258930.html