杂记:解决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     }

参考资料:

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

原文地址:https://www.cnblogs.com/ansersion/p/10157388.html

时间: 2024-10-07 02:46:34

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

Android之BLE编程

写在前面: 作为一个程序员,各种苦逼啊,作为一个Android程序员,苦逼死了. Android手机可以使用WIFI.蓝牙和数据网络进行网络通信,那作为Android程序员,就必须得会这些了.如果不会,都不好意思给别人说你是21世纪的屌丝程序员. 通过WIFI和数据网络通信的Socket编程(基于IP的TCP.UDP.HTTP通信 )相信大家都是驾轻就熟了.而现阶段,随着物联网的发展和蓝牙的BLE低功耗方案的成熟,BLE设备应用越来越广泛,尤其是智能穿戴设备. 那么BLE编程是和怎么回事呢?到底

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

对于研发和测试BLE来说,经常看到同名的设备,是极为不方便的,一大堆设备同时上电会让同事不知道哪一个设备才是自己真正想操作的目标.再说一下小米手环,家中有三支小米手环,打开设备搜索全是“MI”,都不知道连接哪一个,所以在开始使用的时候才要求用户去敲手环几下,当然这个体验也还算不错.但不管怎样,作为开发者,面对Office里一大堆的BLE设备,能够方便区分还是不错的.因此萌生让设备名称包含一个唯一的标识——MAC地址. 第一步先说如何更改设备名称 BLE中要更改名称是极为方便的,只需要更改扫描应答

完美解决Android使用Zxing扫描二维码改成竖屏后,后面的预览画面出现了拉伸,扭曲的情况

完美解决解决Android使用Zxing扫描二维码改成竖屏后,后面的预览画面出现了拉伸,扭曲的情况 第一步:找到com.zxing.camera包下的CameraConfigurationManager.java文件中的void initFromCameraParameters(Camera camera)方法 第二步:在 Log.d(TAG, "Screen resolution: " + screenResolution);后加上如下的代码 Point screenResoluti

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

关键词:蓝牙blueZ  A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_get_properties.AUDIO.DBUS版本号:基于android4.2之前版本号 bluez内核:linux/linux3.08系统:android/android4.1.3.4作者:xubin341719(欢迎转载.请注明作者.请尊重版权谢谢)欢迎指正错误.共同学习.共同进步!! 參考

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

豌豆荚.360手机管家等软件可以获取Android设备名称,显示在界面上,如下图: 我们自己如何来获取设备名称 呢?答案如下: 在命令行中输入"adb shell"进入shell之后,再输入"cat /system/build.prop"其实,设备信息,主要是存放在"/system/build.prop"文件,通过"cat"命令就可以查看了. 下面附上ADB命令的详细介绍 adb 介绍 adb的全称为Android Debug

Zxing图片拉伸解决 Android 二维码扫描

二维码扫描  Android Zxing图片拉伸解决 Zxing是google提供的二维码扫描工程 默认是横屏的  转换成竖屏后图片出现拉伸 这里提供解决办法: Zxing  修改 CameraConfigurationManager.java文件的 void initFromCameraParameters(Camera camera)方法 在 Log.d(TAG, "Screen resolution: " + screenResolution);这句之后增加 Point scre

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

原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_get_properties.AUDIO.DBUS版本:基于android4.2之前版本 bluez内核:linux/linux3.08系统:android/android4

[转]如何解决android模拟器慢的问题

分步阅读 在android开发的过程,发现android模拟器的速度不是一般的慢,那主要是因为android模拟器默认采用的是arm处理器造成的,这里主要提供两种方法: ① 利用intel虚拟硬件加速的方式,实现android模拟器的加速,从而解决android模拟器速度慢的问题: ② 使用genymotion模拟器, 主要采用的是利用Virtual Box虚拟机的原理: 方便他人亦是方便自己,如果觉得还行就点下右边的投票吧,这样可以帮助其他人更快的找到解决问题的方法:有疑问的也可留言哦, 谢谢

理解 QEMU/KVM 和 Ceph(3):存储卷挂接和设备名称

本系列文章会总结 QEMU/KVM 和 Ceph 之间的整合: (1)QEMU-KVM 和 Ceph RBD 的 缓存机制总结 (2)QEMU 的 RBD 块驱动(block driver) (3)存储卷挂接和设备名称 这篇文章分析一下一个 Ceph RBD 卷是如何被映射到一个 QEMU/KVM 客户机的,以及客户机中设备的命名问题. 1. 遇到的设备命名问题 1.1 通过 Nova 和 Cinder 做 Ceph RDB 卷挂接和卸载步骤 挂接一个卷: #运行nova-attach 命令no