背景

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

杂记:解决Android扫描BLE设备名称不刷新问题的更多相关文章

  1. 关于samsung连接BLE设备的一些资料汇总和开发过程一些经验总结

    1 忙了这么久,终于有时间把最近几个月弄的东西整理一下,顺便我的开发过程和经历. 被公司分到做一个蓝牙4.0的项目,对这种软硬结合的东西也比较感兴趣,所以很快投入到android蓝牙4.0的项目中来. ...

  2. Android 6.0 扫描不到 Ble 设备需开启位置权限

    Android 6.0 扫描不到 Ble 设备需开启位置权限 之前做 Ble 开发都是在 Android 6.0 系统以下的版本中进行测试的,今天使用 Android 6.0 的设备测试的时候,发现扫 ...

  3. Android BLE设备蓝牙通信框架BluetoothKit

    BluetoothKit是一款功能强大的Android蓝牙通信框架,支持低功耗蓝牙设备的连接通信.蓝牙广播扫描及Beacon解析. 关于该项目的详细文档请关注:https://github.com/d ...

  4. 让BLE设备的名称包含MAC地址

    对于研发和测试BLE来说,经常看到同名的设备,是极为不方便的,一大堆设备同时上电会让同事不知道哪一个设备才是自己真正想操作的目标.再说一下小米手环,家中有三支小米手环,打开设备搜索全是“MI”,都不知 ...

  5. Android蓝牙BLE开发,扫描、连接、发送和读取信息;

    1.BLE开发权限 Android蓝牙BLE开发须打开蓝牙权限和6.0位置权限: <uses-permission android:name="android.permission.B ...

  6. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

  7. hbuilder在android手机里用chrome调试,只显示了设备名称,却没有inspect按钮

    stark 通过“菜单”->“工具”->“检查设备”打开设备检查页面,只显示了设备名称,却没有inspect按钮,要怎么办 1 赞2014-10-09 22:00 ============ ...

  8. Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    关键词:蓝牙blueZ  A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...

  9. 如何获得Android设备名称(ADB命令详细介绍)

    豌豆荚.360手机管家等软件可以获取android设备名称,显示在界面上,如下图: 我们自己如何来获取设备名称 呢?答案如下: 在命令行中输入“adb shell”进入shell之后,再输入“cat ...

随机推荐

  1. Python学习笔记十

    守护进程 p.daemon=True 必须在p.start()之前设置. 守护进程内不能再开子进程. 在主进程中开启守护进程(就是一个子进程) 什么时候应该把子进程设置为守护进程? 开子进程的目的:就 ...

  2. 使用Percona Data Recovery Tool for InnoDB恢复数据

      运维工作中难免会发生一些误操作,当数据库表被误操作删除需要紧急恢复,或者没有备份时,Percona Data Recovery Tool for InnoDB这个工具也已提供一些便捷的恢复. 当然 ...

  3. jackson对日期的处理(序列化与反序列化)

    https://blog.csdn.net/cover1231988/article/details/76021478

  4. js分析 有_道_翻_译 md5

    0.参考 1.分析 1.1 输入翻译内容,手动点击“翻译”按钮 1.2 查看提交数据,通过多次提交确认变化量 1.3 CTRL+SHIFT+f 全局搜索 salt 或 sign 定位到三处js代码块, ...

  5. python模拟鼠标键盘操作 GhostMouse tinytask 调用外部脚本或程序 autopy右键另存为

    0.关键实现:程序窗口前置 python 通过js控制滚动条拉取全文 通过psutil获取pid窗口句柄,通过win32gui使程序窗口前置 通过pyauto实现右键菜单和另存为操作 1.参考 aut ...

  6. 视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧,可拖动

    作者测试是在windows下使用,所以下载的页面地址是: http://ffmpeg.zeranoe.com/builds/点击页面上的Download FFmpeg git-738ebb4 64-b ...

  7. webpack报错需要合适的loader

    以前做vue项目都好好的,最近做react,公共配置感觉加个jsx就可以了吧,然而不是这样的. 一.问题描述 You may need an appropriate loader to handle ...

  8. 用Java实现AES加密

    参考内容来自:http://blog.csdn.net/hbcui1984/article/details/5201247 一)什么是AES? 高级加密标准(英语:Advanced Encryptio ...

  9. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第5章编程练习5

    #include <iostream>using namespace std;const MAXSIZE=12;const year=3;int main(){ char *month[M ...

  10. 10_常见的get和post请求_路由器_ejs服务器渲染模板引擎

    1. 常见的 get 和 post 请求有哪些? 常见的发送 get 请求方式: 在浏览器地址栏输入 url 地址访问 所有的标签默认发送的是 get 请求:如 script link img a f ...