Skip to content

ble-gatt-playground ​

1. 实验目标与工程要点 ​

这个 Android host 实验不依赖真实 BLE 外设,而是用可稳定运行的状态机面板把 BLE 最容易出事故的链路显式化:

  • Android 12+ 权限申请分支怎么收口
  • 扫描 → 连接 → 服务发现 → MTU → Notification 的时序如何组织
  • 为什么 GATT 操作必须进串行队列
  • disconnect() 和 close() 为什么要分开处理
  • status=133、通知收不到、断线重连时第一步该查什么

它真正验证的不是“我的电脑现在有没有蓝牙外设”,而是:你是否已经把 BLE 的核心状态机与排障心智建模清楚。


2. 深入原理与生活浅显比喻 ​

2.1 生活浅显比喻 ​

把 BLE 想成“门禁访客系统”:

  • 扫描像门口保安认人:先看有没有这类访客。
  • 连接像把访客带进大堂:只说明人进来了,还没开始办业务。
  • 服务发现像确认他能去哪些楼层。
  • Characteristic 读写像递交表单、拿回执。
  • Notification像访客后续主动给前台发消息。
  • GATT 队列像“一次只让一个人办一项业务”,否则窗口会乱。

所以 BLE 最容易踩的坑,不是“门有没有打开”,而是“同一时间窗口里塞了太多人办不同手续”。

2.2 底层原理分析 ​

BLE 工程通常分两层:

  1. GAP:广播、扫描、过滤、建立连接。
  2. GATT:服务发现、特征读写、Descriptor、通知订阅。

Android BLE 栈的大坑是:同一时间往往只允许一个 GATT 操作在途。因此真实业务里至少要有:

  • 操作队列
  • 回调推进
  • 超时与失败收口
  • 断线后的资源释放和重连策略

本实验页面把这些阶段做成日志化状态机,而不是直接绑死在真实硬件回调上。这样即使没有外设,也能复习“正确链路长什么样”。

2.3 方案对比矩阵 ​

方案通俗比喻底层原理保证特性吞吐性能运行开销适用场景
按按钮直接调 GATT看见窗口空着就随手塞业务不建队列,回调里临时串逻辑开发快,但状态不可控高(看起来)低Demo、一次性验证
状态机 + 串行队列窗口一次只办一件事,办完再叫下一个明确阶段、回调推进、失败收口顺序稳定、排障清晰中中真正上线的 BLE 控制链路
完整设备协议层前台 + 后台 + 财务联动的整套业务系统在状态机外再叠协议编码/ACK/重试/分包稳定性最高中高量产设备、固件升级、复杂指令集

「吞吐性能」和「运行开销」分开看:不建队列表面上最轻,实际上最容易把问题转移成线上失败与难排障成本。


3. Android / 移动端实战场景与误配事故 ​

3.1 实战场景 ​

本实验模拟的最小稳定链路:

  • 先检查 Android 12+ 的扫描/连接权限
  • 点击“开始扫描”后进入发现设备阶段
  • 选中设备后进入连接与服务发现阶段
  • 连接建立后演示 MTU、Notification、写命令的典型顺序
  • 支持模拟 status=133、通知未开启、断线重连三类常见故障

3.2 常见误配与事故注意事项 ​

  • 并发发 GATT 操作:最典型,直接导致 false / 133 / 回调错乱。
  • 只 disconnect 不 close:旧句柄残留,重连越来越不稳定。
  • 只开本地 notification,不写 CCCD:页面显示“已订阅”,设备侧却不推送。
  • 盲目无限重连:耗电高、系统限制命中,用户看到的是“App 一直转圈”。

3.3 排障思路 ​

先不要急着怀疑外设,先问这四件事:

  1. 当前卡在扫描、连接、服务发现、订阅,还是写命令?
  2. 是否真的按“一个操作完成后再发下一个”推进?
  3. 断线后是否执行了 close() 并清空旧状态?
  4. 当前问题是“真实硬件不可达”,还是“本地状态机就已经写错”?

4. 实验源码与运行验证 ​

关键源码 ​

关键参数 / 开关 ​

  • grantPermissions:模拟 Android 12+ 扫描/连接权限是否已授权。
  • simulateStatus133:模拟连接后收到 status=133,观察是否进入 close + 退避重连。
  • simulateNotificationFailure:模拟只开本地监听、不完成远端订阅的失败分支。
  • operationQueue:模拟 GATT 操作串行队列,用于观察 MTU / Notification / Write 的推进顺序。

运行方式 ​

bash
cd labs/android/host
./gradlew :app:installDebug
adb shell am start -n com.shayn.engineeringreviewlab.androidhost/.MainActivity

启动后进入 打开 BLE / GATT 最小状态机实验室。

预期控制台运行输出 ​

text
[idle] 等待开始 BLE 实验
[checkingPermissions] 校验 Android 12+ 蓝牙权限
[scanning] 已开始扫描,等待发现目标设备
[connecting] 已发现设备,开始 connectGatt
[discoveringServices] 连接建立,准备 discoverServices
[requestingMtu] 申请更大的 MTU,准备传输长指令
[enablingNotification] 写 CCCD,准备接收设备主动通知
[ready] BLE 最小链路已就绪,可安全发送业务命令

切换故障开关后可看到:

  • 权限关闭 → 直接 failed
  • status=133 → failed + 给出 close / 重连建议
  • Notification 失败 → failed + 指向 CCCD 检查
  • 手动断开 → disconnected + 指数退避重连建议

5. 对应知识库文档 ​

这份 README 负责承载 Android host 的真实入口、运行方式与故障分支;BLE 概念、Android / Flutter 对照、误配解释请回主文档看。

站点构建时间:2026/8/24 23:43:17