背景

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

问题

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

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

原因

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

    private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) { BluetoothDevice device = result.getDevice();
if(null != device && null != device.getName()) {
Log.d("test", device.getName()); // not the real name
}
} @Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
} };

解决

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

      private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) { BluetoothDevice device = result.getDevice();
if(null != device && null != device.getScanRecord().getBytes()) {
byte[] scanRecord = device.getScanRecord().getBytes(); // advertised data
String realName = parseDeviceName(scanRecord);
}
} @Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
} };
     // return name String(successful) or null(failed)
public static String parseDeviceName(byte[] scanRecord) {
String ret = null;
if(null == scanRecord) {
return ret;
} ByteBuffer buffer = ByteBuffer.wrap(scanRecord).order(ByteOrder.LITTLE_ENDIAN);
while (buffer.remaining() > 2) {
byte length = buffer.get();
if (length == 0)
break; byte type = buffer.get();
length -= 1;
switch (type) {
case 0x01: // Flags
buffer.get(); // flags
length--;
break;
case 0x02: // Partial list of 16-bit UUIDs
case 0x03: // Complete list of 16-bit UUIDs
case 0x14: // List of 16-bit Service Solicitation UUIDs
while (length >= 2) {
buffer.getShort();
length -= 2;
}
break;
case 0x04: // Partial list of 32 bit service UUIDs
case 0x05: // Complete list of 32 bit service UUIDs
while (length >= 4) {
buffer.getInt();
length -= 4;
}
break;
case 0x06: // Partial list of 128-bit UUIDs
case 0x07: // Complete list of 128-bit UUIDs
case 0x15: // List of 128-bit Service Solicitation UUIDs
while (length >= 16) {
long lsb = buffer.getLong();
long msb = buffer.getLong();
length -= 16;
}
break;
case 0x08: // Short local device name
case 0x09: // Complete local device name
byte sb[] = new byte[length];
buffer.get(sb, 0, length);
length = 0;
ret = new String(sb).trim();
return ret;
case (byte) 0xFF: // Manufacturer Specific Data
buffer.getShort();
length -= 2;
break;
default: // skip
break;
}
if (length > 0) {
buffer.position(buffer.position() + length);
}
}
return ret;
}

参考资料:

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

最新文章

  1. “未来人类”的笔记本,谁买过哦
  2. About MTU,TCP-MSS (转)
  3. git初体验(六)git配置
  4. hadoop2.6.4运行wordcount
  5. uTenux——LED驱动讲解
  6. linux系统主要常见目录结构
  7. DLL搜索路径和DLL劫持
  8. java集合类之TreeMap
  9. Android中的音频处理------SoundPool,MediaRecorder,MediaPlayer以及RingStone总结
  10. AVFoundation(二)---MPMusicPlayerController
  11. 小程序之发起请求 wx.request(object)的坑
  12. 实战项目:通讯录 UI—第十一天
  13. Android实现无线调试自己的应用
  14. Docker(1):CentOS7 安装Docker
  15. angular4 使用swiper 首次加载问题(一)
  16. [luogu P3806] 【模板】点分治1
  17. 使用Docker部署javaWeb应用
  18. 打破基于OpenResty的WEB安全防护(CVE-2018-9230)
  19. 带你走进php大马的结构模块编写之路
  20. 常见C++内存池技术

热门文章

  1. python第10天(上)
  2. Web服务器原理
  3. python全栈开发day112-CBV、flask_session、WTForms
  4. pyqt pyside QLineEdit 重写键盘事件
  5. python之psutil模块(获取系统性能数据)
  6. LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
  7. XVIII Open Cup named after E.V. Pankratiev. Eastern Grand Prix
  8. web测试注意点
  9. 利用PIL和Selenium实现页面元素截图
  10. __x__(30)0908第五天__导航条的练习 <div>版本