如何按类型过滤附近的蓝牙设备

问题描述

我想扫描并绑定附近运行 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)
}

enter image description here

解决方法

请看那篇文章: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 应用程序列表中,您可能不会遇到相同的问题。