杂记:解决Android扫描BLE设备名称不刷新问题
2024-08-29 01:13:53
背景
个人开发过一种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/
最新文章
- “未来人类”的笔记本,谁买过哦
- About MTU,TCP-MSS (转)
- git初体验(六)git配置
- hadoop2.6.4运行wordcount
- uTenux——LED驱动讲解
- linux系统主要常见目录结构
- DLL搜索路径和DLL劫持
- java集合类之TreeMap
- Android中的音频处理------SoundPool,MediaRecorder,MediaPlayer以及RingStone总结
- AVFoundation(二)---MPMusicPlayerController
- 小程序之发起请求 wx.request(object)的坑
- 实战项目:通讯录&;nbsp;UI—第十一天
- Android实现无线调试自己的应用
- Docker(1):CentOS7 安装Docker
- angular4 使用swiper 首次加载问题(一)
- [luogu P3806] 【模板】点分治1
- 使用Docker部署javaWeb应用
- 打破基于OpenResty的WEB安全防护(CVE-2018-9230)
- 带你走进php大马的结构模块编写之路
- 常见C++内存池技术
热门文章
- python第10天(上)
- Web服务器原理
- python全栈开发day112-CBV、flask_session、WTForms
- pyqt pyside QLineEdit 重写键盘事件
- python之psutil模块(获取系统性能数据)
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
- XVIII Open Cup named after E.V. Pankratiev. Eastern Grand Prix
- web测试注意点
- 利用PIL和Selenium实现页面元素截图
- __x__(30)0908第五天__导航条的练习 <;div>;版本