ERROR_ACCESS_DENIED while using BluetoothLEAdverti

2019-08-16 12:56发布

问题:

I'm trying to use BluetoothLEAdvertisementWatcher to detect BLE advertising packets. However upon calling Start() the watcher object always aborts with 'Access is denied' error.

Code is pretty simple and is as below:

auto filter = BluetoothLEAdvertisementFilter();
auto advert = BluetoothLEAdvertisement();
advert.LocalName(L"Greeny");
filter.Advertisement(advert);
m_watcher.AdvertisementFilter(filter);

// setup event handlers
m_watcher.Received({ this, &MainPage::OnAdvertisementRecieved });
m_watcher.Stopped({ this, &MainPage::OnAdvertisementStopped });

m_watcher.Start();

m_watcher is a class member declared as:

BluetoothLEAdvertisementWatcher m_watcher;

The event handlers are declared as:

void MainPage::OnAdvertisementRecieved(BluetoothLEAdvertisementWatcher const& watcher, BluetoothLEAdvertisementReceivedEventArgs const& args)
{
    OutputDebugString(L"Bluetooth advertisement received!\n");
}

void MainPage::OnAdvertisementStopped(Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher const & watcher, Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcherStoppedEventArgs const & args)
{
    OutputDebugString(L"Advertising stopped\n");
}

This code is pretty similar to the sample code in the SDK which is in C#. I'm trying to do the same in C++ as I'm more familiar with it.

Any idea what could be going wrong? I tried removing all the filters, that is, using the watcher in its default state. That too gives the same error. Removing the event handlers also results in the same error.

Thanks in advance.

EDIT: Changed the title adding ERROR_ACCESS_DENIED.

EDIT2: The exact location where the error occurs is: onecoreuap\drivers\wdm\bluetooth\user\winrt\advertisement\bluetoothleadvertisementwatcher.cpp(1510)\Windows.Devices.Bluetooth.dll!0F479314: (caller: 0F47AD40) Exception(2) tid(2c1c) 80070005 Access is denied.

回答1:

It is good idea to set m_watcher.ScanningMode = Active; before calling Start();

Also, if you develop non UWP (classic) application you should be sure that WinRT initialized correctly. As WinRT based on COM technologyy it is good to initialize WinRT before any other call to COM is made. However some applications based on any frameworks (for example, MFC, Delphi VCL or others) may initialize COM internally with custom parameters. In this case it is good idea to call RoInitialize(RO_INIT_MULTITHREADED) from separate thread.

Microsoft write that WinRT must be initialized with RO_INIT_MULTITHREADED flag. However our experience shows that usingother flags also works but all the WinRT events will be executed synchronous then. Not good for work.

And finally if you develop UWP application do not forget to set application device capabilities as described there: https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/how-to-specify-device-capabilities-for-bluetooth

This is important thing.



回答2:

Solution Explorer -> Package.appxmanifest -> Capabilities -> Bluetooth (check)