Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 622|回复: 0

杂记:解决Android扫描BLE设备名称不刷新问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-30 06:06:02 | 显示全部楼层 |阅读模式

    背景

    个人开发过一种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     }
    View Code

     

     

     

    参考资料:

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

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-11 15:03 , Processed in 0.060141 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表