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

Android端BLE设备断开GATT服务器后才接收数据的问题求助

BLE GATT写入成功但设备仅在断开连接时响应的问题

我尝试通过GATT服务器向BLE设备发送命令字符串,GattCallback显示写入成功,但设备无任何响应;只有退出应用(断开GATT连接)时,BLE设备才会收到数据。以下是相关代码,求解决:

GattCallback代码

private val gattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
    override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
        super.onConnectionStateChange(gatt, status, newState)
        if( status == BluetoothGatt.GATT_FAILURE ) {
            disconnect()
            return
        } else if( status != BluetoothGatt.GATT_SUCCESS ) {
            disconnect()
            return
        }
        if( newState == BluetoothProfile.STATE_CONNECTED ) {
            Log.d(TAG, "Connected to the GATT server")
            gatt.discoverServices()
        } else if ( newState == BluetoothProfile.STATE_DISCONNECTED ) {
            disconnect()
        }
    }
    override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
        super.onServicesDiscovered(gatt, status)

        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "Device service discovery failed, status: $status")
            return
        }
        Log.d(TAG, "Services discovery is successful")
        isStatuschanged = "connected"

        val respCharacteristic = gatt?.let { BluetoothUtils.findResponseCharacteristic(it) }
        if( respCharacteristic == null ) {
            Log.e(TAG, "Unable to find cmd characteristic")
            disconnect()
            return
        }
        gatt.setCharacteristicNotification(respCharacteristic, true)
        val descriptor: BluetoothGattDescriptor = respCharacteristic.getDescriptor(
            UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)
        )
        descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
        gatt.writeDescriptor(descriptor)
    }

    override fun onCharacteristicChanged(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic
    ) {
        super.onCharacteristicChanged(gatt, characteristic)
        readCharacteristic(characteristic)
    }

    override fun onCharacteristicWrite(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic?,
        status: Int
    ) {
        super.onCharacteristicWrite(gatt, characteristic, status)
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "Characteristic written successfully")
        } else {
            Log.e(TAG, "Characteristic write unsuccessful, status: $status")
            disconnect()
        }
    }

    override fun onCharacteristicRead(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic,
        status: Int
    ) {
        super.onCharacteristicRead(gatt, characteristic, status)
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "Characteristic read successfully")
            readCharacteristic(characteristic)
        } else {
            Log.e(TAG, "Characteristic read unsuccessful, status: $status")
        }
    }
}

写入函数代码

fun write(message: String) {
    val cmdCharacteristic = BluetoothUtils.findCommandCharacteristic(bluetoothGatt!!)
    if (cmdCharacteristic == null) {
        Log.e(TAG, "Unable to find cmd characteristic")
        disconnect()
        return
    }

    cmdCharacteristic?.value = message.toByteArray()
    val success: Boolean = bluetoothGatt!!.writeCharacteristic(cmdCharacteristic)
    if (!success) {
        Log.d("jay", "failed to write command")
    }
    Log.d("jay", "write succesful")
}

断开连接函数代码

fun disconnect() {
    Log.d("jay", "disconnect: bluetoothGatt is null? ${bluetoothGatt == null}")
    bluetoothDeviceAddress = null
    bluetoothGatt?.disconnect()
    isStatuschanged = "disconnected"
    bluetoothGatt = null
}

问题原因及解决方法

这种现象通常是因为BLE特性的写入类型配置错误,或者Android端没有正确触发设备端的数据提交,以下是具体解决步骤:

1. 显式设置特性写入类型

确保命令特性的写入类型设置为BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT或WRITE_TYPE_NO_RESPONSE,避免依赖断开连接时的延迟提交。修改写入函数:

fun write(message: String) {
    val cmdCharacteristic = BluetoothUtils.findCommandCharacteristic(bluetoothGatt!!)
    if (cmdCharacteristic == null) {
        Log.e(TAG, "Unable to find cmd characteristic")
        disconnect()
        return
    }

    // 显式指定写入类型
    cmdCharacteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
    cmdCharacteristic.value = message.toByteArray()
    
    val success: Boolean = bluetoothGatt!!.writeCharacteristic(cmdCharacteristic)
    if (!success) {
        Log.d("jay", "failed to send write command request")
    }
}

2. 等待写入回调确认后再操作

Android的BLE写入是异步的,writeCharacteristic返回true仅表示请求已发送,不代表设备已接收。需要在onCharacteristicWrite回调确认成功后,再发起后续操作,避免请求堆积。

3. 检查设备端特性权限

确认BLE设备的命令特性已开启PROPERTY_WRITE或PROPERTY_WRITE_NO_RESPONSE属性权限,无对应权限会导致数据无法被设备正确接收。

4. 避免GATT操作并发

BLE GATT操作是串行的,不能同时发起多个写入/读取请求。如果有批量写入需求,需等待前一个操作的回调完成后再发起下一个。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:13:36