【问题标题】:Android BLE. How to filter Scan by raw advertising data安卓 BLE。如何通过原始广告数据过滤扫描
【发布时间】:2020-02-06 13:36:20
【问题描述】:

我必须构建一个 Android 应用程序,该应用程序在一种设备上读取信息,该设备仅在过滤后才会在扫描时显示(一般扫描不会显示)。该设备类似于信标,因此它只发布数据,其中包含我想要的广告信息(它不可连接)。 制造商给我的过滤器是原始数据。即:

0x02010612435542

我无法按名称过滤它,因为该设备不会宣传它的名称。我也不能通过MAC Address 进行操作,因为该应用程序以前不会知道设备的地址(它将是许多此类设备)。

nrfConnect 应用程序做得很好,如下所示:

App 上的过滤器名称为:

按原始广告数据过滤

而且,当被过滤时,这就是设备在应用程序上的显示方式:

所以,事情就是这样。我无法按名称或MAC Address 过滤。

Java(android/ble 标准库)中用于过滤的其他选项有:

    ScanFilter scanFilter1 = new ScanFilter.Builder().setManufacturerData(manufacturerId, manufacturerData).build();
    ScanFilter scanFilter2 = new ScanFilter.Builder().setServiceData(serviceDataUuid, serviceData).build();
    ScanFilter scanFilter2 = new ScanFilter.Builder().setServiceUuid(serviceUuid).build();

我有制造商提供的 UUID。这是

B54ADC00-67F9-11D9-9669-0800200C9A66

但是,正如制造商所说,UUID 用于扫描 iOS,无法在 Android 上运行(经过测试,确实如此)。

所以,我剩下上面的 scanFilters 的 2 个选项。

我有这样的知识:“制造商数据在原始广告数据中进行广告,可以通过 nrfConnect 应用程序找到。制造商数据的前两个字节是制造商 ID,与 setManufacturerData() 一起使用筛选”。 我什至能够检索原始制造商广告数据(使用setDeviceAddress() 过滤器(用于测试,使用测试设备,因为正如我所说,应用程序以前不会知道 MACAddresses),我得到了类似这样的东西:

0X020106124355420000080390BECB49400400CB500CF

很抱歉这个问题太长了,但我尽量做到最完整。

我已经尝试了所有可以使用这些 scanFilter 方法的方法,但无法让它发挥作用。

有人知道如何实现吗?我为此疯狂了一个多月。

提前致谢!

【问题讨论】:

    标签: java android bluetooth-lowenergy


    【解决方案1】:

    我终于用两种方法弄明白了。

    1. 使用 ScanCallback

               ScanCallback  mScanCallback = new ScanCallback() {
                           @Override
                           public void onScanResult(int callbackType, ScanResult result) {
      
      
                               byte[] scanRecord = result.getScanRecord().getBytes();
                               //scanRecord will give you the raw advertisement data given by the device in byte array.
      
                           }
      
                           @Override
                           public void onBatchScanResults(List<ScanResult> results) {
                               for (ScanResult sr : results) {
                                  //
                               }
                           }
      
                           @Override
                           public void onScanFailed(int errorCode) {
                              //
                           }
                       };
      
    2. 使用 LeScanCallback

            BluetoothAdapter.LeScanCallback mLeScanCallback =
                       new BluetoothAdapter.LeScanCallback() {
                           @Override
                           public void onLeScan(final BluetoothDevice device, int rssi,
                                                byte[] scanRecord) {
      
            //scanRecord will give you the raw advertisement data given by the device in byte array.
      
                           }
                       };
      

    你可以从这个字节数组中过滤掉你想要的设备。

    例如:

    为了仅找出心率监测设备,我将 scanRecord 字节数组转换为字符串,然后检查其中是否出现“0d 18”。

    如果设备原始广告数据包含“0d 18”字符串,则为心率监测器,否则不是。

    如果还有人需要帮助,请告诉我

    【讨论】:

      【解决方案2】:

      我终于找到了解决办法。它没有回答有关原始广告数据过滤器扫描的问题,但我可以扫描我需要的设备。这就是我所做的:

      首先,我按名称制作了一个过滤器。虽然设备没有名称,但我按名称过滤以扫描name == null 的设备。

      private List<ScanFilter> scanFilters() {
          List<ScanFilter> list = new ArrayList<ScanFilter>();
      
          ScanFilter scanFilterName = new ScanFilter.Builder().setDeviceName(null).build();
      
          list.add(scanFilterName);
      
          return list;
      }
      

      在那之后,我需要第二个过滤器(它不在上面的 scanFilters() 方法中,它在 scanResult 上),因为它返回给我大量的设备,并且该过滤器是通过 MAC 地址前缀(我的设备也是如此)。

      private Set<String> btDevice = new LinkedHashSet<String>();
      
      private ScanCallback scanCallback = new ScanCallback() {
          @Override
          public void onScanResult(int callbackType, ScanResult result) {
      
              BluetoothDevice device = result.getDevice();
      
              ScanRecord record = result.getScanRecord();
              byte[] dataByteArray = record.getBytes();
      
              if (device.getAddress().startsWith("F8:36:9B")) {
                  btDevice.add(device.getAddress());
              }
          }
      };
      

      最后,我只需要扫描我需要的设备。我仍然想知道主要问题,所以如果有人对此有解决方案,请随时回答。谢谢!

      【讨论】:

      • 这对您仍然有效吗?您使用的是哪个 Android 版本?当我尝试相同的过滤器时,我得到ScanFailure.FeatureUnsupported
      • @esskar ,你能给我更多的信息吗?到目前为止,您实施了什么?您是否已添加所有权限?它还在工作,我是在 Android 9 上开发的,现在我用的是 10,而且还在工作。
      • 其他所有相关的东西实际上都在工作。就在添加ScanFiltersetDeviceName 为空或为空时,我在scanCallback 中得到ScanFailure.FeatureUnsupported。你在用Intent吗?我最终做的是new ScanFilter.Builder().setManufacturerData(0x004c, null).build(); 它也发现了我所有的广告 ble 设备;不仅是苹果的。
      • ScanFilter scanFilterName = new ScanFilter.Builder().setDeviceAddress("F8:36:9B:...").build();将仅按 MAC id 过滤那些设备
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-02
      • 2015-07-01
      • 1970-01-01
      相关资源
      最近更新 更多