以下内容是在原先 Windows 平台开发流程的基础上,补充针对 Android 平台开发同时支持 SPP(经典蓝牙)和 BLE(低功耗蓝牙)透明传输设备的思路与步骤,帮助你在 Android 上完成相关功能的实现。请根据你的技术栈(Java/Kotlin、开发工具、API Level 等)和项目需求进行调整。

一、Android 平台概览

在 Android 上进行蓝牙开发主要分为两部分:

  1. 蓝牙经典(BR/EDR),也就是常说的 SPP(Serial Port Profile)方式。
    • 适用于 Android 2.0 起几乎所有版本,且系统原生支持 SPP 协议栈。
    • 在 Android 中通过 BluetoothAdapter、BluetoothDevice、BluetoothSocket 等类实现。
  2. 低功耗蓝牙(BLE),使用 GATT 协议进行特征(Characteristic)的读写、订阅通知(Notification/Indication)等。
    • Android 4.3 及以上开始支持 BLE(API Level 18+)。
    • 在 Android 中通常结合 BluetoothLeScanner、BluetoothGatt、BluetoothGattService、BluetoothGattCharacteristic 等来实现。

需要注意:

  • 从 Android 6.0(API 23)开始,蓝牙扫描需要定位权限。
  • 从 Android 10(API 29)开始进一步收紧权限,需要精确位置信息权限来扫描 BLE 设备。
  • Android 12(API 31)及之后新增 Bluetooth 权限(BLUETOOTH_SCAN、BLUETOOTH_CONNECT 等),需要在 Manifest 中声明并在运行时请求权限。

二、SPP(经典蓝牙)开发流程

  1. 打开蓝牙与获取权限

    • 检查并打开蓝牙:
      • 使用 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
      • 确认 adapter 不为 null(设备是否支持蓝牙),并检查 adapter.isEnabled() 决定是否提示用户打开蓝牙。
    • 获取运行时权限(Android 12 及以上需要 BLUETOOTH_CONNECT 等权限),并在必要时启用位置权限(Android 10 及之前)。
  2. 设备扫描与配对(可选)

    • 如果设备未配对,可以通过 startDiscovery() 搜索附近的经典蓝牙设备,也可以跳转到系统蓝牙页面,让用户完成配对。
    • 执行 createBond() 方法发起配对(部分设备可能不需要手动调用,系统会自动配对)。
    • 成功配对后,可以在系统设置中看到已配对设备,可从 BluetoothAdapter.getBondedDevices() 获取。
  3. 使用 SPP 连接设备

    • 通过已配对设备对象:BluetoothDevice device = …
    • 使用 UUID 获取蓝牙串口通道,通常为通用的 SPP UUID(00001101-0000-1000-8000-00805F9B34FB),或设备提供的自定义 UUID。
    • 调用 device.createRfcommSocketToServiceRecord(uuid) 获取 BluetoothSocket,对其进行 connect() 操作。
    • 连接成功后,获取输入输出流:
      • InputStream is = bluetoothSocket.getInputStream();
      • OutputStream os = bluetoothSocket.getOutputStream();
  4. 数据收发与解析

    • 通过 InputStream 读取设备返回的数据,根据协议进行解析。
    • 通过 OutputStream 向设备发送数据(透传协议通常可直接发送二进制/文本)。
    • 注意线程处理:一般应在单独的线程或异步任务中进行收发操作,避免阻塞 UI。
  5. 断开与资源释放

    • 在页面退出或不再需要蓝牙连接时,调用 bluetoothSocket.close() 释放资源。
    • 注意处理异常及断线重连逻辑。

