FromBluetoothAddressAsync抛出';System.IO.FileNotFoundException';在mscorlib.ni.dll中
我正在开发一个连接BLE信标的应用程序,为此我使用BluetoothLEAdvertisementWatcher API。当我收到广告时,我想连接到设备以阅读GATT特征 所以我开了一个观察者FromBluetoothAddressAsync抛出';System.IO.FileNotFoundException';在mscorlib.ni.dll中,bluetooth,windows-10,uwp,background-task,Bluetooth,Windows 10,Uwp,Background Task,我正在开发一个连接BLE信标的应用程序,为此我使用BluetoothLEAdvertisementWatcher API。当我收到广告时,我想连接到设备以阅读GATT特征 所以我开了一个观察者 BluetoothLEAdvertisementWatcher watcher; watcher.Received += OnAdvertisementReceived; watcher.Stopped += OnAdvertisementWatcherStopped; w
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)
有趣的是:如果我打开系统的bluetooth devices(蓝牙设备)窗口,它可以正常工作
因此,当我打开bluetooth devices(蓝牙设备)窗口并运行应用程序时,不会抛出错误,当我关闭bluetooth devices(蓝牙设备)窗口时,会抛出错误
请注意,它总是在后台任务中抛出此错误
显然,它在构建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
没有错误
截图:
BLE Windows API是否可爱,以及它们为您提供的良好(未)记录的异常情况 我想,如果你想和一个设备配对,就不应该使用AdvertisementWatcher。相反,对于包含配对和非配对设备的可移动设备,请使用具有特定选择器的DeviceInformation watcher。这将提供一个可与之配对的即用设备信息对象
示例代码可以在第8个场景中看到。BLE Windows API不是很可爱吗?它们给您提供了很好的(未记录的)异常 我想,如果你想和一个设备配对,就不应该使用AdvertisementWatcher。相反,对于包含配对和非配对设备的可移动设备,请使用具有特定选择器的DeviceInformation watcher。这将提供一个可与之配对的即用设备信息对象
示例代码可在场景8中看到。问题 此错误是由在非UI线程中调用
FromBluetoothAddressAsync
引起的。当应用程序尝试访问蓝牙外围设备时,Windows 10需要用户同意。调用FromBluetoothAddressAsync
时,Windows会尝试创建同意对话。由于这不是UI线程,因此无法显示同意对话框并引发异常
解决方案
首先,您应该使BluetoothLEAdvertisementWatcher更具体地针对您正在搜索的外围设备。如果你不这样做,那么你的应用程序将看到每一个蓝牙LE设备,并在每一个设备上提示用户同意-一个糟糕的用户体验
有多种方法可以过滤广告。您可以使用eventArgs
中的属性,在您的onadvertisimentreceived
方法中手动执行此操作,也可以在BluetoothLEAdvertisementWatcher
本身中设置过滤器。例如,要查找具有心率监视器的蓝牙LE设备,请执行以下操作:
watcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(GattServiceUuids.HeartRate);
要在UI线程上进行调用,需要使用调度程序。您可以使用以下代码设置dispatcher:
// 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));
}
问题 此错误是由在非UI线程中调用
FromBluetoothAddressAsync
引起的。当应用程序尝试访问蓝牙外围设备时,Windows 10需要用户同意。调用FromBluetoothAddressAsync
时,Windows会尝试创建同意对话。由于这不是UI线程,因此无法显示同意对话框并引发异常
解决方案
首先,您应该使BluetoothLEAdvertisementWatcher更具体地针对您正在搜索的外围设备。如果你不这样做,那么你的应用程序将看到每一个蓝牙LE设备,并在每一个设备上提示用户同意-一个糟糕的用户体验
有多种方法可以过滤广告。您可以使用eventArgs
中的属性,在您的onadvertisimentreceived
方法中手动执行此操作,也可以在BluetoothLEAdvertisementWatcher
本身中设置过滤器。例如,要查找具有心率监视器的蓝牙LE设备,请执行以下操作:
watcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(GattServiceUuids.HeartRate);
要在UI线程上进行调用,需要使用调度程序。您可以使用以下代码设置dispatcher:
// 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));
}
连接问题通过我标记为答案的注释解决,首先配对,然后使用FromIdAsync。不过,我也使用了其中的一部分来修复它,谢谢。连接问题通过我标记为答案的评论解决了,首先配对,然后使用FromIdAsync。不过,我也使用了其中的一部分来修复它,非常感谢。