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

Google Pixel与三星Galaxy设备BLE通知分片接收异常咨询

BLE通知异常:Google Pixel与三星Galaxy设备丢失分片响应第一部分

在Google Pixel和三星Galaxy系列设备上遇到BLE通知异常:当接收长度超过MTU的响应时,数据会被拆分为两部分,但上述设备仅能收到第二部分。

通信流程如下:

  • 调用discoverServices()完成服务发现
  • 将MTU设置为512
  • 通过指定BluetoothGattCharacteristic发送初始消息
  • 预期接收被拆分的JSON响应,但在Google Pixel和三星Galaxy设备上,onCharacteristicChanged方法仅被调用一次(其他测试设备会调用两次)

该问题在Android 14中被发现,升级至Android 15后仍未解决,恳请排查原因。

补充信息

  • Android版本:Android 14、Android 15
  • 受影响设备:Google Pixel 6A、Galaxy Tab S8

相关代码

// STEP 1 - Connect to the BluetoothDevice
fun connect(device: BluetoothDevice, context: Context) {
    try {
        device.connectGatt(context, false, callback)
    } catch (e: SecurityException) {
        Log.d("Error connecting to ${device.address}")
    }
}

private val callback = object : BluetoothGattCallback() {
    // STEP 2 - Request the services after a successful connection
    override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
        try {
            val deviceAddress = gatt.device.address
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    Handler(Looper.getMainLooper()).post {
                        gatt.discoverServices()
                    }
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    disconnect()
                }
            } else {
                disconnect(status)
            }
        } catch (e: SecurityException) {
            Log.d("onConnectionStateChange: Error occurred $e")
        }
    }
    // STEP 3 - MTU request after a successful discoverServices()
    override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
        try {
            with(gatt) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    requestMtu(512)
                } else {
                    disconnect()
                }
            }
        } catch (e: SecurityException) {
            Log.d("onServicesDiscovered: Error occurred $e")
        }
    }
    // STEP 4 - Send message after setting the MTU properly
    override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            deviceBluetoothGatt!!.services?.firstOrNull { it.uuid == serviceUUID.uuid }?.let { service ->
                val characteristic = service.characteristics.first { it.uuid == readCharacteristicUUID }
                try {
                    deviceBluetoothGatt!!.findCharacteristic(characteristic.uuid)?.let { _ ->
                        val payload = when {
                            characteristic.isIndicatable() -> BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
                            characteristic.isNotifiable() -> BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                            else -> error("${characteristic.uuid} doesn't support notifications/indications")
                        }

                        characteristic.getDescriptor(configurationCharacteristicUUID)?.let { cccDescriptor ->
                            if (!deviceBluetoothGatt!!.setCharacteristicNotification(characteristic, true)) {
                                return
                            }
                            cccDescriptor.value = payload
                            deviceBluetoothGatt!!.writeDescriptor(cccDescriptor)
                        } ?: this@BLEManager.run {
                            Log.e("${characteristic.uuid} doesn't contain the CCC descriptor!")
                        }
                    } ?: this@BLEManager.run {
                        Log.e("Cannot find $characteristic.uuid! Failed to enable notifications.")
                    }
                } catch (e: SecurityException) {
                    Log.d("onMtuChanged: Error occurred: $e")
                }
            }
        } else {
           Log.d("onMtuChanged: Error occurred $e")
           disconnect()
        }
    }
    // STEP 5 - Receive the message on this callback in blocks
    override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        with(characteristic) {
            decodeResponse(characteristic.value)
        }
    }
    override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
        with(descriptor) {
            when (status) {
                BluetoothGatt.GATT_SUCCESS -> {
                    writeCharacteristic(GetinfoRequest().encode())
                }
                BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
                    Log.d("Write not permitted for $uuid!")
                }
                else -> {
                    Log.d("Descriptor write failed for $uuid, error: $status")
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:37:05