# BluetoothDemo **Repository Path**: nnddkj/bluetooth-demo ## Basic Information - **Project Name**: BluetoothDemo - **Description**: 本项目包含一个功能完整的 Android 蓝牙库 `bluetoothlib` 和一个功能测试APP `app - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-14 - **Last Updated**: 2026-08-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 蓝牙库(bluetoothlib)使用说明文档 > 开发者:宁工 电话:17776688224 ## 一、项目概述 本项目包含一个功能完整的 Android 蓝牙库 `bluetoothlib` 和一个功能测试APP `app`。 最近在找工作,有内推最好了 | 模块 | 说明 | | --- | --- | | `bluetoothlib` | 蓝牙库(Android Library),封装传统蓝牙与BLE蓝牙全部功能,含权限与版本兼容处理 | | `app` | 蓝牙测试工具APP,调用蓝牙库实现全部功能的界面化测试,可直接打包用于硬件联调 | ### 系统兼容范围 | 项目 | 版本 | | --- | --- | | 最低支持 | **Android 5.0(API 21)** | | 最高适配 | **Android 17(API 37,targetSdk 37)** | ### 核心特性 - ✅ **传统蓝牙与BLE蓝牙独立封装**:两个管理器互相独立、互不影响,可单独使用 - ✅ **开箱即用**:单例模式 + 回调接口,几行代码完成扫描、连接、收发数据 - ✅ **权限与兼容库内处理**:安卓5~17各版本权限差异、API差异均在库内完成,APP几乎零适配成本 - ✅ **配置灵活**:`BluetoothConfig` Builder模式,扫描超时/自动重连/UUID/MTU等全部可配置 - ✅ **兼容性强**:支持 Java 和 Kotlin 项目调用 - ✅ **架构无关**:支持普通安卓项目(无模式)和 MVVM 架构项目 - ✅ **线程安全**:任意线程调用,回调自动切换到主线程 - ✅ **商业级封装**:混淆规则、中文注解、错误码体系齐全,可直接用于商业项目 --- ## 二、Library 文件结构说明 ``` bluetoothlib/src/main/java/com/nyw/bluetoothlib/ ├── BluetoothHelper.kt ★ 库统一入口(门面类),init/classic()/ble()/permission() ├── common/ 公共定义(传统蓝牙与BLE共用) │ ├── BluetoothState.kt 蓝牙状态枚举(扫描中/已连接/已断开等) │ ├── BluetoothDeviceInfo.kt 设备信息封装类(MAC/名称/信号/配对状态) │ ├── BluetoothConfig.kt 蓝牙配置类(Builder模式,全部配置项) │ ├── BluetoothPermissionHelper.kt ★ 权限与兼容性助手(安卓5~17权限统一处理) │ ├── HexUtil.kt 十六进制数据转换工具(HEX收发必备) │ └── BleGattInfo.kt BLE服务/特征/描述符信息封装类 ├── classic/ 传统蓝牙模块(独立) │ ├── ClassicBluetoothManager.kt ★ 传统蓝牙管理器(扫描/配对/连接/收发/重连) │ └── ClassicBluetoothListener.kt 传统蓝牙事件回调接口 └── ble/ BLE蓝牙模块(独立) ├── BleBluetoothManager.kt ★ BLE蓝牙管理器(扫描/GATT/服务/读写/通知/RSSI) └── BleBluetoothListener.kt BLE蓝牙事件回调接口 ``` | 文件 | 作用 | 何时使用 | | --- | --- | --- | | `BluetoothHelper` | 库总入口,负责初始化 | 应用启动时调用 init() | | `BluetoothPermissionHelper` | 权限申请与蓝牙开关 | 进入蓝牙功能前调用 | | `BluetoothConfig` | 全局配置 | 初始化时传入自定义配置 | | `ClassicBluetoothManager` | 传统蓝牙所有功能 | 串口模块(HC-05等)开发 | | `BleBluetoothManager` | BLE蓝牙所有功能 | 低功耗外设(手环/传感器)开发 | | `BluetoothDeviceInfo` | 设备信息 | 扫描结果、连接参数 | | `BleServiceInfo/BleCharacteristicInfo` | BLE服务与特征 | 服务选择与数据读写 | | `HexUtil` | HEX/字节互转 | 硬件调试收发十六进制数据 | --- ## 三、快速集成(新项目) ### 1. 引入库模块 将 `bluetoothlib` 文件夹复制到新项目根目录,在 `settings.gradle.kts` 添加: ```kotlin include(":bluetoothlib") ``` 在 `app/build.gradle.kts` 添加依赖: ```kotlin dependencies { implementation(project(":bluetoothlib")) } ``` > 库的 AndroidManifest 已声明全部蓝牙权限,会自动合并到APP,无需手动声明权限。 ### 2. 初始化(建议在 Application 中) ```kotlin class App : Application() { override fun onCreate() { super.onCreate() val config = BluetoothConfig.Builder() .setLogEnabled(true) // 调试日志开关 .setScanTimeout(15000) // 扫描超时(ms) .setAutoReconnect(true) // 自动重连开关 .setMaxReconnectAttempts(3) // 最大重连次数 .setReconnectInterval(3000) // 重连间隔(ms) .setClassicUuid(BluetoothConfig.UUID_SPP) // 传统蓝牙UUID .setBleMtuSize(512) // BLE MTU大小 .build() BluetoothHelper.init(this, config) // 初始化(也可用initClassic/initBle只初始化一个) } } ``` Java 写法: ```java BluetoothConfig config = new BluetoothConfig.Builder() .setLogEnabled(true) .setAutoReconnect(true) .build(); BluetoothHelper.init(this, config); ``` ### 3. 运行时权限与蓝牙开关(库内已处理版本兼容) 静态权限声明已由库的 AndroidManifest 自动合并到APP,**无需手动声明**。 运行时权限各版本差异如下,库内 `BluetoothPermissionHelper` 已自动判断: | 安卓版本 | 需要的运行时权限 | | --- | --- | | Android 12+(API 31+) | BLUETOOTH_SCAN、BLUETOOTH_CONNECT、ACCESS_FINE_LOCATION | | Android 6~11(API 23~30) | ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION(扫描需要) | | Android 5.x(API 21~22) | 无需运行时权限 | **接入方式(推荐,照抄本Demo的 MainActivity 即可):** 由于运行时权限申请必须与 Activity 交互,库提供"发起请求 + APP转发结果"的交互方式: ```kotlin // ① 发起权限申请(库自动判断当前系统所需权限清单) BluetoothPermissionHelper.requestPermissions(this, object : BluetoothPermissionHelper.PermissionCallback { override fun onPermissionResult(allGranted: Boolean, missingPermissions: List) { if (allGranted) { /* 权限齐全,继续使用蓝牙功能 */ } } }) // ② 弹出系统对话框引导开启蓝牙 BluetoothPermissionHelper.requestEnableBluetooth(this, object : BluetoothPermissionHelper.EnableBluetoothCallback { override fun onResult(enabled: Boolean) { /* enabled=蓝牙已开启 */ } }) // ③ Activity中转发结果(必须实现,照抄即可) override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) BluetoothPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults) } @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) BluetoothPermissionHelper.onEnableBluetoothResult(requestCode, resultCode) } ``` **方式B(APP有自己的权限框架,如ActivityResult API):** ```kotlin // 只取库生成的权限清单,自行申请 val permissions = BluetoothPermissionHelper.getRequiredPermissions(context) // 自行申请后检查 val ok = BluetoothPermissionHelper.hasAllPermissions(context) ``` Java 写法: ```java BluetoothPermissionHelper.requestPermissions(this, (allGranted, missing) -> { }); // onRequestPermissionsResult 中转发: BluetoothPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults); ``` --- ## 四、传统蓝牙使用教程 适用硬件:HC-05、HC-06 等蓝牙串口模块。 ### 完整流程(Kotlin) ```kotlin // 1. 获取管理器并设置回调 val classic = BluetoothHelper.classic() classic.setListener(object : ClassicBluetoothListener { override fun onDeviceFound(device: BluetoothDeviceInfo) { // 扫描到设备:显示到列表 } override fun onConnected(device: BluetoothDeviceInfo) { // 连接成功:可以收发数据了 } override fun onDataReceived(data: ByteArray) { // 接收到数据 val text = String(data) } override fun onError(errorCode: Int, errorMsg: String) { // 错误处理 } }) // 2. 扫描设备(结果通过 onDeviceFound 回调) classic.startScan() // 3. 配对设备(可选,部分设备首次连接前需先配对,长按列表项场景) classic.createBond(device) // 配对状态通过 onBondStateChanged 回调 // 4. 连接设备(也可先 classic.getBondedDevices() 获取已配对设备直接连) classic.connect(device) // 5. 发送数据 classic.sendText("Hello") // 发送字符串 classic.sendData(byteArrayOf(0x01)) // 发送字节 // 发送HEX数据(配合HexUtil工具): classic.sendData(HexUtil.hexStringToBytes("0A 1B 2C")!!) // 6. 断开与释放 classic.disconnect() classic.release() ``` ### API 速查表 | 方法 | 说明 | | --- | --- | | `init(context, config)` | 初始化(必须最先调用) | | `setListener(listener)` | 设置事件回调 | | `startScan()` / `stopScan()` | 开始/停止扫描 | | `getBondedDevices()` | 获取已配对设备列表 | | `createBond(device)` | 发起设备配对(状态通过 onBondStateChanged 回调) | | `connect(device)` / `connect(address)` | 连接设备 | | `disconnect()` | 断开连接 | | `sendData(bytes)` / `sendText(text)` | 发送数据(内置发送间隔控制) | | `isConnected()` / `getState()` | 查询连接状态 | | `release()` | 释放资源 | --- ## 五、BLE蓝牙使用教程 适用硬件:BLE手环、传感器、ESP32 BLE 等低功耗蓝牙设备。 ### 完整流程(Kotlin) ```kotlin // 1. 获取管理器并设置回调 val ble = BluetoothHelper.ble() ble.setListener(object : BleBluetoothListener { override fun onDeviceFound(device: BluetoothDeviceInfo) { // 扫描到BLE设备 } override fun onConnected(device: BluetoothDeviceInfo) { // 连接成功(库会自动请求MTU并发现服务) } override fun onServicesDiscovered(services: List) { // 服务发现完成:选择需要的服务和特征 } override fun onCharacteristicChanged(characteristic: BleCharacteristicInfo, value: ByteArray) { // 接收到设备通知数据 } override fun onError(errorCode: Int, errorMsg: String) { // 错误处理 } }) // 2. 扫描BLE设备(可按服务UUID过滤:startScan(listOf(uuid))) ble.startScan() // 3. 连接设备(连接后自动发现服务) ble.connect(device) // 4. 开启通知(接收设备主动推送的数据) ble.enableNotification(serviceUuid, charUuid, true) // 5. 写入数据 / 读取数据 ble.writeCharacteristic(serviceUuid, charUuid, "Hello".toByteArray()) // 无响应写(速度快)+ HEX数据(配合HexUtil): ble.writeCharacteristic(serviceUuid, charUuid, HexUtil.hexStringToBytes("0A 1B")!!, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) ble.readCharacteristic(serviceUuid, charUuid) // 6. 读取信号强度(结果通过 onRssiRead 回调) ble.readRemoteRssi() // 7. 断开与释放 ble.disconnect() ble.release() ``` ### API 速查表 | 方法 | 说明 | | --- | --- | | `init(context, config)` | 初始化(必须最先调用) | | `setListener(listener)` | 设置事件回调 | | `startScan(uuids?)` / `stopScan()` | 扫描(可按服务UUID过滤) | | `connect(device)` / `connect(address)` | GATT连接 | | `disconnect()` | 断开连接 | | `getDiscoveredServices()` | 获取已发现的服务列表 | | `writeCharacteristic(serviceUuid, charUuid, data, writeType)` | 写入特征数据 | | `readCharacteristic(serviceUuid, charUuid)` | 读取特征数据 | | `enableNotification(serviceUuid, charUuid, enable)` | 开启/关闭通知 | | `isNotificationEnabled(serviceUuid, charUuid)` | 查询通知是否已开启 | | `requestMtu(mtu)` / `getCurrentMtu()` | 手动请求MTU / 获取当前MTU | | `readRemoteRssi()` | 读取信号强度(onRssiRead回调) | | `requestConnectionPriority(priority)` | 设置连接优先级(0低功耗/1平衡/2高) | | `release()` | 释放资源 | --- ## 六、配置项完整说明(BluetoothConfig) | 配置项 | 方法 | 默认值 | 说明 | | --- | --- | --- | --- | | 日志开关 | `setLogEnabled` | true | 是否打印调试日志 | | 扫描超时 | `setScanTimeout` | 15000ms | 超时自动停止扫描 | | 连接超时 | `setConnectTimeout` | 10000ms | BLE连接超时保护 | | 自动重连 | `setAutoReconnect` | false | 断开后自动重连 | | 重连次数 | `setMaxReconnectAttempts` | 5 | 最大重连次数 | | 重连间隔 | `setReconnectInterval` | 3000ms | 每次重连间隔 | | 传统蓝牙UUID | `setClassicUuid` | SPP UUID | 串口协议UUID,可按硬件修改 | | BLE MTU | `setBleMtuSize` | 512 | 请求的MTU大小(23~517) | | BLE连接优先级 | `setBleConnectionPriority` | 0 | 0低功耗/1平衡/2高优先级 | | 发送间隔 | `setSendInterval` | 20ms | 数据发送最小间隔 | --- ## 七、在不同项目架构中使用 ### 普通项目(无模式) 在 Activity 中直接使用,Activity 实现 Listener 接口即可(参考本Demo的 `ClassicBluetoothActivity` / `BleBluetoothActivity`)。 ### MVVM 项目 管理器是应用级单例,生命周期长于 ViewModel,可在 ViewModel 中安全使用。用 LiveData/StateFlow 包装回调数据: ```kotlin class BleViewModel : ViewModel() { private val ble = BluetoothHelper.ble() private val _devices = MutableLiveData>() val devices: LiveData> = _devices private val _receivedData = MutableLiveData() val receivedData: LiveData = _receivedData init { ble.setListener(object : BleBluetoothListener { override fun onDeviceFound(device: BluetoothDeviceInfo) { _devices.postValue(ble.getDiscoveredDevices()) } override fun onConnected(device: BluetoothDeviceInfo) {} override fun onServicesDiscovered(services: List) {} override fun onCharacteristicChanged(characteristic: BleCharacteristicInfo, value: ByteArray) { _receivedData.postValue(value) } override fun onError(errorCode: Int, errorMsg: String) {} }) } fun scan() = ble.startScan() fun connect(device: BluetoothDeviceInfo) = ble.connect(device) fun send(serviceUuid: UUID, charUuid: UUID, data: ByteArray) = ble.writeCharacteristic(serviceUuid, charUuid, data) override fun onCleared() { super.onCleared() ble.setListener(null) // 解除监听,避免持有ViewModel引用 } } ``` ### Java 项目 所有API均提供Java友好调用方式(`@JvmStatic`静态方法、Builder模式): ```java ClassicBluetoothManager classic = BluetoothHelper.classic(); classic.setListener(new ClassicBluetoothListener() { @Override public void onDeviceFound(BluetoothDeviceInfo device) { } @Override public void onConnected(BluetoothDeviceInfo device) { } @Override public void onDataReceived(byte[] data) { } @Override public void onError(int errorCode, String errorMsg) { } }); classic.startScan(); ``` --- ## 八、测试工具APP功能说明 `app` 模块是一个完整的蓝牙测试工具,已覆盖库的全部功能,硬件开发联调时可直接打包使用: | 页面 | 文件 | 测试功能 | | --- | --- | --- | | 主页 | `MainActivity` | 库权限助手申请权限、蓝牙开关检测、功能入口 | | 传统蓝牙测试 | `ClassicBluetoothActivity` | 扫描、已配对设备、长按配对、连接/断开、文本/HEX收发、配对状态、日志 | | BLE蓝牙测试 | `BleBluetoothActivity` | 扫描、连接、服务/特征选择、通知、读/写(文本/HEX/无响应写)、MTU、RSSI、日志 | 库功能覆盖对照表(库能力 ↔ 测试APP入口): | 库功能 | 测试APP中的操作入口 | | --- | --- | | 权限申请/蓝牙开关 | 主页自动处理(BluetoothPermissionHelper) | | 扫描/停止扫描 | 两个测试页[开始扫描/停止扫描]按钮 | | 已配对设备 | 传统页[已配对设备]按钮 | | 设备配对createBond | 传统页长按设备项 | | 连接/断开 | 点击设备项连接,[断开连接]按钮 | | 传统蓝牙文本/HEX收发 | 传统页输入框 + [HEX发送]开关 + [发送] | | BLE通知/读/写 | BLE页服务特征下拉框 + 对应按钮 | | BLE HEX写/无响应写 | BLE页[HEX写入]、[无响应写]开关 | | MTU协商 | 连接后自动协商,日志显示结果 | | RSSI读取 | BLE页[读RSSI]按钮 | | 自动重连 | App.kt中已开启,意外断开自动重连 | 硬件联调步骤: 1. 打开APP,首次使用授予权限并允许开启蓝牙 2. 进入对应测试页面,点击"开始扫描",等待目标设备出现 3. 点击设备项连接(传统蓝牙首次连接可先长按配对) 4. BLE:等待服务发现完成后选择服务与特征,开启通知即可接收数据,输入数据点"写入"即可发送 5. 传统蓝牙:连接成功后直接输入数据发送,接收数据实时显示在日志区(同时显示文本与HEX) --- ## 九、错误码说明 ### 传统蓝牙(1001~1009) | 错误码 | 说明 | | --- | --- | | 1001 | 蓝牙未开启或设备不支持 | | 1002 | 扫描启动失败 | | 1003 | 连接失败 | | 1004 | 数据发送失败 | | 1005 | 数据接收失败 | | 1006 | 未初始化(请先调用init) | | 1007 | 未连接设备 | | 1008 | 权限不足 | | 1009 | 配对失败 | ### BLE蓝牙(2001~2010) | 错误码 | 说明 | | --- | --- | | 2001 | 蓝牙未开启或设备不支持 | | 2002 | 扫描启动失败 | | 2003 | 连接失败 | | 2004 | 服务发现失败 | | 2005 | 特征操作失败(读/写/通知) | | 2006 | 未初始化(请先调用init) | | 2007 | 未连接设备 | | 2008 | 找不到指定特征 | | 2009 | 权限不足 | | 2010 | RSSI读取失败 | --- ## 十、常见问题 **Q1:扫描不到设备?** - 确认已授予权限(Android 12+为附近设备权限,以下为定位权限且需开启GPS) - 确认目标设备未被其他手机连接占用 **Q2:传统蓝牙连接失败?** - 先在系统设置中配对一次设备 - 确认配置的连接UUID与硬件一致(默认SPP,部分模块需自定义UUID) **Q3:BLE写入数据失败(status=5)?** - 检查特征是否支持写属性 - 单次写入数据量不要超过 MTU-3 字节 **Q4:如何只使用其中一种蓝牙?** - 初始化时用 `BluetoothHelper.initClassic()` 或 `BluetoothHelper.initBle()` 即可,两个模块完全独立互不影响。 **Q5:集成到新项目需要考虑系统兼容吗?** - 不需要。库支持 Android 5.0(API 21) ~ Android 17(API 37),各版本权限差异由 `BluetoothPermissionHelper` 自动处理,API差异在管理器内部处理。新项目只需 minSdk ≥ 21 即可直接集成。 --- ## 十一、开发者信息 | 项目 | 内容 | | --- | --- | | 开发者 | 宁工 | | 联系电话 | 17776688224 | | 库名称 | bluetoothlib(传统蓝牙 + BLE蓝牙) | | 支持系统 | Android 5.0(API 21) ~ Android 17(API 37) | | 支持语言 | Java / Kotlin,普通项目 / MVVM架构 | 蓝牙开发相关问题、库定制需求均可联系宁工。