三、BLE(低功耗蓝牙)开发流程

  1. 打开蓝牙与权限检查

    • 同样需要检查 BluetoothAdapter 是否可用,并在 AndroidManifest.xml 中声明所需权限,Android 12 及以上需要 BLUETOOTH_SCAN、BLUETOOTH_CONNECT 等;低版本还要精确定位权限。
    • 在运行时请求相应权限,确保能够进行 BLE 扫描和连接。
  2. 设备扫描

    • 获取 BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
    • 使用 scanner.startScan(…) 开始扫描,通过回调 onScanResult() 获取附近的 BLE 设备。
    • 如果只想连接已知的设备 MAC 地址,也可以通过 bluetoothAdapter.getRemoteDevice(mac) 直接获取 BluetoothDevice 对象,然后发起连接。
  3. 发起 GATT 连接

    • BluetoothDevice device = …
    • BluetoothGatt bluetoothGatt = device.connectGatt(context, false, gattCallback);
    • context:一般为当前 Activity 或应用上下文
    • false 表示不使用自动重连机制(可根据需求设为 true)
    • gattCallback:连接和数据通信过程的回调
  4. 发现服务与特征

    • 在 onConnectionStateChange() 中处理连接成功或失败。连接成功后,调用 bluetoothGatt.discoverServices() 发起服务发现。
    • 在 onServicesDiscovered() 回调中获取到可用服务: bluetoothGatt.getServices()。
    • 根据设备协议或文档,找到对应 Service UUID 和 Characteristic UUID。
  5. 特征(Characteristic)读写与通知

    1. 写数据

      • 得到目标 characteristic 实例后:
        BluetoothGattCharacteristic characteristic = …
        characteristic.setValue(需要发送的字节数组);
        bluetoothGatt.writeCharacteristic(characteristic);
      • 在 onCharacteristicWrite() 回调中查看写入结果。
    2. 读数据

      • bluetoothGatt.readCharacteristic(characteristic);
      • 在 onCharacteristicRead() 回调中处理读取到的值。
    3. 订阅通知(或指示)

      • 先设置 Notification:
        bluetoothGatt.setCharacteristicNotification(characteristic, true);
      • 给描述符(Descriptor)写入开启通知(0x2902 UUID),例如:
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(相应的 UUID);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        bluetoothGatt.writeDescriptor(descriptor);
      • 当设备有数据主动推送时,会在 onCharacteristicChanged() 回调中接收到实时数据。
  6. 数据解析与处理

    • 在透传模式下,BLE 通常支持直接发送和接收二进制流。
    • 需要根据你与设备约定的协议封包形式进行组包、拆包、校验等操作。
  7. 断开与资源释放

    • 不需要时,调用 bluetoothGatt.close() 断开连接并释放资源。
    • 注意在不同回调中正确处理错误、超时和异常情况,并做好重连策略。

四、常见调试方法与注意事项

  1. 调试工具

    • 对于 SPP,可以用安卓的串口调试类 App(或第三方调试器)测试发送/接收;也可以使用桌面端工具与硬件先行验证。
    • 对于 BLE,可以使用例如 “nRF Connect” 或 “BLE Scanner” 等 App;它们可以列出设备 GATT 服务、特征,并手动进行读写和订阅。
  2. 权限与兼容性

    • 从 Android 6.0 起,蓝牙扫描需要定位权限;Android 10(29) 开始需要精确定位权限。
    • Android 12(31) 之后,新增了 BLUETOOTH_SCAN、BLUETOOTH_CONNECT 等权限,需要区分声明和请求。
    • 尽量在运行时,而非仅在 Manifest 中申请权限,保证在实际使用时已经拿到授权。
  3. 扫描与连接超时策略

    • BLE 扫描若持续过久,会消耗电量并触发系统限制,需要合理控制扫描时长。
    • 在连接后要有超时或重试机制,以免卡在连接状态或等待回调无人处理。
  4. 断线与重连

    • 无论是 SPP 还是 BLE,移动环境中蓝牙断线较常见,需要在回调中监控连接状态并尝试重连。
    • 注意清理资源,避免重复持有 BluetoothSocket 或 BluetoothGatt 对象而不调用 close()。
  5. 性能与功耗

    • BLE 的设计初衷是低功耗,需尽量减少无用的扫描、连接和大数据量的持续传输。
    • 对于 SPP,如果需要持续大数据通信,可以关注速度和稳定性(部分设备可能会有带宽和延时限制)。

五、参考链接

  1. 官方文档

  2. 第三方工具/库

    • nRF Connect (Nordic)
    • BLE Scanner
    • RxAndroidBle(如果你想用 RxJava 处理 BLE 流程)

总结

  • SPP(经典蓝牙)模式下,Android 相对简单,和传统串口思路类似,通过 BluetoothSocket 进行数据收发;但需先进行配对。
  • BLE 模式下,需要进行服务与特征的发现、读写、通知订阅等,更灵活但也更复杂;需注意权限、回调处理和断线重连。
  • 在 Android 开发中,与 Windows 类似,你需要对硬件和协议充分了解,使用对应的 API 进行数据通讯,并做好异常处理及权限管理。
  • 优先用第三方应用或调试工具验证设备与数据链路可行性,然后再在自己项目中实现业务逻辑。

通过上述步骤,就能够在 Android 平台上实现对同时支持 SPP 和 BLE 的蓝牙设备进行透传通信的基本流程。结合之前的 Windows 部分,你可以分别在两个平台上完成配对、连接、数据读写以及后续的设备管理和异常处理。祝开发顺利!