问题描述
我想扫描并绑定附近运行 WearOS 的 Android 智能手表。我使用 CompanionDeviceManager 按照此处的说明进行操作:https://developer.android.com/guide/topics/connectivity/companion-device-pairing
CompanionDeviceManager 始终显示所有设备类型的列表,包括其他手机、笔记本电脑、蓝牙扬声器和手表(绑定和未配对)。与 Google Wear OS 应用相比,它还使用 CompanionDeviceManager(因为我看到了相同的弹出 UI)并且它始终只显示 Android Watch。
它如何在众多其他蓝牙设备中过滤智能手表?
这是我的代码:
private fun scanLeDevice(enable: Boolean) {
val deviceFilter: BluetoothLeDeviceFilter = BluetoothLeDeviceFilter.Builder()
.build()
// The argument provided in setSingleDevice() determines whether a single
// device name or a list of device names is presented to the user as
// pairing options.
val pairingRequest: AssociationRequest = AssociationRequest.Builder()
.setSingleDevice(false)
.addDeviceFilter(deviceFilter)
.build()
// When the app tries to pair with the Bluetooth device,show the
// appropriate pairing request dialog to the user.
deviceManager.associate(pairingRequest,object : CompanionDeviceManager.Callback() {
override fun onDeviceFound(chooserLauncher: IntentSender) {
startIntentSenderForResult(chooserLauncher,Companion.SELECT_DEVICE_REQUEST_CODE,null,0)
}
override fun onFailure(error: CharSequence?) {
// Handle failure
}
},null)
}
解决方法
请看那篇文章:https://medium.com/@martijn.van.welie/making-android-ble-work-part-1-a736dcd53b02
TL;TR
String[] names = new String[]{"Polar H7 391BB014"};
List<ScanFilter> filters = null;
if(names != null) {
filters = new ArrayList<>();
for (String name : names) {
ScanFilter filter = new ScanFilter.Builder()
.setDeviceName(name)
.build();
filters.add(filter);
}
}
scanner.startScan(filters,scanSettings,scanCallback);
,
备注:这不是完整的答案,因为我不知道每种设备类型的过滤器掩码到底是什么,但至少它可以帮助过滤 Android 智能手表
我反编译了 Google WearOS 应用程序并查看了源文件 FindDeviceControllerSdk26.java。以下是感兴趣的内容:
private static final byte[] BLE_WEAR_MATCH_DATA = { 0,20 };
private static final byte[] BLE_WEAR_MATCH_DATA_LEGACY = { 0,19 };
private static final byte[] BLE_WEAR_MATCH_MASK = { 0,-1 };
private final void showAssociationDialog()
{
Object localObject1 = new ArrayList();
Object localObject3 = new FindDeviceDeviceFilterBuilder();
medium = 1;
Object localObject4 = new ScanFilter.Builder();
byte[] arrayOfByte = BLE_WEAR_MATCH_DATA;
Object localObject2 = BLE_WEAR_MATCH_MASK;
scanFilter = ((ScanFilter.Builder)localObject4).setManufacturerData(224,arrayOfByte,(byte[])localObject2).build();
FindDeviceAssociationRequestBuilder.unbox_addDeviceFilter$ar$ds((FindDeviceDeviceFilterBuilder)localObject3,(List)localObject1);
localObject3 = new FindDeviceDeviceFilterBuilder();
medium = 1;
scanFilter = new ScanFilter.Builder().setManufacturerData(224,BLE_WEAR_MATCH_DATA_LEGACY,(List)localObject1);
if (!deviceWhitelist.shouldShowAllDevices())
{
localObject2 = (GServicesFindDeviceWhitelist)deviceWhitelist;
((GServicesFindDeviceWhitelist)localObject2).initializeIfNecessary();
localObject2 = cachedDeviceWhitelistRegularExpression;
if (!TextUtils.isEmpty((CharSequence)localObject2))
{
localObject3 = new FindDeviceDeviceFilterBuilder();
medium = 0;
namePatternString = ((String)localObject2);
FindDeviceAssociationRequestBuilder.unbox_addDeviceFilter$ar$ds((FindDeviceDeviceFilterBuilder)localObject3,(List)localObject1);
}
}
else
{
localObject2 = new FindDeviceDeviceFilterBuilder();
medium = 0;
namePatternString = ".*";
FindDeviceAssociationRequestBuilder.unbox_addDeviceFilter$ar$ds((FindDeviceDeviceFilterBuilder)localObject2,(List)localObject1);
}
localObject2 = new AssociationRequest.Builder().setSingleDevice(false);
localObject3 = ((List)localObject1).iterator();
while (((Iterator)localObject3).hasNext())
{
localObject1 = (FindDeviceDeviceFilterBuilder)((Iterator)localObject3).next();
if (medium != 0)
{
localObject4 = new BluetoothLeDeviceFilter.Builder();
localObject1 = scanFilter;
if (localObject1 != null) {
((BluetoothLeDeviceFilter.Builder)localObject4).setScanFilter((ScanFilter)localObject1);
}
localObject1 = ((BluetoothLeDeviceFilter.Builder)localObject4).build();
}
else
{
localObject4 = new BluetoothDeviceFilter.Builder();
if (!Platform.stringIsNullOrEmpty(namePatternString)) {
((BluetoothDeviceFilter.Builder)localObject4).setNamePattern(Pattern.compile(namePatternString));
}
localObject1 = ((BluetoothDeviceFilter.Builder)localObject4).build();
}
((AssociationRequest.Builder)localObject2).addDeviceFilter((DeviceFilter)localObject1);
}
localObject1 = ((AssociationRequest.Builder)localObject2).build();
viewClient.hideRefreshButton();
cwEventLogger.incrementCounter(Counter.COMPANION_PAIR_CDM_ASSOCIATE_REQUEST);
companionDeviceManager.associate((AssociationRequest)localObject1,deviceManagerCallback,null);
}
然后我重写我的扫描函数如下
private val BLE_WEAR_MATCH_DATA = byteArrayOf(0,20)
private val BLE_WEAR_MATCH_DATA_LEGACY = byteArrayOf(0,19)
private val BLE_WEAR_MATCH_MASK = byteArrayOf(0,-1)
private fun scanLeDevice(enable: Boolean) {
val scanFilter = ScanFilter.Builder().setManufacturerData(224,BLE_WEAR_MATCH_MASK).build()
val deviceFilter: BluetoothLeDeviceFilter = BluetoothLeDeviceFilter.Builder()
.setScanFilter(scanFilter)
.setNamePattern(Pattern.compile(".*"))
.build()
// The argument provided in setSingleDevice() determines whether a single
// device name or a list of device names is presented to the user as
// pairing options.
val pairingRequest: AssociationRequest = AssociationRequest.Builder()
.setSingleDevice(false)
.addDeviceFilter(deviceFilter)
.build()
// When the app tries to pair with the Bluetooth device,show the
// appropriate pairing request dialog to the user.
deviceManager.associate(pairingRequest,object : CompanionDeviceManager.Callback() {
override fun onDeviceFound(chooserLauncher: IntentSender) {
startIntentSenderForResult(chooserLauncher,Companion.SELECT_DEVICE_REQUEST_CODE,null,0)
}
override fun onFailure(error: CharSequence?) {
// Handle failure
}
},null)
}
我希望有人能帮助描述这些面具代表什么,然后我会帮助更新以完整地回答这个问题。
私有值 BLE_WEAR_MATCH_DATA = byteArrayOf(0,20)
私有值 BLE_WEAR_MATCH_DATA_LEGACY = byteArrayOf(0,19)
私有值 BLE_WEAR_MATCH_MASK = byteArrayOf(0,-1)
,尝试重新启动您的设备。只是第一次,因为一旦它在 SmartWatch 应用程序列表中,您可能不会遇到相同的问题。