蓝牙BLE模块集成说明

目录结构

capability-ble/src/
└── main/
    ├── AndroidManifest.xml          # Android 清单文件(权限声明)
    └── java/
        └── com/narutohuo/xindazhou/ble/
            ├── api/                  # API 接口层
            │   └── BLEService.kt    # 蓝牙服务接口定义
            ├── factory/              # 工厂类层
            │   └── BLEServiceFactory.kt  # 服务工厂(统一入口)
            ├── impl/                 # 实现层
            │   └── BLEServiceImpl.kt     # 蓝牙服务具体实现(单例模式)
            ├── callback/             # 回调接口层
            │   └── BLECallback.kt         # 蓝牙回调接口(包含 ConnectCallback、HandshakeCallback、CommandCallback、DataCallback)
            ├── config/               # 配置层
            │   └── BLEConstants.kt         # 蓝牙常量定义(用户类型、功能码、UUID等)
            ├── model/                # 数据模型层
            │   ├── BLEDevice.kt          # BLE设备模型
            │   ├── BLECommand.kt          # BLE指令模型(包含 AppControlInstruction、SystemControlInstruction)
            │   ├── BLEResponse.kt         # BLE响应模型
            │   └── Command.kt             # 指令协议数据类
            └── util/                 # 工具类层
                ├── BleScanner.kt          # BLE扫描工具
                ├── BleConnector.kt         # BLE连接工具
                ├── BLECrypto.kt            # 加密解密工具(AES)
                ├── BLEPacketBuilder.kt    # 协议包构建工具
                ├── BLEPacketParser.kt     # 协议包解析工具
                ├── BLEPacketSplitter.kt   # 协议包分包工具
                └── BlePacketSender.kt     # 协议包发送工具

功能说明

1. api/ 层 - 接口定义

2. factory/ 层 - 工厂类

3. impl/ 层 - 具体实现

4. model/ 层 - 数据模型

5. callback/ 层 - 回调接口

6. config/ 层 - 配置

7. util/ 层 - 工具类

架构设计

使用方式

完整示例(单例模式)

import androidx.fragment.app.Fragment
import android.widget.Toast
import com.narutohuo.xindazhou.ble.factory.BLEServiceFactory
import com.narutohuo.xindazhou.ble.api.BLEService
import com.narutohuo.xindazhou.ble.config.BLEConstants

class VehicleFragment : Fragment() {
    
