如何连接到 Windows 上的蓝牙设备?
How to connect to bluetooth device on Windows?
我想允许用户直接从应用程序连接到配对的音频设备,而不是手动导航到蓝牙设置。
我使用 WinRT Apis 成功列出了所有蓝牙设备:
var result = await DeviceInformation.FindAllAsync(BluetoothDevice.GetDeviceSelector());
// allow user to select a device
DeviceInfo d = await SelectDevice(result);
BluetoothDevice bluetoothDevice = await BluetoothDevice.FromIdAsync(d.Id);
由于 WinRT-Apis 不公开任何“连接”接口(请记住,我想连接设备,因为 Windows 我自己不会与之通信),我正在探索使用 P/Invoke, 所以我在阅读 this answer on superuser.com 后使用以下建议使用 BluetoothSetServiceState
:
// Definitions
private const string bluetoothDll = "bthprops.cpl";
[DllImport(bluetoothDll, ExactSpelling = true, SetLastError = true)]
private static extern uint BluetoothSetServiceState(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO pbtdi, ref Guid pGuidService, uint dwServiceFlags);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern IntPtr BluetoothFindFirstRadio(ref Bluetooth_Find_Radio_Params pbtfrp, out IntPtr phRadio);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern bool BluetoothFindRadioClose(IntPtr findHandle);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern uint BluetoothGetDeviceInfo(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO pbtdi);
private const uint BLUETOOTH_SERVICE_DISABLE = 0;
private const uint BLUETOOTH_SERVICE_ENABLE = 0x00000001;
// Code (using the bluetoothDevice obtained from the WinRT Api)
using(var pointer = GetRadioPointer())
{
BLUETOOTH_DEVICE_INFO deviceInfo = new BLUETOOTH_DEVICE_INFO
{
Address = bluetoothDevice.BluetoothAddress,
dwSize = (uint)Marshal.SizeOf<BLUETOOTH_DEVICE_INFO>()
};
uint result = BluetoothGetDeviceInfo(pointer.Handle, ref deviceInfo);
Guid serviceRef = InTheHand.Net.Bluetooth.BluetoothService.Handsfree;
result = BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 1);
}
// I get the radio like this:
private RadioHandle GetRadioPointer()
{
Bluetooth_Find_Radio_Params pbtfrp = new Bluetooth_Find_Radio_Params();
pbtfrp.Initialize();
IntPtr findHandle = IntPtr.Zero;
try
{
findHandle = BluetoothFindFirstRadio(ref pbtfrp, out IntPtr phRadio);
return new RadioHandle(phRadio);
}
finally
{
if (findHandle != IntPtr.Zero)
{
BluetoothFindRadioClose(findHandle);
}
}
}
但是,我无法让它工作。 BluetoothSetServiceState
总是 returns 87,也就是 ERROR_INVALID_PARAMETER
并且没有任何反应。关于如何解决这个问题的任何想法?使用超级用户中引用的命令行工具-post,它有效...
感谢您的帮助。
为什么您会期望以下行会起作用:
private const string bluetoothDll = "bthprops.cpl";
当 MSDN's page 表示:
DLL: Bthprops.dll
?
我自己偶然发现的,现在可以用了。根据服务是否已处于状态(即使设备已断开连接),您需要先将其关闭。因此,将其关闭并再次打开有效:
BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 0);
BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 1);
事实证明,如果您枚举服务、关闭所有服务并重新打开,您可以连接设备。通过关闭所有来断开连接。当最后一个关闭时,Windows 断开设备。
我想允许用户直接从应用程序连接到配对的音频设备,而不是手动导航到蓝牙设置。
我使用 WinRT Apis 成功列出了所有蓝牙设备:
var result = await DeviceInformation.FindAllAsync(BluetoothDevice.GetDeviceSelector());
// allow user to select a device
DeviceInfo d = await SelectDevice(result);
BluetoothDevice bluetoothDevice = await BluetoothDevice.FromIdAsync(d.Id);
由于 WinRT-Apis 不公开任何“连接”接口(请记住,我想连接设备,因为 Windows 我自己不会与之通信),我正在探索使用 P/Invoke, 所以我在阅读 this answer on superuser.com 后使用以下建议使用 BluetoothSetServiceState
:
// Definitions
private const string bluetoothDll = "bthprops.cpl";
[DllImport(bluetoothDll, ExactSpelling = true, SetLastError = true)]
private static extern uint BluetoothSetServiceState(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO pbtdi, ref Guid pGuidService, uint dwServiceFlags);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern IntPtr BluetoothFindFirstRadio(ref Bluetooth_Find_Radio_Params pbtfrp, out IntPtr phRadio);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern bool BluetoothFindRadioClose(IntPtr findHandle);
[DllImport(bluetoothDll, SetLastError = true)]
private static extern uint BluetoothGetDeviceInfo(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO pbtdi);
private const uint BLUETOOTH_SERVICE_DISABLE = 0;
private const uint BLUETOOTH_SERVICE_ENABLE = 0x00000001;
// Code (using the bluetoothDevice obtained from the WinRT Api)
using(var pointer = GetRadioPointer())
{
BLUETOOTH_DEVICE_INFO deviceInfo = new BLUETOOTH_DEVICE_INFO
{
Address = bluetoothDevice.BluetoothAddress,
dwSize = (uint)Marshal.SizeOf<BLUETOOTH_DEVICE_INFO>()
};
uint result = BluetoothGetDeviceInfo(pointer.Handle, ref deviceInfo);
Guid serviceRef = InTheHand.Net.Bluetooth.BluetoothService.Handsfree;
result = BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 1);
}
// I get the radio like this:
private RadioHandle GetRadioPointer()
{
Bluetooth_Find_Radio_Params pbtfrp = new Bluetooth_Find_Radio_Params();
pbtfrp.Initialize();
IntPtr findHandle = IntPtr.Zero;
try
{
findHandle = BluetoothFindFirstRadio(ref pbtfrp, out IntPtr phRadio);
return new RadioHandle(phRadio);
}
finally
{
if (findHandle != IntPtr.Zero)
{
BluetoothFindRadioClose(findHandle);
}
}
}
但是,我无法让它工作。 BluetoothSetServiceState
总是 returns 87,也就是 ERROR_INVALID_PARAMETER
并且没有任何反应。关于如何解决这个问题的任何想法?使用超级用户中引用的命令行工具-post,它有效...
感谢您的帮助。
为什么您会期望以下行会起作用:
private const string bluetoothDll = "bthprops.cpl";
当 MSDN's page 表示:
DLL: Bthprops.dll
?
我自己偶然发现的,现在可以用了。根据服务是否已处于状态(即使设备已断开连接),您需要先将其关闭。因此,将其关闭并再次打开有效:
BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 0);
BluetoothSetServiceState(pointer.Handle, ref deviceInfo, ref serviceRef, 1);
事实证明,如果您枚举服务、关闭所有服务并重新打开,您可以连接设备。通过关闭所有来断开连接。当最后一个关闭时,Windows 断开设备。