FromBluetoothAddressAsync抛出' System.IO.FileNotFoundException'在mscorlib.ni.dll中

时间:2016-06-21 12:36:22

标签: bluetooth windows-10 uwp background-task

我正在开发一个连接到BLE信标的应用程序,为此我使用了BluetoothLEAdvertisementWatcher API。当我收到广告时,我想连接到设备以读取GATT特征。

所以我开始了一个BLEwatcher

    BluetoothLEAdvertisementWatcher watcher;
    watcher.Received += OnAdvertisementReceived;
    watcher.Stopped += OnAdvertisementWatcherStopped;
    watcher.Start();

然后我尝试访问设备

private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
    var address = eventArgs.BluetoothAddress;

    BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
    Debug.WriteLine(device.Name + " - " + device.DeviceId);
    ....

这失败了(在FromBluetoothAddressAsync行)

  

类型' System.IO.FileNotFoundException'的例外情况发生在   mscorlib.ni.dll但未在用户代码中处理

附加信息:系统找不到指定的文件。 (HRESULT异常:0x80070002)

有趣的是:如果我打开系统的蓝牙设备窗口,它可以正常工作!

因此,当我打开蓝牙设备窗口并运行应用程序时,不会抛出错误,当我关闭蓝牙设备窗口时,它会抛出错误。

请注意,它始终会在后台任务中抛出此错误。

显然它适用于build 10.0.10586.218。 我在网上找到了同样问题的人:

  

LUMIA 950,Windows 10,1511,10.0.14332.1001

     

FromIdAsync()抛出异常:' System.IO.FileNotFoundException'   在mscorlib.ni.dll中

     

LUMIA 730,Windows 10,1511,10.0.10586.218

     

FindAllAsync()抛出异常:' System.ArgumentException'

     

LUMIA 920,Windows 10,1511,10.0.10586.218

     

没有错误!

截图: When it fails

When it works

2 个答案:

答案 0 :(得分:2)

问题

此错误是由非UI线程中的FromBluetoothAddressAsync调用引起的。当应用程序尝试访问蓝牙外围设备时,Windows 10需要用户同意。调用FromBluetoothAddressAsync时,Windows会尝试创建同意对话。因为这不是UI线程,所以不能出现同意对话并抛出异常。

<强>解决方案

首先,您应该使BluetoothLEAdvertisementWatcher更具体地针对您正在搜索的外围设备。如果你没有,那么你的应用程序将会看到每一个蓝牙LE设备并提示用户同意每一个 - 一个糟糕的用户体验。

有多种方法可以过滤广告。您可以使用OnAdvertisementReceived中的属性在eventArgs方法中手动执行,也可以在BluetoothLEAdvertisementWatcher本身设置过滤器。例如,要查找具有心率监测器的蓝牙LE设备,请执行以下操作:

watcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(GattServiceUuids.HeartRate);

要在UI线程上进行调用,您需要使用调度程序。您可以使用以下代码设置调度程序:

// Variable in your class
CoreDispatcher dispatcher;

// Init for your class
public MainPage() {
    ...
    // Init the dispatcher, this must be done on the main thread
    this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
    ...
}

然后,当您收到广告时,您可以进行自己的过滤,然后告诉调度员连接到主线程上的蓝牙LE设备。

private async void ConnectToBTDevice(BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
    // This will cause a consent prompt if the user hasn't already consented
    var btDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
}

private bool Filter(BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
    // Return true if the advertisement has the name we're looking for
    return eventArgs.Advertisement.LocalName != null && eventArgs.Advertisement.LocalName.Equals("Peripheral Name");
}

private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {

    // Do our own filtering (for example)
    if(!this.Filter(eventArgs)) return;

    // Connect to the Bluetooth device in the UI (main) thread
    this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.ConnectToBTDevice(eventArgs));
}

答案 1 :(得分:0)

Aren的BLE Windows API是否可爱,以及他们为您提供的好的(未)记录的异常?

如果您打算与设备配对,我不应该使用AdvertisementWatcher。而是使用具有特定选择器的DeviceInformation观察器,用于包含配对和非配对设备的BLE设备。这将提供一个可以与之配对的即用型DeviceInformation对象。

可以在https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing,方案编号8看到示例代码。