我正在开发一个连接到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
没有错误!
答案 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看到示例代码。