object CHatServer{
private fun setupGattService(): BluetoothGattService {
//......
val rrepCharacteristic = BluetoothGattCharacteristic(
RREP_UUID,
BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_NOTIFY ,
BluetoothGattCharacteristic.PERMISSION_READ
)
val cccd = BluetoothGattDescriptor(
CCCD_UUID,
BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE
)
rrepCharacteristic.addDescriptor(cccd)
service.addCharacteristic(rrepCharacteristic)
val uuid = BluetoothGattCharacteristic(
app?.let { UUIDManager.getStoredUUID(it.applicationContext) },
BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PERMISSION_READ
)
service.addCharacteristic(uuid)
return service
}
private class GattClientCallback : BluetoothGattCallback() {
@SuppressLint("MissingPermission")
//.......
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@SuppressLint("MissingPermission")
override fun onServicesDiscovered(discoveredGatt: BluetoothGatt, status: Int) {
super.onServicesDiscovered(discoveredGatt, status)
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "onServicesDiscovered: Have gatt $discoveredGatt")
gatt = discoveredGatt
val service = discoveredGatt.getService(SERVICE_UUID)
if (service!=null){
if(service.getCharacteristic(MESSAGE_UUID)!=null){
messageCharacteristic = service.getCharacteristic(MESSAGE_UUID)
}
if(service.getCharacteristic(RREQ_UUID)!=null){
rreqCharacteristic = service.getCharacteristic(RREQ_UUID)
}
if(service.getCharacteristic(RREP_UUID)!=null){
rrepCharacteristic = service.getCharacteristic(RREP_UUID)
enableNotificationsForRrepCharacteristic(gatt, rrepCharacteristic)
}
val uuid = getUUID(service)
notifyConnectionSuccess(gatt!!.device,uuid)
Log.d(TAG, "UUID Discovered: $uuid")
gatt!!.requestMtu(GATT_MAX_MTU_SIZE)
}
}
}
override fun onCharacteristicChanged(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
value: ByteArray
) {
super.onCharacteristicChanged(gatt, characteristic, value)
Log.d(TAG, "Received RREP: ${gatt.device}")
val packet = deserializePacket(value)
if (packet != null) {
if(packet.src == appUUID.toString()){
Log.d(TAG, "Path Found from A to C")
}
}
_rrepRequests.postValue(packet)
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@SuppressLint("MissingPermission")
fun enableNotificationsForRrepCharacteristic(gatt: BluetoothGatt?, rrepCharacteristic: BluetoothGattCharacteristic?) {
// Step 1: Enable notifications locally
val notificationEnabled = gatt?.setCharacteristicNotification(rrepCharacteristic, true) ?: false
if (!notificationEnabled) {
Log.w(TAG, "Failed to enable local notifications for RREP_UUID")
return
}
// Step 2: Write to the CCCD to enable notifications on the peripheral
val cccd = rrepCharacteristic?.getDescriptor(CCCD_UUID)
if (cccd == null) {
Log.w(TAG, "RREP_UUID characteristic does not have a CCCD")
return
}
val success = gatt?.writeDescriptor(cccd,BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
if (success != BluetoothStatusCodes.SUCCESS) {
Log.w(TAG, "Failed to write CCCD value for enabling notifications")
} else {
Log.d(TAG, "Successfully requested to enable notifications for RREP_UUID")
}
}
}
我认为问题在于 writeDescriptor() 函数,因为我们在 GATT 操作之间仍在 onDiscoveredServices() 回调中时进行写入,这导致了 201 错误(繁忙错误)。但如果我们不能这样做,那么我们如何启用通知呢?
当我在 onServiceDiscovered() 回调中仅使用 setCharacteristicNotification() 函数时,我可以写入任何特征,但无法接收通知。因为我听说你需要描述符才能做到这一点。`
一般来说,您需要对所有 BLE 操作进行排队,以便在开始下一个操作之前可以完全完成一个操作。所有 BLE 库都这样做。
在您的情况下,实际上可能是 requestMTU() 方法存在问题。因为对描述符的写入尚未完成。只需调试它,看看哪个 gatt 操作给你带来了错误......