代码改变世界

杂记:解决Android扫描BLE设备名称不刷新问题

2018-12-21 18:19  Ansersion  阅读(2182)  评论(0编辑  收藏  举报

背景

个人开发过一种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/