You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android与ESP32 BLE连续读写仅首个回调触发问题求助

问题分析与解决方案

核心问题原因

Android的BLE GATT操作是异步且串行执行的,GATT客户端不会同时处理多个并发的读写请求。如果在第一个操作(比如写特征)的回调确认完成前就发起第二个操作(读特征),第二个请求会被GATT栈直接丢弃,导致ESP32端收不到第二个操作的请求,自然不会触发对应的回调。

你当前代码里加的TimeUnit.MILLISECONDS.sleep(500)只是单纯阻塞线程,无法保证第一个BLE操作真正完成——BLE操作的完成是通过BluetoothGattCallback的回调通知的,sleep和操作是否完成没有关联。

修复方案:基于回调串行化BLE操作

修改Android端代码,利用BluetoothGattCallback的回调函数触发下一个操作,确保前一个操作完全完成后再执行后续步骤。

步骤1:完善BluetoothGattCallback回调实现

重写onCharacteristicWrite和onCharacteristicRead回调,感知操作完成状态:

override fun onCharacteristicWrite(
    gatt: BluetoothGatt?,
    characteristic: BluetoothGattCharacteristic?,
    status: Int
) {
    super.onCharacteristicWrite(gatt, characteristic, status)
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // 写操作成功后,触发读取站点的操作
        if (characteristic?.uuid == SET_TIME_UUID) {
            getStations()
        }
    } else {
        Log.e(TAG, "写特征失败,状态码:$status")
    }
}

override fun onCharacteristicRead(
    gatt: BluetoothGatt?,
    characteristic: BluetoothGattCharacteristic?,
    status: Int
) {
    super.onCharacteristicRead(gatt, characteristic, status)
    if (status == BluetoothGatt.GATT_SUCCESS) {
        val value = characteristic?.value?.let { String(it) }
        Log.d(TAG, "读取到特征值:$value")
        // 这里可以处理读取到的站点数据
    } else {
        Log.e(TAG, "读特征失败,状态码:$status")
    }
}

步骤2:修改sync函数,仅发起第一个操作

去掉连续调用的逻辑,只启动第一个写操作,后续操作由回调触发:

fun sync() {
    Log.d("sync", "syncing")
    bluetoothGatt?.apply {
        if (device.bondState != BluetoothDevice.BOND_BONDED) {
            device.createBond()
        } else {
            // 只发起写时间操作,读站点操作在写成功回调中触发
            updateTime()
        }
    }
}

步骤3:移除sendToCharacteristic中的无用sleep

现在用回调控制操作顺序,无需阻塞线程:

private fun sendToCharacteristic(characteristic: BluetoothGattCharacteristic?, value: String) {
    Log.d(TAG, "Sending to write characteristic ${characteristic?.uuid} value ($value)")
    characteristic?.value = value.toByteArray()
    bluetoothGatt?.writeCharacteristic(characteristic)
}

额外注意事项

  • 确保BluetoothGattCallback的回调在主线程执行,避免线程安全问题。
  • 如果需要执行多个连续BLE操作,可以封装操作队列,每次回调完成后取出下一个操作执行,提升扩展性。
  • ESP32端的NimBLE代码无需修改,单独操作正常说明问题根源在Android端的并发操作处理。

内容的提问来源于stack exchange,提问作者La bla bla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:45:20