仓库简介与示例构成
android-bt-demo 是珠海杰理科技股份有限公司(Jieli-Tech)为蓝牙产品提供的 Android 端测试示例代码集合仓库,当前包含 ATT(GATT over BR/EDR)设备连接示例 ATTConnect,用于帮助客户快速验证杰理蓝牙产品的扫描、连接、数据收发等核心功能。
Purpose and Scope
本页面介绍整个 android-bt-demo 仓库的定位、组织方式与示例构成:
- 仓库定位:说明仓库是什么、由谁维护、解决什么问题。
- 示例构成:说明当前包含的示例工程(
ATTConnect/)及其内部模块结构。 - 快速上手路径:克隆、导入、编译、运行示例的完整流程。
- 示例选择指南:如何根据产品需求挑选合适的示例工程。
ATTConnect 示例的详细使用指南(权限申请、扫描/连接/收发数据的具体代码、调试方法)属于独立子页面,本页只做概览与索引;详细内容请参阅 ATTConnect 示例说明。
概述
Android-BT-Demo 是杰理科技面向其蓝牙芯片产品线发布的 Android 端测试示例集合。它把客户在集成杰理蓝牙方案时常遇到的典型场景——设备扫描、连接管理、GATT 服务发现、数据收发——封装为可直接运行、可直接阅读源码的示例工程。
当前仓库的用例范围:
- ATT 设备(GATT over BR/EDR)连接示例:演示如何在 Android 端通过 GATT 协议(运行在经典蓝牙 BR/EDR 底层之上)与杰理蓝牙产品进行高速数据通讯。
与传统的 GATT over BLE 相比,GATT over BR/EDR(ATT) 走的是 BR/EDR 底层协议,传输速率更高、数据量更大,适合需要大数据吞吐的双模蓝牙设备场景。Android 原生系统同时支持这两种 GATT 通讯方式,示例工程对 Android 系统接口做了封装,客户可以基于这些封装自行实现或改造。
仓库整体架构
仓库采用「单仓库、多示例」的组织方式:每个独立业务场景对应一个顶层示例工程目录,每个示例工程自带完整的 Gradle 工程配置,可单独用 Android Studio 打开、独立编译运行。
flowchart TD
subgraph sg_Repo["android-bt-demo 仓库根目录"]
README["README.md / README_en.md"]
LICENSE["LICENSE (Apache 2.0)"]
subgraph sg_ATT["ATTConnect 示例工程"]
APP["app 应用主模块"]
APKDIR["apk/ 预编译 APK"]
IMGDIR["image/ 图片资源"]
GRADLE["build.gradle.kts / settings.gradle.kts"]
end
end
subgraph sg_AppLayer["app 模块分层 (com.jieli.bt.att)"]
UI["ui/ 界面层<br/>home / device / settings / widget"]
TOOL["tool/ 能力层<br/>scan / ble"]
DATA["data/ 数据层<br/>constant / device / result"]
UTIL["util/ 工具类<br/>蓝牙 / 权限 / 文件"]
end
subgraph sg_Android["Android 系统能力"]
BTAPI["BluetoothAdapter / BluetoothGatt"]
PERM["蓝牙 & 定位权限"]
end
README --> APP
APP --> UI
UI --> TOOL
TOOL --> DATA
TOOL --> BTAPI
APP --> UTIL
APP --> PERM
UI --> UTIL
各组成部分的职责:
| 组成 | 路径 | 职责 |
|---|---|---|
| 仓库说明文档 | README.md / README_en.md | 仓库总览、快速开始、工程结构、示例选择指南、版本历史 |
| 开源协议 | LICENSE | Apache License 2.0 |
| ATT 连接示例 | ATTConnect/ | 独立 Gradle 工程,演示 ATT 设备扫描、连接/断开、数据收发、服务发现 |
| 界面层 | ATTConnect/app/src/main/java/com/jieli/bt/att/ui/ | Home、设备扫描/连接界面、设置界面(含日志管理)、自定义控件 |
| 能力层 | .../tool/ | scan/BtScanner.kt(扫描器)、ble/BleManager.java(连接与数据管理) |
| 数据层 | .../data/ | constant/Config.kt(UUID、MTU 等全局配置)、设备模型、操作结果模型 |
| 工具层 | .../util/ | 蓝牙、权限、文件等通用工具类 |
设计意图:把界面(ui)、能力(tool)、数据(data)分层隔离,使得
BtScanner与BleManager可以脱离 UI 独立复用——客户接入自己产品时,只需替换 UI 并调整Config常量即可。
仓库构成与示例组织
根目录当前包含:
android-bt-demo/
├── ATTConnect/ # 📌 ATT 设备连接示例
├── LICENSE # Apache 2.0 开源协议
└── README.md
其中 ATTConnect 是唯一已发布的示例工程,其目录组织为:
ATTConnect/
├── app/ # 应用主模块
│ ├── src/main/java/com/jieli/bt/att/
│ │ ├── data/ # 配置常量、设备模型、操作结果模型
│ │ ├── tool/ble/ # BLE 设备管理(BleManager.java)
│ │ ├── tool/scan/ # 蓝牙扫描器(BtScanner.kt)
│ │ ├── ui/ # common / device / home / settings / widget
│ │ └── util/ # 蓝牙、权限、文件等工具类
│ ├── libs/ # AAR 依赖库
│ └── build.gradle.kts # 应用构建配置
├── apk/ # 预编译 APK 文件
├── image/ # 图片资源(连接流程图等)
├── build.gradle.kts # 项目级构建配置
├── settings.gradle.kts
├── gradle/ # Gradle Wrapper
└── LICENSE # Apache 2.0 开源协议
仓库刻意保持「一个场景一个目录」的扁平结构:新增示例时不会侵入既有工程,客户也只下载需要的示例目录即可,降低接入成本。
示例核心类
ATTConnect 示例通过三个核心类封装了完整的 ATT 通讯能力,客户集成时通常只需关注它们:
| 类 | 路径 | 职责 |
|---|---|---|
BtScanner | tool/scan/BtScanner.kt | 蓝牙设备扫描器(单例),负责搜索附近的蓝牙设备并回调扫描事件 |
BleManager | tool/ble/BleManager.java | BLE/ATT 设备管理器(单例),负责连接、断开、数据收发与 GATT 服务发现 |
Config | data/constant/Config.kt | 全局配置常量,包含服务/特征 UUID、MTU 等参数 |
BtScanner 与 BleManager 均采用单例模式(getInstance())暴露给 UI 层,简化了跨界面共享蓝牙状态的问题;Config 则是设备端协议契约在 APP 端的唯一配置入口。
支持的平台与设备
| 项目 | 说明 |
|---|---|
| 最低 Android 版本 | Android 5.0(API 21) |
| 目标/编译版本 | Android 16+(API 36+,仓库级说明);ATTConnect 工程目标 Android 14(API 34) |
| 开发语言 | Kotlin / Java |
| 支持的协议 | GATT over BLE、GATT over BR/EDR(ATT),均 ✅ 支持 |
注意:Android 端对 ATT(GATT over BR/EDR)功能的支持可能存在兼容性问题,官方建议在目标设备上进行充分测试。
快速开始
克隆仓库
git clone https://github.com/Jieli-Tech/android-bt-demo.git
cd android-bt-demo/ATTConnect
导入并运行
- 打开 Android Studio;
- 点击 File → Open,选择
ATTConnect/目录; - 等待 Gradle 同步完成;
- 连接 Android 手机,点击 Run → Run 'app';
- 在手机上打开 APP,测试蓝牙功能。
编译 APK
# 编译 Debug 版本
./gradlew assembleDebug # Linux/macOS
gradlew.bat assembleDebug # Windows
# 编译 Release 版本
./gradlew assembleRelease
# 安装到已连接设备
./gradlew installDebug
APK 默认生成路径:app/build/outputs/apk/debug/。
示例选择指南
| 项目 | 说明 |
|---|---|
| 适用场景 | 双模蓝牙设备(经典蓝牙 + BLE),需要通过 GATT 协议进行高速数据通讯 |
| 关键特性 | ATT 设备扫描、连接/断开管理、数据收发、GATT 服务发现 |
| 核心类 | BtScanner(蓝牙扫描)、BleManager(BLE/ATT 设备管理) |
| 参考文档 | ATTConnect 详细说明 |
当前仓库仅有 ATT 连接示例一个用例;根 README 明确标注「更多示例持续更新中」,后续新增示例(如经典 SPP、BLE 纯低功耗场景等)会以并列的顶层目录形式加入,选择时只需对照「适用场景」一列即可。
核心流程:ATT 设备连接与数据通讯
示例 APP 的端到端交互流程如下:先扫描发现设备,再以 TRANSPORT_BREDR 传输方式发起连接,连接成功后通过 GATT 特征进行数据收发。
sequenceDiagram
participant U as App UI (device 界面)
participant S as BtScanner (单例)
participant M as BleManager (单例)
participant A as Android 蓝牙栈
participant D as 杰理蓝牙设备
U->>S: startScan(30 * 1000L, callback)
S->>A: startDiscovery()
A-->>S: onDiscoveryDevice(ScanDeviceInfo)
S-->>U: 回调扫描到的设备列表
U->>M: connectBleDevice(device, TRANSPORT_BREDR)
M->>A: connectGatt(TRANSPORT_BREDR)
A-->>M: onConnectionStateChange(STATE_CONNECTED)
M-->>U: onBleConnection(device, STATE_CONNECTED)
U->>M: writeDataByBleAsync(device, serviceUuid, writeUuid, data, callback)
M->>A: writeCharacteristic(...)
A-->>M: onCharacteristicWrite(result)
M-->>U: onBleResult(result)
A-->>M: onCharacteristicChanged(notifyUuid, data)
M-->>U: onBleDataNotification(serviceUuid, charUuid, data)
U->>M: disconnectBleDevice(device)
M->>A: disconnect()
关键设计点:
- 必须显式指定 ATT 传输方式:调用
connectBleDevice(device, BleManager.TRANSPORT_BREDR)时第二个参数指明走经典蓝牙 GATT;否则默认按 BLE 设备连接。 - 连接状态复用系统常量:回调中的
status直接复用BluetoothProfile#STATE_xxx(STATE_CONNECTED/STATE_CONNECTING/STATE_DISCONNECTED),客户无需记忆新枚举。 - 数据收发为异步回调:发送通过
OnWriteDataCallback返回结果,接收通过onBleDataNotification上报,并可按Config.BLE_SERVICE_UUID与Config.BLE_NOTIFY_UUID过滤数据来源。
使用示例
以下代码均摘自 ATTConnect 示例说明,展示了核心类的典型调用方式。
扫描 ATT 设备
使用 BtScanner 启动扫描,并通过 IBtScanCallback 接收蓝牙开关、扫描状态、设备与失败事件:
// 初始化蓝牙扫描器对象
val btScanner = BtScanner.getInstance()
// 扫描设备
// timeout --- 扫描超时限制
// callback --- 扫描事件回调
btScanner.startScan(30 * 1000L, object : IBtScanCallback {
override fun onAdapterChange(bEnabled: Boolean) {
// 回调蓝牙开关状态
}
override fun onDiscoveryState(bStart: Boolean) {
// 回调扫描设备状态
}
override fun onDiscoveryDevice(scanDeviceInfo: ScanDeviceInfo?) {
// 回调搜索到的设备
}
override fun onDiscoveryFail(code: Int, message: String?) {
// 回调搜索设备失败
}
})
Source: ATTConnect/README.md
连接 ATT 设备
使用 BleManager 连接设备,注意必须以 TRANSPORT_BREDR 指明 ATT 连接方式:
// 初始化 BleManager 对象
val bleManager = BleManager.getInstance()
// 注册连接状态回调
val callback = object : BleEventCallback(){
override fun onBleConnection(device: BluetoothDevice?, status: Int) {
// 回调 BLE 设备连接状态
// status --- 连接状态,复用 BluetoothProfile#STATE_xxx 状态
// BluetoothProfile.STATE_CONNECTED --- 已连接
// BluetoothProfile.STATE_CONNECTING --- 连接中
// BluetoothProfile.STATE_DISCONNECTED --- 已断开
}
}
bleManager.registerBleEventCallback(callback)
// 连接 ATT 设备
// 必须指明是连接 ATT 方式,否则按照 BLE 设备连接
val ret = bleManager.connectBleDevice(device, BleManager.TRANSPORT_BREDR)
// ret 为操作结果
if (!ret) {
// 连接失败,一般为设备正在连接中。
}
// 不需要监听连接状态时,记得移除监听器
// bleManager.unregisterBleEventCallback(callback)
Source: ATTConnect/README.md
发送数据
通过 writeDataByBleAsync 异步发送数据,写入指定服务与特征 UUID:
// 初始化 BleManager 对象
val bleManager = BleManager.getInstance()
// 异步发送数据
bleManager.writeDataByBleAsync(
device,
Config.BLE_SERVICE_UUID,
Config.BLE_WRITE_UUID,
data,
object : OnWriteDataCallback {
override fun onBleResult(
device: BluetoothDevice?,
serviceUUID: UUID?,
characteristicUUID: UUID?,
result: Boolean,
data: ByteArray?
) {
// 发送数据的回调
}
}
)
Source: ATTConnect/README.md
接收设备端数据
注册 BleEventCallback 后,在 onBleDataNotification 中按 UUID 过滤并处理接收到的数据:
// 初始化 BleManager 对象
val bleManager = BleManager.getInstance()
// 注册连接状态回调
val callback = object : BleEventCallback() {
override fun onBleDataNotification(
device: BluetoothDevice?,
serviceUuid: UUID?,
characteristicsUuid: UUID?,
data: ByteArray?
) {
// 回调接收到的数据
if (Config.BLE_SERVICE_UUID == serviceUuid && Config.BLE_NOTIFY_UUID == characteristicsUuid) {
// 可以对数据进行过滤
}
}
}
bleManager.registerBleEventCallback(callback)
Source: ATTConnect/README.md
断开连接
// 初始化 BleManager 对象
val bleManager = BleManager.getInstance()
// 注册连接状态回调(同上)
// ...
// 断开设备连接
bleManager.disconnectBleDevice(device)
Source: ATTConnect/README.md
配置说明
ATTConnect 的全局配置集中在 com/jieli/bt/att/data/constant/Config.kt,客户接入自有设备时必须根据设备端协议修改这些常量:
object Config {
/**
* 是否跳过没有名字的设备
*/
const val IS_FILTER_NO_NAME_DEVICE = false
/**
* 调整 BLE 的 MTU
* <p>
* 注意: GATT over BR/EDR 不支持调整 MTU
* </p>
*/
const val REQUEST_BLE_MTU = 509
/**
* BLE 服务 UUID
* <p>
* BLE: 服务 UUID 是 0xae00 <br/>
* GATT over BR/EDR: 服务 UUID 是 0x1801
* </p>
*/
val BLE_SERVICE_UUID: UUID = UuidUtil.to16BitUUID("1801")
/**
* BLE 写特征 UUID
*/
val BLE_WRITE_UUID: UUID = UuidUtil.to16BitUUID("ae01")
/**
* BLE 通知特征 UUID
*/
val BLE_NOTIFY_UUID: UUID = UuidUtil.to16BitUUID("ae02")
}
Source: ATTConnect/README.md
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
IS_FILTER_NO_NAME_DEVICE | Boolean | false | 扫描时是否跳过无名称设备 |
REQUEST_BLE_MTU | Int | 509 | BLE 请求的 MTU 大小;GATT over BR/EDR 不支持调整 MTU |
BLE_SERVICE_UUID | UUID | 0x1801 | 服务 UUID(ATT/GATT over BR/EDR 场景) |
BLE_WRITE_UUID | UUID | 0xae01 | 写特征 UUID |
BLE_NOTIFY_UUID | UUID | 0xae02 | 通知特征 UUID |
💡 提示:请根据实际设备端的 UUID 配置修改上述常量,确保 APP 端与设备端的 UUID 一致。
失败模式与边界情况
结合 ATTConnect 使用指南,以下是该示例涉及的主要边界与兼容性约束:
- ATT 兼容性风险:Android 端对 ATT(GATT over BR/EDR)功能的支持存在兼容性问题,官方明确建议在目标设备上充分测试。
- 必须为双模设备:连接 GATT over BR/EDR 设备时,设备必须是双模设备(经典蓝牙 + BLE)。
- 连接前必须配对:BR/EDR 底层协议要求先配对再连接,这是与 BLE 连接流程最大的差异点。
- 不支持 MTU 调整:MTU 调整是 BLE 底层协议的能力,BR/EDR 底层协议并不支持,因此
REQUEST_BLE_MTU仅对传统 BLE 连接生效(取值范围 [20, 509])。 - 连接重入:
connectBleDevice返回false时通常表示设备正在连接中,调用方应避免在连接中重复发起连接。 - 监听器生命周期:注册的
BleEventCallback在使用完毕后应调用unregisterBleEventCallback移除,防止内存泄漏与无关回调。
调试与日志
- 调试开关:通过
JL_Log.setLog(isLog)与JL_Log.setSaveLogFile(isLog, context)开启日志;开启后可通过JL_Log.configure(...)设置isLogcatCrash = true记录崩溃日志。 - 日志格式:
app_log_[时间戳].txt。 - 获取日志:APP 设置界面 → 日志存储位置 → 选择异常时间点最近的日志,可分享或下载;支持清除全部日志、侧滑删除、点击浏览。
版本历史与许可证
| 版本 | 日期 | 修改记录 |
|---|---|---|
| 1.0.0 | 2025/03/31 | 初始化版本,新增 ATT 连接示例代码 |
- 仓库许可证:Apache License 2.0,Copyright 2024 珠海市杰理科技股份有限公司。
- 社区支持:Gitee 组织 JieLi-Tech,问题反馈见 Issue 追踪。
- 在线文档中心:https://doc.zh-jieli.com/vue
相关链接
- ATTConnect 示例详细说明:示例的完整使用指南(权限申请、扫描/连接/收发代码、配置、调试、注意事项)
- ATTConnect 英文说明
- 仓库英文总览
- 仓库根 README
- 开源许可证