# apk_bluetooth_utils **Repository Path**: fancy171101034/apk_bluetooth_utils ## Basic Information - **Project Name**: apk_bluetooth_utils - **Description**: 一个轻量级原生 Android BLE 调试工具,用于扫描、连接 BLE 设备,发送快捷指令、文件,订阅通知并查看收发日志。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-07-07 - **Last Updated**: 2026-07-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # BluetoothTools 一个轻量级原生 Android BLE 调试工具,用于扫描、连接 BLE 设备,发送快捷指令、文件,订阅通知并查看收发日志。 ## 功能 - 设备扫描:按 RSSI 降序展示,支持按设备名称或 MAC 实时过滤,过滤忽略大小写。 - 设备连接:显示当前连接设备,已连接设备不可重复连接;连接后自动发现服务并协商 MTU(247)。 - 快捷指令:内置 `放平`、`零重力`、`配网` 三条 Hex 指令。 - 指令编辑:长按快捷指令可修改名称、内容和格式,支持新增自定义指令。 - 手动发送:支持 Hex / ASCII 输入,支持单次发送和循环发送;发送时短震动反馈。 - 文件发送:选择文件后按 MTU 自动分包传输,实时显示进度与包数,支持取消。 - 订阅通知:连接后在“订阅”页选择 Notify / Indicate 特征值订阅。 - 数据日志:记录 Tx / Rx / 系统日志,支持 Hex / ASCII 显示和过滤。 - 主题切换:内置 经典绿 / 水色 / 夜间 / 石墨 四种主题。 - 权限检查:启动时检查蓝牙、定位服务和运行时权限。 ## 默认快捷指令 ```json [ { "name": "放平", "content": "AA03000A00040100000008F2F355", "format": "hex" }, { "name": "零重力", "content": "AA03000A00040100100000EAF355", "format": "hex" }, { "name": "配网", "content": "0D0A737369643A6B6565736F6E2D6F66666963657077643A536D61727462656432303235400A0D", "format": "hex" } ] ``` `配网` 指令中的 `0D0A` / `0A0D` 会按 Hex 原样转成字节发送,不会按字符串截断。 ## 界面预览 | 设备 | 日志 | |-------------------------------------------------------|-------------------------------------------------------| | 设备页 | 日志页 | | 订阅 | 设置 | | --- | --- | | 订阅页 | 设置页 | ## 代码结构 ```text app/src/main/java/com/zxh/www/ MainActivity.kt Activity 入口,只负责创建 Controller 和 UI bluetooth/BluetoothController.kt BLE 扫描、连接、写入、订阅、日志、权限状态 model/Models.kt 设备、特征值、指令、日志等数据模型 util/BleFormat.kt Hex/ASCII 转换、MAC 显示等工具 ui/BluetoothToolsApp.kt 根 UI、底部导航、权限检查页 ui/DeviceTab.kt 设备扫描、过滤、连接、快捷发送 ui/CommandTab.kt 快捷指令、手动发送、循环发送、文件发送 ui/LogTab.kt 日志展示和过滤 ui/SubscribeTab.kt 通知订阅管理 ui/Components.kt 通用 UI 组件 ui/theme/ 主题(颜色、字体、风格) ``` ## 蓝牙发送逻辑 参考 `utools_bluetooth_utils` 的实现: 1. Hex 输入先清理空格、`0x` 和非 Hex 字符。 2. 校验长度必须为偶数。 3. 转成 `ByteArray`。 4. 优先使用支持 `PROPERTY_WRITE` 的特征值。 5. 写类型选择: - 文件传输优先使用 `WRITE_TYPE_NO_RESPONSE`(无响应,吞吐高)。 - 仅当特征值不支持 `WRITE` 且支持 `WRITE_NO_RESPONSE` 时,使用 `WRITE_TYPE_NO_RESPONSE`。 - 其余使用 `WRITE_TYPE_DEFAULT`(带响应)。 6. Android 13+ 使用 `BluetoothGatt.writeCharacteristic(characteristic, bytes, writeType)`。 ## MTU 与分包 - 连接后先 `discoverServices()`,服务发现完成后再 `requestMtu(247)`,避免两个 GATT 操作并发导致 MTU 协商失败。 - `onMtuChanged` 回调成功后 `mtuPayloadSize = mtu - 3`(默认 244 字节)。 - `isBusy` 保持到 MTU 协商完成(或 2 秒超时保底)才释放,避免在 MTU 未生效时发送文件被拆成 20 字节小包。 - 发送时按 `mtuPayloadSize` 切包;若收到 status 13(数据包过长),自动降级为 20 字节小包重试一次。 ## 构建 ```bash cd /Users/keeson/AndroidStudioProjects/BluetoothTools ./gradlew assembleDebug ``` APK 输出: ```text app/build/outputs/apk/debug/zxh-bluetooth-tools-debug.apk ``` 安装到手机: ```bash adb install -r app/build/outputs/apk/debug/zxh-bluetooth-tools-debug.apk ``` ## 后续维护建议 - 如果某个设备必须写入固定特征值,可以在 `BluetoothController.collectCharacteristics()` 中按 UUID 优先选择。 - 如果扫描不到设备,优先检查系统蓝牙、定位服务、附近设备权限和应用定位权限。 - 如果设备使用 Notify 返回数据,需要先在“订阅”页点击对应特征值订阅。 - 如果发送失败,先确认“指令”页的可写特征值是否正确。 - 如果文件发送后端数据缺失,可能是 NO_RESPONSE 模式下对端处理不过来丢包,可在 `sendBytes` 中改为 `WRITE_TYPE_DEFAULT`。