雜記:解決Android掃描BLE設備名稱不刷新問題
阿新 • • 發佈:2018-12-21
ati connect size androi 緩存 none 實時 err blue
背景
個人開發過一種BLE設備有這樣一種需求:當設備處於狀態A時,廣播設備名稱A;處於狀態B時,廣播設備名稱B。
問題
我們發現,當Android在進行Ble掃描的時候,掃描回調函數onScanResult中獲取的設備名稱並未隨設備實時改變。
但是當使用nrfConnect進行掃描時,卻發現設備廣播名稱確實是實時改變的。
原因
我們使用如下代碼獲取BLE設備名稱,然而此時device.getName()中的名稱是系統緩存的數據,而非實時的廣播數據,要想獲取實時的設備名稱,必須自行解碼實時廣播數據。
1 private ScanCallback mScanCallback = newScanCallback() { 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/
雜記:解決Android掃描BLE設備名稱不刷新問題