27、低功耗蓝牙(BLE)开发:BLE基础、扫描优化、连接参数、广播策略
各位同学,今天我们来聊聊低功耗蓝牙(BLE)开发。说实话,BLE 在 Android 开发里是个挺有意思的模块——它不像 WiFi 那样大功率传输,也不像 NFC 那样只能贴一下。BLE 的核心就是「低功耗」三个字,但很多新手一上来就踩坑。
我个人习惯把 BLE 开发分成四个模块:基础概念、扫描优化、连接参数、广播策略。咱们一个一个来拆解。
27.1 BLE 基础:你得先知道它怎么工作的
BLE 和经典蓝牙最大的区别是什么?说白了,经典蓝牙是「一直在线」,而 BLE 是「睡一会,醒一下」。它大部分时间都在休眠,只有需要传输数据时才短暂唤醒。这就是它省电的秘密。
在 Android 上做 BLE 开发,核心 API 就几个:BluetoothAdapter、BluetoothLeScanner、BluetoothGatt。嗯,这里要注意:从 Android 6.0 开始,扫描 BLE 设备需要位置权限;从 Android 12 开始,还需要 BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 这两个运行时权限。
BLUETOOTH_ADMIN 不再覆盖扫描权限。必须单独申请 BLUETOOTH_SCAN。
BLE 通信模型是「中心设备 - 外围设备」模式。手机通常是中心设备,智能手环、传感器是外围设备。外围设备通过广播包告诉别人「我在这里」,中心设备扫描到后发起连接。
27.2 扫描优化:别让你的手机变成电老虎
很多同学写 BLE 扫描,上来就是一个 while(true) 循环。你想想看,手机一直在扫描,电量哗哗地掉。我建议的做法是:按需扫描,扫到就停。
扫描参数优化主要看三个东西:
| 参数 | 说明 | 我常用的值 |
|---|---|---|
| 扫描间隔 | 两次扫描之间的间隔时间 | 100ms(快速发现) / 1000ms(省电模式) |
| 扫描窗口 | 每次扫描持续的时间 | 50ms(窗口越短越省电) |
| 扫描模式 | 低功耗、平衡、低延迟 | 低延迟用于连接前,低功耗用于后台 |
举个例子,如果你在做门锁应用,用户靠近时自动解锁。这时候扫描间隔可以设短一点,比如 50ms,让手机快速发现门锁。但如果是后台温度传感器,一小时上报一次数据,那扫描间隔拉到 5 秒都行。
ScanFilter 过滤掉不需要的设备。比如只扫描特定 Service UUID 的设备,这样能大幅减少回调次数,省电又省 CPU。
27.3 连接参数:调好了体验飞起,调不好疯狂断连
连接参数是 BLE 开发里最容易忽略但又最关键的部分。它决定了手机和外围设备之间怎么「对话」。核心参数有四个:
- 连接间隔(Connection Interval):设备之间多久交换一次数据。范围 7.5ms ~ 4s。
- 延迟(Slave Latency):外围设备可以跳过多少次连接事件。比如设成 3,表示可以连续跳过 3 次不回复。
- 超时(Supervision Timeout):超过这个时间没收到数据,就认为连接断了。
- MTU 大小:一次能传多少字节。默认 23 字节,可以协商到 512 字节。
我记得有一次做运动手环项目,用户反馈说「手机放口袋就走几步路,手环就断连了」。查了半天,发现是连接间隔设成了 100ms,但手机在口袋里信号不好,丢包率一高就超时了。后来我把连接间隔调到 30ms,超时时间从 5 秒调到 10 秒,问题就解决了。
连接参数不是随便设的。Android 系统会检查你请求的参数是否合理。比如连接间隔不能小于 7.5ms,超时时间必须大于连接间隔的 4 倍。如果参数不合理,系统会拒绝,使用默认值。
27.4 广播策略:让设备被正确发现
外围设备通过广播包告诉手机「我在这里,我能做什么」。广播包分两种:
- 广播包(Advertising Data):31 字节,必须包含,用于快速发现。
- 扫描响应包(Scan Response Data):31 字节,可选,手机主动请求后返回。
广播策略的核心是:在 31 字节里塞最重要的信息。比如设备名称、Service UUID、Tx Power Level。别把完整的数据都塞进去,你想想看,31 字节能塞多少东西?
我建议的做法是:广播包里只放 Service UUID 和少量标识信息,完整的设备名称和额外数据放到扫描响应包里。这样手机扫描时,先通过 UUID 过滤,再请求扫描响应获取详细信息。
广播间隔也很重要。间隔越短,设备被发现得越快,但越耗电。我一般这样设:
- 设备待连接时:广播间隔 100ms(快速被发现)
- 设备已连接时:停止广播(省电)
- 设备在后台:广播间隔 1000ms(省电模式)
27.5 知识体系总览
下面这张图是我自己整理的 BLE 开发知识体系,你可以把它当作一个检查清单:
27.6 避坑指南:我踩过的那些坑
最后分享几个我实际项目中遇到的坑,希望能帮你少走弯路:
- 扫描回调不触发:检查一下是不是忘了在 Android 12+ 上申请
BLUETOOTH_SCAN权限。我曾经因为这个排查了整整一天。 - 连接后频繁断连:先看连接参数是否合理。我遇到过外围设备只支持 30ms 以上的连接间隔,但手机请求了 20ms,结果系统直接拒绝。
- 广播包发不出去:检查广播包是否超过 31 字节。很多新手把设备名称、所有 Service UUID、厂商数据全塞进去,超了还不知道。
- MTU 协商失败:不是所有设备都支持 512 字节 MTU。我建议先请求 512,如果失败再回退到 128 或 64。
好了,关于 BLE 开发的基础内容就讲到这里。记住一句话:BLE 开发没有银弹,每个参数都要根据你的实际场景去调。多测试、多踩坑,慢慢就有感觉了。
公众号:蓝海资料掘金营,微信deep3321