    // 1. 获取单例实例(全局只有一个,在任何地方获取的都是同一个)
    private val bleService: BLEService = BLEServiceFactory.create(requireContext())
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 2. 连接设备(一键完成扫描+连接+握手)
        connectDevice()
    }
    
    private fun connectDevice() {
        // 获取用户信息(实际项目中从用户认证信息中获取)
        val userId = getUserId() // 16字节
        val userType = BLEConstants.USER_TYPE_OWNER // 0x02=车主
        
        bleService.initializeAndConnect(
            userId = userId,
            userType = userType,
            onConnected = {
                activity?.runOnUiThread {
                    // 连接成功,可以直接使用指令了
                    Toast.makeText(context, "连接成功", Toast.LENGTH_SHORT).show()
                }
            },
            onError = { error ->
                activity?.runOnUiThread {
                    Toast.makeText(context, "连接失败: $error", Toast.LENGTH_SHORT).show()
                }
            }
        )
    }
    
    // 3. 发送指令(连接成功后调用)
    private fun lockCar() {
        // 设防
        bleService.setDefense(enabled = true) { response ->
            activity?.runOnUiThread {
                if (response.success) {
                    Toast.makeText(context, "设防成功", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(context, "设防失败: ${response.errorMessage}", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
    
    private fun powerOn() {
        // 上电
        bleService.powerOn { response ->
            activity?.runOnUiThread {
                if (response.success) {
                    Toast.makeText(context, "上电成功", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
    
    private fun findCar() {
        // 寻车
        bleService.findCar { response ->
            activity?.runOnUiThread {
                if (response.success) {
                    Toast.makeText(context, "寻车成功", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
    
    private fun getUserId(): ByteArray {
        // 实际项目中从用户认证信息中获取
        return ByteArray(16) { it.toByte() } // 示例数据
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        // 4. 断开连接(可选,单例会保持连接状态)
        if (bleService.isConnected()) {
            bleService.disconnect()
        }
    }
}

步骤说明

  1. 获取单例实例:使用 BLEServiceFactory.create(context) 获取服务实例(全局只有一个)
  2. 连接设备:调用 initializeAndConnect() 连接设备(自动完成扫描+连接+握手)
  3. 发送指令:连接成功后,调用各种指令方法(如 setDefense()powerOn()findCar() 等)
  4. 断开连接:在 onDestroyView() 中断开连接(可选)

重要说明

  1. 单例模式BLEService 是单例,全局只有一个实例,在任何地方获取的都是同一个
  2. 连接状态共享:所有使用该服务的地方共享同一个连接状态
  3. 第一次需要 Context:第一次获取单例时需要传入 Context,后续获取可以不带(但建议统一使用工厂类)
  4. 连接是必须的:蓝牙不是自动连接的,需要手动调用 initializeAndConnect() 连接设备

两种连接方式的区别

方式一:一键连接(推荐,最简单)

使用 initializeAndConnect() - 自动完成所有步骤

适用场景:大多数情况,直接连接即可

// 一键完成:扫描 + 连接 + 握手
bleService.initializeAndConnect(
    userId = userId,
    userType = userType,
    onConnected = {
        // 连接成功,可以直接使用指令了
    },
    onError = { error ->
        // 连接失败
    }
)

方式二:手动控制(需要选择设备时使用)

使用 startScan() + connect() - 手动控制每个步骤

适用场景:需要显示设备列表让用户选择,或者需要控制扫描过程

// 1. 开始扫描
bleService.startScan { device: BLEDevice ->
    // 找到设备,可以显示在列表中让用户选择
    println("找到设备: ${device.name}, 地址: ${device.address}")
    // 可以添加到设备列表,让用户选择
}

// 2. 停止扫描(用户选择设备后)
bleService.stopScan()

// 3. 连接用户选择的设备
val userId = getUserId() // 16字节
val userType = BLEConstants.USER_TYPE_OWNER
val selectedDevice = BLEDevice(name = "用户选择的设备", address = "MAC地址", rssi = 0)
bleService.connect(selectedDevice, userId, userType) { response ->
    if (response.success) {
        // 连接成功,已自动完成握手
    } else {
        // 连接失败
    }
}

总结

API 参考

基础连接功能

startScan(callback: (BLEDevice) -> Unit)

开始扫描 BLE 设备

stopScan()

停止扫描设备

connect(device: BLEDevice, userId: ByteArray, userType: Byte, callback: (BLEResponse) -> Unit)

连接设备(自动完成握手和配对)

disconnect()

断开连接

isConnected(): Boolean

检查是否已连接

高级连接功能(推荐使用)

initializeAndConnect()

一键完成扫描+连接+握手(最简单的方式)

fun initializeAndConnect(
    userId: ByteArray,
    userType: Byte,
    onConnected: () -> Unit,
    onDisconnected: (() -> Unit)? = null,
    onDataReceived: ((ByteArray) -> Unit)? = null,
    onError: ((String) -> Unit)? = null,
    scanTimeoutMs: Long = 10000
)

参数说明

scanAndConnect()

扫描并连接设备(一键完成扫描+连接)

fun scanAndConnect(
    userId: ByteArray,
    userType: Byte,
    scanTimeoutMs: Long = 10000,
    onScanning: (() -> Unit)? = null,
    onDeviceFound: ((BLEDevice) -> Unit)? = null,
    onConnected: () -> Unit,
    onError: (String) -> Unit
)

setConnectionListener()

设置连接状态监听器(连接/断开时自动回调)

fun setConnectionListener(
    onConnected: () -> Unit,
    onDisconnected: () -> Unit,
    onError: (String) -> Unit
)

便捷方法

setDefense(enabled: Boolean, callback: (BLEResponse) -> Unit)

设防/撤防

powerOn(callback: (BLEResponse) -> Unit)

上电

powerOff(callback: (BLEResponse) -> Unit)

下电

findCar(callback: (BLEResponse) -> Unit)

寻车

unlockSeat(callback: (BLEResponse) -> Unit)

打开座桶锁

unlockHandlebar(callback: (BLEResponse) -> Unit)

打开龙头锁

lockHandlebar(callback: (BLEResponse) -> Unit)

关闭龙头锁

unlockTrunk(callback: (BLEResponse) -> Unit)

打开尾箱锁

lockTrunk(callback: (BLEResponse) -> Unit)

关闭尾箱锁

setSensorUnlock(enabled: Boolean, callback: (BLEResponse) -> Unit)

设置感应解锁开关

setAmbientLight(enabled: Boolean, callback: (BLEResponse) -> Unit)

设置氛围灯开关

setAmbientLightColor(r: Int, g: Int, b: Int, callback: (BLEResponse) -> Unit)

设置氛围灯颜色

setAutoPowerOffTime(timeSeconds: Int, callback: (BLEResponse) -> Unit)

设置自动下电时间

setSpeakerVolume(volume: Int, callback: (BLEResponse) -> Unit)

设置蓝牙音箱音量

通用方法

sendAppControlCommand(instructionType: Byte, data: ByteArray, callback: (BLEResponse) -> Unit)

发送应用控制指令

指令类型AppControlInstruction 对象):

sendSystemControlCommand(instructionType: Byte, data: ByteArray, callback: (BLEResponse) -> Unit)

发送系统控制指令

指令类型SystemControlInstruction 对象):

queryVehicleInfo(callback: (BLEResponse) -> Unit)

查询车辆信息

sendCommand(command: BLECommand, callback: (BLEResponse) -> Unit)

发送自定义指令

setDataReceivedListener(listener: DataCallback)

设置数据接收监听器

常量定义

用户类型

BLEConstants.USER_TYPE_HIGHEST  // 0x01 - 最高权限
BLEConstants.USER_TYPE_OWNER    // 0x02 - 车主
BLEConstants.USER_TYPE_SHARED   // 0x03 - 分享用户

功能码

BLEConstants.FUNCTION_CODE_HANDSHAKE        // 0x01 - 握手
BLEConstants.FUNCTION_CODE_APP_CONTROL      // 0x02 - 应用控制
BLEConstants.FUNCTION_CODE_SYSTEM_CONTROL   // 0x03 - 系统控制
BLEConstants.FUNCTION_CODE_SYSTEM_QUERY     // 0x04 - 系统查询
BLEConstants.FUNCTION_CODE_SYSTEM_SETTING   // 0x05 - 系统设置

注意事项

  1. 单例模式BLEServiceImpl 使用单例模式,全局共享同一个连接状态

  2. 自动握手connect() 方法内部自动完成握手,无需单独调用握手方法

  3. 线程安全:BLE 回调可能在非主线程执行,需要在回调中使用 activity?.runOnUiThread {} 切换到主线程更新 UI

  4. 错误处理:所有 API 都通过 BLEResponse 返回结果,需要检查 response.success 判断是否成功

  5. 生命周期管理:建议在 onDestroyView() (Fragment) 或 onDestroy() (Activity) 中调用 disconnect() 断开连接

  6. 获取服务实例:推荐使用 BLEServiceFactory.create(context) 获取服务实例(工厂方法内部使用单例模式)

  7. Fragment 中使用:在 Fragment 中使用时,使用 requireContext() 获取 Context,回调中使用 activity?.runOnUiThread {} 更新 UI