zoukankan      html  css  js  c++  java
  • 杂记:解决Android扫描BLE设备名称不刷新问题

    背景

    个人开发过一种BLE设备有这样一种需求:当设备处于状态A时,广播设备名称A;处于状态B时,广播设备名称B。

    问题

    我们发现,当Android在进行Ble扫描的时候,扫描回调函数onScanResult中获取的设备名称并未随设备实时改变。

    但是当使用nrfConnect进行扫描时,却发现设备广播名称确实是实时改变的。

    原因

    我们使用如下代码获取BLE设备名称,然而此时device.getName()中的名称是系统缓存的数据,而非实时的广播数据,要想获取实时的设备名称,必须自行解码实时广播数据。

     1    private ScanCallback mScanCallback = new ScanCallback() {
     2         @Override
     3         public void onScanResult(int callbackType, ScanResult result) {
     4             
     5             BluetoothDevice device = result.getDevice();
     6             if(null != device && null != device.getName()) {
     7                  Log.d("test", device.getName()); // not the real name
     8             }
     9         }
    10 
    11 
    12         @Override
    13         public void onScanFailed(int errorCode) {
    14               super.onScanFailed(errorCode);
    15         }
    16 
    17     };

    解决

    通过分析BLE广播包协议,自行解码出设备名称。

     1      private ScanCallback mScanCallback = new ScanCallback() {
     2           @Override
     3           public void onScanResult(int callbackType, ScanResult result) {
     4               
     5               BluetoothDevice device = result.getDevice();
     6               if(null != device && null != device.getScanRecord().getBytes()) {
     7                    byte[] scanRecord = device.getScanRecord().getBytes(); // advertised data
     8                    String realName = parseDeviceName(scanRecord);
     9               }
    10           }
    11  
    12  
    13          @Override
    14          public void onScanFailed(int errorCode) {
    15                super.onScanFailed(errorCode);
    16          }
    17  
    18      };
     1     // return name String(successful) or null(failed)
     2       public static String parseDeviceName(byte[] scanRecord) {
     3         String ret = null;
     4         if(null == scanRecord) {
     5             return ret;
     6         }
     7 
     8         ByteBuffer buffer = ByteBuffer.wrap(scanRecord).order(ByteOrder.LITTLE_ENDIAN);
     9         while (buffer.remaining() > 2) {
    10             byte length = buffer.get();
    11             if (length == 0)
    12                 break;
    13 
    14             byte type = buffer.get();
    15             length -= 1;
    16             switch (type) {
    17                 case 0x01: // Flags
    18                     buffer.get(); // flags
    19                     length--;
    20                     break;
    21                 case 0x02: // Partial list of 16-bit UUIDs
    22                 case 0x03: // Complete list of 16-bit UUIDs
    23                 case 0x14: // List of 16-bit Service Solicitation UUIDs
    24                     while (length >= 2) {
    25                         buffer.getShort();
    26                         length -= 2;
    27                     }
    28                     break;
    29                 case 0x04: // Partial list of 32 bit service UUIDs
    30                 case 0x05: // Complete list of 32 bit service UUIDs
    31                     while (length >= 4) {
    32                         buffer.getInt();
    33                         length -= 4;
    34                     }
    35                     break;
    36                 case 0x06: // Partial list of 128-bit UUIDs
    37                 case 0x07: // Complete list of 128-bit UUIDs
    38                 case 0x15: // List of 128-bit Service Solicitation UUIDs
    39                     while (length >= 16) {
    40                         long lsb = buffer.getLong();
    41                         long msb = buffer.getLong();
    42                         length -= 16;
    43                     }
    44                     break;
    45                 case 0x08: // Short local device name
    46                 case 0x09: // Complete local device name
    47                     byte sb[] = new byte[length];
    48                     buffer.get(sb, 0, length);
    49                     length = 0;
    50                     ret = new String(sb).trim();
    51                     return ret;
    52                 case (byte) 0xFF: // Manufacturer Specific Data
    53                     buffer.getShort();
    54                     length -= 2;
    55                     break;
    56                 default: // skip
    57                     break;
    58             }
    59             if (length > 0) {
    60                 buffer.position(buffer.position() + length);
    61             }
    62         }
    63         return ret;
    64     }
    View Code

    参考资料:

    https://www.race604.com/ble-advertising/

  • 相关阅读:
    MySQL的count函数注意点
    case when语句的报错问题
    redis的主从搭建与sentinel高可用服务的搭建
    解析范式(1NF-4NF)
    对SQL语言的相关学习
    ASP.NET Core MVC+EF Core项目实战
    ASP.NET Core +Highchart+ajax绘制动态柱状图
    tab页卡效果!
    今天我注册了迅雷快传
    触发器学习笔记(:new,:old用法)
  • 原文地址:https://www.cnblogs.com/ansersion/p/10157388.html
Copyright © 2011-2022 走看看