雜記:解決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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM