|
|
|
@ -996,30 +996,48 @@ object BleService { |
|
|
|
isDescriptorWriteInProgress = false |
|
|
|
notificationTargetsTotal = 0 |
|
|
|
notificationTargetsSucceeded = 0 |
|
|
|
if (callAudioChar != null && audioChar != null) { |
|
|
|
setupNotifications(g, callAudioChar) |
|
|
|
setupNotifications(g, audioChar) |
|
|
|
Log.i(TAG, "通话音频服务特征找到并设置通知") |
|
|
|
Handler(Looper.getMainLooper()).postDelayed({ |
|
|
|
getDeviceWakeupVersion() |
|
|
|
}, 1000) // 延迟3秒再请求版本,确保通知描述符写入完成 |
|
|
|
} else { |
|
|
|
Log.w(TAG, "通话音频服务特征未完整找到") |
|
|
|
} |
|
|
|
|
|
|
|
setupNotifications(g, notifyChar) |
|
|
|
|
|
|
|
// 获取唤醒词OTA主服务特征 |
|
|
|
// 获取唤醒词OTA主服务特征(提前获取,便于统一加入串行注册队列) |
|
|
|
val wakeupVoicesSvc = g.getService(BleConst.WakeupVoices_PRIMARY_SERVICE_UUID) |
|
|
|
wakeupVoicesNotifyChar = wakeupVoicesSvc?.getCharacteristic(BleConst.WakeupVoices_NOTIFY_UUID) |
|
|
|
wakeupVoicesWriteChar = wakeupVoicesSvc?.getCharacteristic(BleConst.WakeupVoices_WRITE_UUID) |
|
|
|
if (wakeupVoicesNotifyChar != null && wakeupVoicesWriteChar != null) { |
|
|
|
wakeupVoicesWriteChar?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE |
|
|
|
setupWakeupVoicesNotifications(g, wakeupVoicesNotifyChar) |
|
|
|
Log.i(TAG, "liwei------- 唤醒词OTA服务特征已找到") |
|
|
|
} else { |
|
|
|
Log.w(TAG, "liwei------- 唤醒词OTA服务特征未找到") |
|
|
|
} |
|
|
|
|
|
|
|
// 串行注册所有需要通知/指示的特征: |
|
|
|
// Android BLE 协议栈一次只允许一个 GATT 操作排队, |
|
|
|
// 连续直接 writeDescriptor 会导致后续调用被丢弃,必须等上一个 onDescriptorWrite 回调后再写下一个。 |
|
|
|
val notifyCandidates = listOf(callAudioChar, audioChar, notifyChar, wakeupVoicesNotifyChar) |
|
|
|
for (c in notifyCandidates) { |
|
|
|
if (c == null) continue |
|
|
|
val supportsNotify = (c.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0 |
|
|
|
val supportsIndicate = (c.properties and BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0 |
|
|
|
val hasCccd = c.getDescriptor(BleConst.CLIENT_CHAR_CONFIG_UUID) != null |
|
|
|
if ((supportsNotify || supportsIndicate) && hasCccd) { |
|
|
|
notificationSetupQueue.addLast(c) |
|
|
|
} else { |
|
|
|
Log.w(TAG, "特征不支持通知/指示或缺少CCCD: ${c.uuid}") |
|
|
|
} |
|
|
|
} |
|
|
|
notificationTargetsTotal = notificationSetupQueue.size |
|
|
|
if (notificationTargetsTotal > 0) { |
|
|
|
Log.i(TAG, "开始串行注册通知通道,总数: $notificationTargetsTotal") |
|
|
|
processNextNotificationDescriptor(g) |
|
|
|
} else { |
|
|
|
Log.w(TAG, "未找到可注册通知/指示的特征") |
|
|
|
} |
|
|
|
|
|
|
|
if (callAudioChar != null && audioChar != null) { |
|
|
|
Log.i(TAG, "通话音频服务特征找到并加入通知注册队列") |
|
|
|
Handler(Looper.getMainLooper()).postDelayed({ |
|
|
|
getDeviceWakeupVersion() |
|
|
|
}, 1500) // 适当放宽,确保所有CCCD串行写入完成 |
|
|
|
} else { |
|
|
|
Log.w(TAG, "通话音频服务特征未完整找到") |
|
|
|
} |
|
|
|
// 在服务发现完成后,请求最大MTU |
|
|
|
//requestMaxMtu(g) |
|
|
|
|
|
|
|
@ -1145,8 +1163,15 @@ object BleService { |
|
|
|
* @param characteristic 要设置通知的特征 |
|
|
|
*/ |
|
|
|
private fun setupNotifications(g: BluetoothGatt, characteristic: BluetoothGattCharacteristic?) : Boolean{ |
|
|
|
if (characteristic == null || characteristic.properties.and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0) { |
|
|
|
Log.w(TAG, "特征不支持通知功能: ${characteristic?.uuid}") |
|
|
|
if (characteristic == null) { |
|
|
|
Log.w(TAG, "特征为空,无法设置通知/指示") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
val supportsNotify = characteristic.properties.and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0 |
|
|
|
val supportsIndicate = characteristic.properties.and(BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0 |
|
|
|
if (!supportsNotify && !supportsIndicate) { |
|
|
|
Log.w(TAG, "特征不支持通知/指示功能: ${characteristic.uuid}") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
@ -1165,8 +1190,12 @@ object BleService { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 设置描述符值为启用通知 |
|
|
|
desc.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE |
|
|
|
// 设置描述符值:根据特征属性自适应启用 NOTIFY 或 INDICATE |
|
|
|
desc.value = if (supportsNotify) { |
|
|
|
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE |
|
|
|
} else { |
|
|
|
BluetoothGattDescriptor.ENABLE_INDICATION_VALUE |
|
|
|
} |
|
|
|
|
|
|
|
// 向远程设备写入描述符(异步操作,结果在onDescriptorWrite回调中处理) |
|
|
|
val writeResult = g.writeDescriptor(desc) |
|
|
|
|