规划进度
由 plan 工具自动维护;与纲卷/INDEX 状态表联动,请勿手改勾选。
p1 ├── 01_总目录.md ← 入口 + 结论与决策速览
p2 ├── 02_问题定义与方案总览.md ← 三种方案对比 + Mermaid 总览图
p3 ├── 03_硬件层技术路线.md ← A/B/C 详细实现 + 各方案架构图
p4 ├── 04_手机端控制机制.md ← Android/iOS 控制机制对比
p5 ├── 05_指令协议设计.md ← 协议定义 + 安全机制
自动更新于 2026/9/29 21:51:59
创建时间:2026-09-29 21:39
工作目录:D:/5xWorks/immediates/202609292139_手机蓝牙硬件控制手机操作
状态:✅ 全部完成(8 章 + 参考来源)
问题树
手机蓝牙硬件 → 控制手机操作 ├── 1. 硬件层选哪条技术路线? │ ├── A. BLE HID(伪装键盘/鼠标,零 App) │ ├── B. BLE GATT(自定义协议 + 配套 App) │ └── C. 经典蓝牙 SPP(串口,兼容性好) ├── 2. 手机端如何执行控制? │ ├── Android:AccessibilityService / InputManager / UiAutomation │ └── iOS:CoreBluetooth 通信 vs 系统级限制 ├── 3. 指令协议怎么设计?(数据格式 / 幂等 / 安全) ├── 4. 推荐技术栈与固件/App 分工 ├── 5. 开发路线与验收里程碑 └── 6. 局限、风险与合规边界(含出处)
各章内容与状态
| 编号 | 章节 | 路径 | 状态 |
|---|---|---|---|
| 00 | 本目录 | 01_总目录.md | ✅ 完成 |
| 01 | 问题定义与方案总览 | 02_问题定义与方案总览.md | 完成 |
| 02 | 硬件层技术路线对比(HID / GATT / SPP) | 03_硬件层技术路线.md | 完成 |
| 03 | 手机端控制机制(Android / iOS) | 04_手机端控制机制.md | 完成 |
| 04 | 指令协议设计 | 05_指令协议设计.md | 完成 |
| 05 | 推荐技术栈与工程实现 | 06_技术栈与工程实现.md | 完成 |
| 06 | 开发路线、风险与合规 | 07_开发路线风险合规.md | ✅ 已完成 |
| 07 | 参考来源 | 08_参考来源.md | ✅ 已完成 |
结论与决策速览
核心结论
推荐方案:ESP32-C3(NimBLE)+ Android AccessibilityService,硬件同时实现 HID + GATT 双 Profile。
iOS 限制:iOS 无公开触摸注入 API,仅能做 HID 键盘/蓝牙通信;完整控制需越狱或 MDM 企业方案。
协议选型:BLE GATT 自定义 Service 是万能方案,HID 是免配对兜底,SPP 仅用于调试。
安全机制:BLE LE Secure Connections + 应用层 HMAC 签名 + 指令白名单。
合规风险:Android 无障碍服务受 Google Play 政策限制,iOS 越狱有法律风险。
决策速览
| 场景 | 推荐方案 | 硬件 | 手机端 |
|---|---|---|---|
| 免配对快速控制 | 方案 A(HID) | ESP32-C3 | 无需 App |
| 完整控制系统 | 方案 B(GATT) | ESP32-C3 | Android App + 无障碍 |
| 调试/老设备 | 方案 C(SPP) | HC-05 | Android App |
| iOS 场景 | 方案 A(HID) | ESP32-C3 | 仅键盘输入 |
下一步建议
硬件选型:ESP32-C3-DevKitM-1(约 ¥30),NimBLE 协议栈。
固件开发:基于 ESP-IDF
ble_hid_device_demo示例扩展。App 开发:Android Kotlin + AccessibilityService + BluetoothGatt。
协议设计:JSON 指令 + HMAC-SHA256 签名 + 心跳保活。
测试验证:nRF Sniffer 抓包 + 真机联调。
Mermaid 总览图已补入 02 章;各方案架构图已补入 03 章。
02 问题定义与方案总览
2.1 目标
用一个蓝牙硬件设备(而非手机 USB 或局域网)作为「远端输入源」,对手机执行可编程操作:点击、滑动、输入文本、打开 App、截图、按键等。核心问题是:
链路怎么建:蓝牙协议层选 HID / GATT / SPP,决定手机能否"即插即用"还是要装 App;
手机怎么执行:Android 与 iOS 的系统权限差异(AccessibilityService 等)决定最终能力上限;
指令怎么传:数据格式、确认/重试、安全;
工程怎么做:固件 + App 的分工与里程碑。
2.2 方案总览
2.3 三路线的适用边界(结论先行)
| 维度 | A. BLE HID | B. BLE GATT | C. 经典 SPP |
|---|---|---|---|
| 是否需装 App | 否(系统识别为外设) | 是 | 是 |
| 可执行操作 | 键鼠事件(点击坐标受限,靠 Tab/方向键) | 任意系统操作(App 有无障碍权限时) | 同 GATT |
| Android | ✅ 通用键鼠可用 | ✅ | ✅ |
| iOS | ⚠️ 仅键盘等 HID 可用 | ✅ 通信无限制,但无公开 API 模拟点击 | ✅ 通信无限制 |
| 延迟/功耗 | BLE 低功耗、低延迟 | BLE 低功耗 | 经典蓝牙功耗高 |
| 开发量 | 固件中等、App 为零 | 固件 + App 都做 | 固件简单、App 都做 |
| 建议 | 成品/玩具/应急控制 | 自研首选 | 兼容性兜底 |
推荐组合:硬件固件同时实现 BLE HID(开箱即用)与 GATT(完整功能),App 优先 Android。iOS 侧受系统限制,只做 HID/通信能力,不做模拟点击(越狱除外)。
2.4 芯片选型的事实依据
ESP32 系列(乐鑫):集成 Wi-Fi + 蓝牙的 SoC,可用 ESP-IDF 开发,生态成熟、资料丰富。出处:
乐鑫 ESP32 产品页:https://www.espressif.com/zh-hans/products/socs/esp32
ESP-IDF 快速入门:https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/get-started/index.html
nRF52840(Nordic):支持 BLE 5.0 等多协议并发(BLE Mesh/Thread/Zigbee/802.15.4),ARM Cortex-M4,1MB Flash / 256KB RAM,官方 DK 开发套件。出处:
Nordic 中文产品页:https://www.nordicsemi.cn/products/nrf52840/
nRF52840 DK:https://www.nordicsemi.cn/tools/nrf52840dk/
事实:ESP32 是"蓝牙+Wi-Fi"通用 SoC;nRF52840 是多协议低功耗旗舰。两者都支持 BLE HID 与 GATT 自定义服务,选型取决于成本(ESP32 更便宜)还是多协议/超低功耗(nRF52840 更强)。
2.5 本章小结
技术上完全可行,三条路线各有取舍;Android 是执行能力强、权限可控的目标平台,iOS 只能做到"HID 键盘/蓝牙通信",不能公开 API 模拟触摸。下文各章分别展开。 (GATT 手机端机制、协议细节见 04/05 章,检索补充中)
03 硬件层技术路线
结论:自研首选 BLE GATT 完整方案 + 固件内置 BLE HID 兜底;本文按「原理 → 实现 → 对比」展开。
3.1 方案 A:BLE HID(零 App 依赖)
3.1.1 原理
BLE HID 是蓝牙 SIG 定义的 HID-over-GATT Profile(HOGP):外设把自己声明成一个键盘 / 鼠标 / 触摸板,手机蓝牙设置里直接显示为「蓝牙键盘」,配对即用,无需安装任何 App。
规范:HID over GATT Profile(HOGP)— 参考 Bluetooth SIG 规范 https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile/
手机侧:Android / iOS 系统内置 HID Host 支持,输入事件自动进入系统输入管线(Android
/dev/input、iOS 键盘事件)。
3.1.2 能做什么 / 不能做什么
| 能力 | 说明 |
|---|---|
| ✅ 键盘按键 | 任意按键、组合键(如 Home、音量、媒体键) |
| ✅ 鼠标移动/点击 | 蓝牙鼠标指针 + 左/右键 |
| ✅ 消费类 HID 用法 | 媒体控制、系统控制(Android 上部分可用) |
| ❌ 任意坐标点击 | HID 鼠标是「相对位移」,不是「绝对坐标 tap」;做不了 tap(x,y) 精确坐标,只能靠 Tab/方向键焦点导航 |
| ❌ 触摸手势 | 多点/滑动不可表达 |
| ❌ 读屏幕状态 | 纯单向输入 |
典型应用:按键翻页/翻 PPT、媒体播放控制、应急解锁输入键盘、游戏方向键等「按键级」操作。
3.1.3 固件实现要点(ESP32 / nRF52)
方案 A 架构图:
协议:HID over GATT Profile(HOGP),蓝牙 SIG 标准 https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile/
ESP32 + NimBLE:
nimble_hid_service组件(ESP-IDF 官方示例ble_hid_device_demo)即实现 HID 键盘/鼠标/消费控制服务,改报表描述符即可定制按键。ESP-IDF BLE HID 示例:https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/nimble/ble_hid_device_demo
nRF52 + Zephyr:
samples/bluetooth/hid_keyboard官方示例。Zephyr HID keyboard 示例:https://docs.zephyrproject.org/latest/samples/bluetooth/hid_keyboard/README.html
3.1.4 评估
✅ 无需 App、即连即用、电池友好(BLE 低功耗)
⚠️ 能力天花板 =「键鼠」,无坐标级触摸、无屏幕回读
📌 定位:兜底通道 / 免配对的应急输入,适合「按键类」控制
3.2 方案 B:BLE GATT(自研功能最强的路线)
3.2.1 原理
外设用 GATT 自定义服务(custom Service + Characteristic)承载指令:手机 App 作为 GATT Client,连接外设、订阅 Notify、写入指令。协议内容完全自定(JSON / 二进制均可),因此能力只受手机 App 权限限制,不受 HID 报表约束。
Android:
BluetoothLeScanner(扫描)→BluetoothGatt(连接)→onCharacteristicChanged读 Notify /writeCharacteristic下发。Android BLE 官方文档:https://developer.android.com/develop/connectivity/bluetooth/ble/ble-overview
iOS:
CBCentralManager+CBPeripheral连接,CoreBluetooth 对 BLE 直连无系统限制。Apple CoreBluetooth 文档:https://developer.apple.com/documentation/corebluetooth
3.2.2 指令下发链路(Android 为例)
蓝牙外设 --GATT Notify/自定义 Service--> App(BLE Client) --> 指令解析(JSON) --> 无障碍服务(UiAutomation/performAction) --> 点击/滑动/输入/开App/截屏 --> 结果回传(外设或云端)
3.2.3 实现要点
方案 B 架构图:
| 端 | 要点 |
|---|---|
| 固件 | 定义 Service UUID + Characteristic(指令写、状态通知、可加 128-bit UUID 防碰撞);用 NimBLE GATT server / Zephyr bt_gatt_service_static |
| App | 用 BluetoothGatt 维护连接状态机;消息分包(BLE MTU 默认 23 字节,协商后 247+);写前 requestMtu |
| 安全 | Characteristic 属性设为 Encrypt + Authenticate;可加 6 位 PIN 配对 |
BLE MTU 与分包说明(Android 官方):
https://developer.android.com/develop/connectivity/bluetooth/ble/mtu
3.2.4 评估
✅ 协议自由、可传复杂指令、可回传状态/截屏
⚠️ 必须装 App、App 需常驻(前台服务 + 无障碍权限)
📌 定位:自研控制系统的核心通道
3.3 方案 C:经典蓝牙 SPP(串口兜底)
3.3.1 原理
经典蓝牙 Serial Port Profile(SPP)模拟串口,外设 ↔ App 之间透传任意字节流。手机端无需配对后鉴权协议,App 用蓝牙 Socket 读流即可。
Android:
BluetoothSocket(SPP,UUID00001101-0000-1000-8000-00805F9B34FB)可直连。iOS:苹果 不支持公开 SPP(只能用 MFi / External Accessory 或 BLE),这是 iOS 侧主要限制。
3.3.2 评估
方案 C 架构图:
✅ 最简单、最通用(Android 老兼容性最好),调试方便(可接 PC 串口)
⚠️ 功耗高、连接慢;iOS 无公开 SPP;生态正被 BLE 取代
📌 定位:调试通道 / 老设备兼容
3.4 芯片对比与选型建议
| 维度 | ESP32-C3 / ESP32 | nRF52840 | STM32WB |
|---|---|---|---|
| 内核 | RISC-V (C3) / Xtensa | Cortex-M4F | Cortex-M4 |
| BLE | BLE 5.0 | BLE 5.0 多协议 | BLE 5.0 |
| 成本 | 低(¥10-20 量级) | 中高(¥30+) | 中 |
| 生态 | ESP-IDF / Arduino 资料最多 | Zephyr / SDK 最全,低功耗标杆 | STM32Cube 生态 |
| HID/GATT 支持 | ✅(NimBLE) | ✅(SoftDevice / Zephyr) | ✅ |
| 建议 | 开发首选(性价比+资料多) | 量产低功耗/多协议并发 | 已有 STM32 产线时 |
出处:
乐鑫 ESP32 芯片参数:https://www.espressif.com/zh-hans/products/socs/esp32 (errata/参数见产品页)
nordicsemi nRF52840:https://www.nordicsemi.cn/products/nrf52840/
STM32WB 系列(ST 官网):https://www.st.com/zh/microcontrollers-microprocessors/stm32wb-series.html
3.5 本章小结
三路线硬件成本接近,能力差异在协议层:
HID = 万能免装 App 但只是「键鼠」;
GATT = 万能协议但需 App;
SPP = 简单但被 iOS/生态淘汰。
推荐 ESP32(NimBLE) 同时实现 HID + GATT:HID 给免配对场景,GATT 给完整控制系统。
04 手机端控制机制(Android / iOS)
结论:Android 用「无障碍服务 + 前台服务」是官方唯一合规路径;iOS 无公开 API,只能走 MFi 或越狱,实用价值低。
4.1 Android:无障碍服务(AccessibilityService)
4.1.1 为什么必须用无障碍服务
Android 从 4.1 起把「模拟点击/滑动/输入」能力收归到 AccessibilityService 中,普通 App 无法直接注入触摸事件。这是官方唯一合规路径。
官方文档:https://developer.android.com/reference/android/accessibilityservice/AccessibilityService
无障碍服务开发指南:https://developer.android.com/guide/topics/ui/accessibility/service
4.1.2 核心 API
| API | 作用 |
|---|---|
dispatchGesture(GestureDescription, callback, handler) | 注入点击/滑动/长按(Android 7.0+) |
performGlobalAction(action) | 全局动作:HOME、BACK、RECENTS、NOTIFICATION、OPEN_NOTIFICATION、GLOBAL_ACTION_EXPAND_NOTIFICATIONS 等 |
performAction(node, action, args) | 对指定 UI 节点执行点击/滚动/输入 |
findAccessibilityNodeInfosByText / ByViewId | 按文本/ID 定位控件 |
onAccessibilityEvent(event) | 监听系统事件(窗口切换、文本变化等) |
takeScreenshot(...) (Android 12+) | 无障碍服务可截屏(需 CAPTURE_CONTENT 权限) |
4.1.3 声明与授权流程
AndroidManifest.xml声明 Service +BIND_ACCESSIBILITY_SERVICE权限 +meta-data指向accessibility_service_config.xml。accessibility_service_config.xml声明canPerformGestures="true"、canRetrieveWindowContent="true"、accessibilityEventTypes、accessibilityFeedbackType。用户手动到「设置 → 无障碍 → 已下载的服务」打开开关(无法静默授权)。
服务启动后常驻,通过
onServiceConnected拿到实例。
4.1.4 前台服务保活
无障碍服务本身是系统级常驻,但接收蓝牙指令的 App 需要前台服务避免被杀:
声明
FOREGROUND_SERVICE+FOREGROUND_SERVICE_CONNECTED_DEVICE(Android 14 起要求细分类型)。蓝牙连接建立后
startForeground(id, notification),通知常驻。Android 12+ 后台启动限制:需用户先启动 App 一次,或用
BOOT_COMPLETED广播 + 已授权无障碍服务组合。
4.1.5 关键限制
| 限制 | 说明 |
|---|---|
| 用户手动授权 | 无法静默开启无障碍 |
| 部分厂商限制 | 小米/华为/OPPO/vivo 有额外「后台弹出界面」「自启动」开关 |
| 电池优化 | 需引导用户关闭「电池优化」 |
| 应用商店审核 | Google Play 对无障碍滥用有审核,需说明用途 |
| 屏幕常亮 | 部分操作需 FLAG_KEEP_SCREEN_ON 或 WAKE_LOCK |
4.2 Android:Root 方案(不推荐)
通过
input命令(adb shell input tap x y)或sendevent直接写/dev/input/eventX。需要 root 权限,无法上架应用商店,安全风险高。
仅用于开发调试或私有部署。
4.3 iOS:无公开 API
4.3.1 官方限制
iOS 不提供任何公开 API 让第三方 App 模拟触摸、点击、滑动。
系统级自动化只能通过:
MFi(Made for iPhone)认证:走 External Accessory Framework,但只能控制认证过的硬件,不能操作其他 App。
AppleScript / Shortcuts:只能操作 iOS 自身功能,不能跨 App 注入触摸。
越狱:注入
IOHIDEvent或SpringBoard私有 API,但需越狱,实用性极低。
4.3.2 结论
iOS 侧无法用蓝牙硬件 + App 的方式实现「控制任意 App 的点击/滑动」。
若必须支持 iOS,只能:
用 BLE HID 做「键盘/鼠标」级控制(有限);
或走 MFi 认证做专用硬件(成本高、周期长)。
4.4 本章小结
Android 是唯一可行平台:无障碍服务 + 前台服务 + 蓝牙 GATT 三件套。
iOS 侧能力天花板 = BLE HID 键鼠,无法做完整自动化。
工程上需重点处理:厂商差异化授权、电池优化、后台保活。
05 指令协议设计
结论:BLE GATT 用「二进制头 + JSON 载荷」混合协议,兼顾解析速度与可读性;HID 走标准报表。
5.1 协议分层
┌─────────────────────────────────────────┐ │ 应用层:指令语义(tap/swipe/input/open) │ ├─────────────────────────────────────────┤ │ 传输层:GATT Characteristic / HID Report │ ├─────────────────────────────────────────┤ │ 链路层:BLE / SPP │ └─────────────────────────────────────────┘
5.2 BLE GATT 服务设计
5.2.1 Service UUID
主服务:
0000FFE0-0000-1000-8000-00805F9B34FB(16-bit 保留段,避免与系统服务冲突)或 128-bit 自定义 UUID(防碰撞):
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
5.2.2 Characteristic 划分
| Characteristic | 属性 | 用途 |
|---|---|---|
CmdWrite | Write / WriteNoResponse | 手机 → 外设:指令下发 |
StatusNotify | Notify | 外设 → 手机:状态/结果回传 |
Heartbeat | Read / Notify | 心跳保活 |
Config | Read / Write | 配置(音量、亮度、模式) |
5.2.3 消息格式(推荐:二进制头 + JSON 载荷)
[Header 4B] [Payload N B] Header: - Byte 0: Magic (0xAA) - Byte 1: Version (0x01) - Byte 2: Type (0x01=Cmd, 0x02=Status, 0x03=Heartbeat) - Byte 3: Length (Payload 长度, 低字节) Payload: - JSON 字符串(UTF-8)
为什么混合:
纯 JSON:解析慢、无边界,BLE 分包后需重组;
纯二进制:可读性差、扩展难;
混合:Header 快速定位边界,Payload 用 JSON 便于扩展。
5.2.4 指令集(应用层)
| 指令 | 参数 | 说明 |
|---|---|---|
tap | {x, y} | 点击坐标 |
swipe | {x1, y1, x2, y2, duration} | 滑动 |
input | {text} | 输入文本 |
key | {code} | 按键(HOME/BACK/音量) |
open | {package, activity} | 打开 App |
screenshot | {} | 截屏(Android 12+) |
scroll | {direction, steps} | 滚动 |
longpress | {x, y, duration} | 长按 |
5.2.5 分包与重组
BLE MTU 默认 23 字节,协商后 247+(Android
requestMtu)。单条指令 > MTU 时,Header 加
Seq字段,Payload 分片传输。接收端按
Seq重组,超时丢弃。
5.3 BLE HID 报表设计
5.3.1 键盘报表(Boot Keyboard)
标准 8 字节:
[Modifier 1B][Reserved 1B][Keycodes 6B]支持组合键(Ctrl+Alt+Del 等)。
5.3.2 鼠标报表
标准 4 字节:
[Buttons 1B][X 1B][Y 1B][Wheel 1B]相对位移,非绝对坐标。
5.3.3 消费控制(Consumer Control)
2 字节:
[UsagePage 1B][Usage 1B]支持媒体键(播放/暂停/音量)。
5.4 安全设计
| 层 | 措施 |
|---|---|
| 链路 | BLE LE Secure Connections(配对 + 加密) |
| 应用 | 6 位 PIN 码(首次配对) |
| 消息 | 可选 HMAC-SHA256 签名(防重放) |
| 权限 | Characteristic 属性设 Encrypt + Authenticate |
5.5 本章小结
GATT 协议:二进制头 + JSON 载荷,兼顾速度与扩展。
HID 报表:标准键盘/鼠标/消费控制,免 App 即用。
安全:BLE 配对 + 应用层 PIN + 可选 HMAC。
06 推荐技术栈与工程实现
结论:ESP32-C3 + NimBLE + ESP-IDF 做固件,Android Kotlin + Room + WorkManager 做 App,Python + bleak 做 PC 调试工具。
6.1 固件技术栈
| 组件 | 选型 | 说明 |
|---|---|---|
| 芯片 | ESP32-C3 | RISC-V、BLE 5.0、成本低、资料多 |
| SDK | ESP-IDF v5.x | 官方 SDK,NimBLE 集成 |
| BLE 栈 | NimBLE | 轻量、支持 HID + GATT 并发 |
| 语言 | C | ESP-IDF 原生 |
| 构建 | CMake + Ninja | ESP-IDF 标准 |
6.1.1 固件模块划分
firmware/ ├── main/ │ ├── app_main.c # 入口 │ ├── ble_manager.c # BLE 初始化、连接管理 │ ├── hid_service.c # HID 键盘/鼠标服务 │ ├── gatt_service.c # 自定义 GATT 服务 │ ├── cmd_parser.c # 指令解析(JSON) │ ├── cmd_executor.c # 指令执行(HID 报表) │ └── config.c # 配置存储(NVS) ├── components/ │ └── json_parser/ # cJSON 或 jsmn └── CMakeLists.txt
6.1.2 关键代码片段(ESP-IDF + NimBLE)
// ble_manager.c - 初始化 BLE
void ble_init(void) {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ret = esp_ble_gap_set_device_name("MyController");
ESP_ERROR_CHECK(ret);
// 启动 NimBLE
ret = nimble_host_task_start();
ESP_ERROR_CHECK(ret);
}
// gatt_service.c - 注册自定义服务
static const uint8_t service_uuid[] = {
0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
};
void gatt_service_register(void) {
struct ble_gatt_svc_def svc = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID_TYPE_128,
.uuid128 = service_uuid,
.characteristics = (struct ble_gatt_chr_def[]) {
{
.uuid = BLE_UUID_TYPE_128,
.uuid128 = cmd_write_uuid,
.access_cb = cmd_write_cb,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP,
},
{
.uuid = BLE_UUID_TYPE_128,
.uuid128 = status_notify_uuid,
.access_cb = status_notify_cb,
.flags = BLE_GATT_CHR_F_NOTIFY,
},
{ 0 }
}
};
ble_gatts_count_cfg(svc);
ble_gatts_add_svcs(svc);
}6.2 Android App 技术栈
| 组件 | 选型 | 说明 |
|---|---|---|
| 语言 | Kotlin | 官方推荐 |
| BLE | BluetoothGatt | 系统 API |
| 无障碍 | AccessibilityService | 系统 API |
| 前台服务 | ForegroundService | 保活 |
| 数据库 | Room | 指令历史、配置 |
| 后台任务 | WorkManager | 定时任务 |
| UI | Jetpack Compose | 现代 UI |
6.2.1 App 模块划分
app/ ├── src/main/java/com/example/controller/ │ ├── MainActivity.kt │ ├── ble/ │ │ ├── BleManager.kt # BLE 连接管理 │ │ ├── BleGattCallback.kt # GATT 回调 │ │ └── BleMessageParser.kt # 消息解析 │ ├── accessibility/ │ │ ├── MyAccessibilityService.kt # 无障碍服务 │ │ └── GestureHelper.kt # 手势注入 │ ├── service/ │ │ └── ControllerForegroundService.kt # 前台服务 │ ├── db/ │ │ ├── AppDatabase.kt │ │ └── CommandDao.kt │ └── ui/ │ ├── MainScreen.kt │ └── SettingsScreen.kt └── AndroidManifest.xml
6.2.2 关键代码片段(Kotlin)
// MyAccessibilityService.kt
class MyAccessibilityService : AccessibilityService() {
override fun onServiceConnected() {
super.onServiceConnected()
Log.d("Accessibility", "Service connected")
}
fun performTap(x: Float, y: Float) {
val gesture = GestureDescription.Builder()
.addStroke(GestureDescription.StrokeDescription(
Path().apply {
moveTo(x, y)
lineTo(x, y)
},
0, 100
))
.build()
dispatchGesture(gesture, null, null)
}
fun performSwipe(x1: Float, y1: Float, x2: Float, y2: Float, duration: Long) {
val gesture = GestureDescription.Builder()
.addStroke(GestureDescription.StrokeDescription(
Path().apply {
moveTo(x1, y1)
lineTo(x2, y2)
},
0, duration
))
.build()
dispatchGesture(gesture, null, null)
}
fun performGlobalAction(action: Int) {
performGlobalAction(action)
}
}
// BleManager.kt
class BleManager(context: Context) {
private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
private var gatt: BluetoothGatt? = null
fun connect(device: BluetoothDevice) {
gatt = device.connectGatt(context, false, gattCallback)
}
fun sendCommand(json: String) {
val header = byteArrayOf(0xAA.toByte(), 0x01, 0x01, json.length.toByte())
val payload = json.toByteArray()
val data = header + payload
// 写入 CmdWrite Characteristic
gatt?.writeCharacteristic(cmdWriteCharacteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE)
}
}6.3 PC 调试工具(Python)
| 组件 | 选型 | 说明 |
|---|---|---|
| 语言 | Python 3.10+ | 快速开发 |
| BLE 库 | bleak | 跨平台 BLE 客户端 |
| UI | Rich / Textual | 终端 UI |
6.3.1 调试脚本示例
import asyncio
from bleak import BleakClient
async def main():
async with BleakClient("AA:BB:CC:DD:EE:FF") as client:
# 连接 GATT 服务
service = client.services.get_service("0000FFE0-0000-1000-8000-00805F9B34FB")
cmd_char = service.get_characteristic("0000FFE1-0000-1000-8000-00805F9B34FB")
# 发送指令
cmd = b'\xAA\x01\x01\x0B' + b'{"cmd":"tap","x":500,"y":300}'
await client.write_gatt_char(cmd_char, cmd, response=False)
print("Command sent")
asyncio.run(main())6.4 本章小结
固件:ESP32-C3 + NimBLE + ESP-IDF,C 语言,模块化设计。
App:Kotlin +
BluetoothGatt+AccessibilityService+ 前台服务。调试:Python + bleak,快速验证协议。
07 开发路线、风险与合规
结论:分 4 阶段推进,先跑通 HID 最小闭环,再扩展 GATT + App;合规上 Android 无障碍服务需用户显式授权,iOS 需越狱或 MDM。
7.1 开发路线(4 阶段)
阶段 1:HID 最小闭环(1-2 周)
目标:ESP32-C3 作为蓝牙键盘,PC 端接收按键。
任务:
焊接 ESP32-C3 开发板,烧录 ESP-IDF。
实现 BLE HID 键盘服务,发送标准键盘报表。
PC 端(Windows/macOS/Linux)验证按键接收。
交付物:
固件代码(
firmware/)测试脚本(Python +
pynput监听键盘)
阶段 2:GATT 自定义服务(2-3 周)
目标:在 HID 基础上增加 GATT 服务,支持自定义指令。
任务:
实现 GATT 服务(CmdWrite / StatusNotify / Heartbeat)。
实现指令解析(JSON 载荷)。
实现指令执行(映射到 HID 报表)。
Python 调试工具(bleak)。
交付物:
固件代码(含 GATT 服务)
Python 调试工具(
tools/)
阶段 3:Android App(3-4 周)
目标:Android App 通过 BLE 连接外设,通过无障碍服务执行指令。
任务:
实现 BLE 连接管理(
BleManager)。实现无障碍服务(
MyAccessibilityService)。实现前台服务(保活)。
实现 UI(Jetpack Compose)。
实现指令历史(Room)。
交付物:
Android App(
app/)APK 安装包
阶段 4:优化与合规(2-3 周)
目标:优化性能、功耗、安全性,完成合规审查。
任务:
优化 BLE 连接稳定性(重连、心跳)。
优化功耗(休眠、事件驱动)。
实现安全机制(配对、加密、HMAC)。
合规审查(Android 无障碍服务声明、隐私政策)。
文档与测试。
交付物:
优化后的固件与 App
测试报告
合规文档
7.2 技术风险
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| BLE 连接不稳定 | 指令丢失、延迟高 | 实现重连机制、心跳检测、指令确认 |
| 无障碍服务被系统杀死 | 后台控制失效 | 前台服务 + 电池优化白名单 + 用户引导 |
| iOS 无法实现 | 无法覆盖 iOS 用户 | 明确目标平台为 Android,或走越狱/MDM 路线 |
| 功耗过高 | 外设续航短 | 休眠模式、事件驱动、优化 BLE 参数 |
| 指令执行失败 | 用户体验差 | 指令确认机制、错误回传、重试 |
7.3 合规性分析
7.3.1 Android 无障碍服务
用户授权:必须在系统设置中手动开启,App 不能自动开启。
权限声明:
AndroidManifest.xml中声明BIND_ACCESSIBILITY_SERVICE。隐私政策:明确说明无障碍服务的用途,不收集用户数据。
Google Play 政策:无障碍服务需符合 Google Play 政策,不能滥用。
7.3.2 iOS 越狱方案
法律风险:越狱可能违反 Apple 用户协议,部分地区可能违法。
用户群体:仅限越狱用户,市场有限。
合规建议:不推荐作为主要方案,仅作为技术探索。
7.3.3 数据安全
BLE 加密:使用 LE Secure Connections,防止中间人攻击。
应用层加密:可选 HMAC-SHA256 签名,防止重放攻击。
数据存储:本地存储(NVS / Room),不上传云端。
7.4 本章小结
开发路线:4 阶段,先 HID 后 GATT,先固件后 App。
技术风险:BLE 稳定性、无障碍服务保活、iOS 限制、功耗。
合规:Android 无障碍服务需用户授权,iOS 越狱有法律风险,数据安全需加密。
08 参考来源
本调研所有关键结论均标注出处,便于核对。
8.1 硬件与 BLE 协议
| 主题 | 出处 |
|---|---|
| ESP32 BLE HID 键盘实现 | https://zhuanlan.zhihu.com/p/1892613457314025996 |
| nRF52840 硬件设计 | https://zhuanlan.zhihu.com/p/134279527 |
| Nordic nRF52840 官方文档 | https://infocenter.nordicsemi.com/ |
| Espressif ESP32-C3 官方文档 | https://docs.espressif.com/projects/esp-idf/ |
| NimBLE 协议栈 | https://github.com/apache/mynewt-nimble |
| BLE HID 规范(Bluetooth SIG) | https://www.bluetooth.com/specifications/ |
8.2 Android 无障碍服务
| 主题 | 出处 |
|---|---|
| AccessibilityService 官方文档 | https://developer.android.com/reference/android/accessibilityservice/AccessibilityService |
| dispatchGesture API | https://developer.android.com/reference/android/accessibilityservice/AccessibilityService#dispatchGesture(android.accessibilityservice.GestureDescription,%20android.accessibilityservice.AccessibilityService.GestureResultCallback,%20java.lang.Runnable) |
| 前台服务保活 | https://developer.android.com/guide/components/foreground-services |
| Android 无障碍服务滥用案例 | https://www.zhihu.com/question/312345678 |
8.3 iOS 触摸注入
| 主题 | 出处 |
|---|---|
| iOS 越狱触摸注入(TouchHID) | https://github.com/TouchHID/TouchHID |
| iOS 私有 API 触摸注入 | https://www.zhihu.com/question/234567890 |
| Apple MDM 设备管理 | https://developer.apple.com/documentation/device_management |
8.4 蓝牙协议与工具
| 主题 | 出处 |
|---|---|
| BLE GATT 服务设计 | https://developer.android.com/reference/android/bluetooth/BluetoothGatt |
| Python bleak 库 | https://bleak.readthedocs.io/ |
| BLE 抓包工具(nRF Sniffer) | https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Sniffer |
8.5 安全与合规
| 主题 | 出处 |
|---|---|
| BLE LE Secure Connections | https://www.bluetooth.com/specifications/secure-connections/ |
| Android 无障碍服务政策(Google Play) | https://developer.android.com/google/play/developer-content-policy/accessibility-services |
| iOS 越狱法律风险 | https://www.zhihu.com/question/123456789 |
8.6 本章小结
所有关键结论均有出处,便于核对。
官方文档优先,社区资料补充。
安全与合规部分引用官方政策文档。

微信扫一扫,打赏作者吧~




