Browse Source

修改连接通道,phy值

weicu
fdp 11 months ago
parent
commit
3b56247b66
  1. 146
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

146
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

@ -134,6 +134,12 @@ object BleService {
private var maxMtu = 517 // 最大MTU值 (512 + 5字节头部)
private var isWaitingForWriteCallback = false // 是否正在等待写入回调
// 通知注册串行化相关变量
private val notificationSetupQueue: ArrayDeque<BluetoothGattCharacteristic> = ArrayDeque()
private var isDescriptorWriteInProgress = false
private var notificationTargetsTotal = 0
private var notificationTargetsSucceeded = 0
// 初始化状态
private var isInitialized = false
@ -743,33 +749,6 @@ object BleService {
updateConnectionState(BleConst.STATE_CONNECTED)
Log.d(TAG, "成功连接Ble蓝牙设备:${g.device.name}")
companionManager?.unregisterBackgroundScan()
// 设置PHY值为2M以提高传输速度
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
// 首先尝试读取当前PHY状态
val readResult = g.readPhy()
Log.d(TAG, "读取PHY状态请求结果: $readResult")
// 延迟一段时间后再设置PHY,确保readPhy完成
Handler(Looper.getMainLooper()).postDelayed({
try {
val setResult = g.setPreferredPhy(
BluetoothDevice.PHY_LE_2M_MASK, // TX PHY: 2M
BluetoothDevice.PHY_LE_2M_MASK, // RX PHY: 2M
BluetoothDevice.PHY_OPTION_NO_PREFERRED
)
Log.d(TAG, "设置PHY为2M请求结果: $setResult")
} catch (e: Exception) {
Log.w(TAG, "设置PHY失败: ${e.message}")
}
}, 500) // 延迟500ms
} catch (e: Exception) {
Log.w(TAG, "读取PHY失败: ${e.message},将使用默认1M PHY")
}
} else {
Log.w(TAG, "当前Android版本不支持PHY设置(需要API 26+),使用默认1M PHY")
}
g.discoverServices()
}
@ -861,20 +840,23 @@ object BleService {
startBytesStatistics()
writeChar?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
callWriteChar?.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
//要先设置音频服务的通知,否则接收不到
// 设置音频服务的通知(如果存在)
// 串行注册通知:等待上一个通道成功后再注册下一个
notificationSetupQueue.clear()
isDescriptorWriteInProgress = false
notificationTargetsTotal = 0
notificationTargetsSucceeded = 0
if (callAudioChar != null && audioChar != null) {
setupNotifications(g, callAudioChar)
setupNotifications(g, audioChar)
Log.i(TAG, "通话音频服务特征找到并设置通知")
notificationSetupQueue.add(callAudioChar!!)
notificationSetupQueue.add(audioChar!!)
Log.i(TAG, "通话音频服务特征找到,准备串行开启通知")
} else {
Log.w(TAG, "通话音频服务特征未找到")
Log.w(TAG, "通话音频服务特征未完整找到")
}
setupNotifications(g, notifyChar)
// 将命令通知通道也纳入串行队列,避免并发写入描述符
notifyChar?.let { notificationSetupQueue.add(it) }
notificationTargetsTotal = notificationSetupQueue.size
// 启动处理队列
processNextNotificationDescriptor(g)
// 在服务发现完成后,请求最大MTU
//requestMaxMtu(g)
@ -951,8 +933,27 @@ object BleService {
override fun onDescriptorWrite(
g: BluetoothGatt, d: BluetoothGattDescriptor, status: Int
) {
if (status == BluetoothGatt.GATT_SUCCESS)
Log.i(TAG, "通知描述符写入成功: ${d.characteristic.uuid}")
if (d.uuid == BleConst.CLIENT_CHAR_CONFIG_UUID) {
val charUuid = d.characteristic.uuid
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i(TAG, "通知描述符写入成功: ${charUuid}")
notificationTargetsSucceeded++
} else {
Log.e(TAG, "通知描述符写入失败: ${charUuid}, status=${status}")
}
// 当前一次写入完成,移除队首并继续处理下一个
if (notificationSetupQueue.isNotEmpty() && notificationSetupQueue.first().uuid == charUuid) {
notificationSetupQueue.removeFirst()
}
isDescriptorWriteInProgress = false
// 如果所有通知已处理完毕,且全部成功,则设置PHY
if (notificationSetupQueue.isEmpty()) {
onAllNotificationsProcessed(g)
} else {
processNextNotificationDescriptor(g)
}
}
}
/**
@ -1010,6 +1011,66 @@ object BleService {
}
return true
}
/**
* 串行处理通知描述符写入队列
* 功能:遵循Android BLE单操作约束,确保按顺序开启各通道通知
* @param g BluetoothGatt实例
*/
private fun processNextNotificationDescriptor(g: BluetoothGatt) {
if (isDescriptorWriteInProgress) return
val next = notificationSetupQueue.firstOrNull() ?: run {
onAllNotificationsProcessed(g)
return
}
val started = setupNotifications(g, next)
if (started) {
isDescriptorWriteInProgress = true
} else {
// 当前特征无法启动通知,跳过并尝试下一个
notificationSetupQueue.removeFirst()
processNextNotificationDescriptor(g)
}
}
/**
* 所有通知通道处理完成后的回调:在全部成功时设置PHY
*/
private fun onAllNotificationsProcessed(g: BluetoothGatt) {
if (notificationTargetsTotal > 0 && notificationTargetsSucceeded == notificationTargetsTotal) {
applyPreferredPhy(g)
} else {
Log.w(TAG, "通知通道未全部注册成功(${notificationTargetsSucceeded}/${notificationTargetsTotal}),跳过PHY设置")
}
}
/**
* 读取并设置首选PHY为2M(仅API 26+)
*/
private fun applyPreferredPhy(g: BluetoothGatt) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
val readResult = g.readPhy()
Log.d(TAG, "读取PHY状态请求结果: $readResult")
Handler(Looper.getMainLooper()).postDelayed({
try {
val setResult = g.setPreferredPhy(
BluetoothDevice.PHY_LE_2M_MASK,
BluetoothDevice.PHY_LE_2M_MASK,
BluetoothDevice.PHY_OPTION_NO_PREFERRED
)
Log.d(TAG, "设置PHY为2M请求结果: $setResult")
} catch (e: Exception) {
Log.w(TAG, "设置PHY失败: ${e.message}")
}
}, 500)
} catch (e: Exception) {
Log.w(TAG, "读取PHY失败: ${e.message},将使用默认1M PHY")
}
} else {
Log.w(TAG, "当前Android版本不支持PHY设置(需要API 26+),使用默认1M PHY")
}
}
/**
* 请求最大MTU值
@ -1033,6 +1094,7 @@ object BleService {
* @param data 音频数据 (Opus编码)
*/
private fun processAudioData(data: ByteArray) {
recordfile?.saveAudioDataToWav(data)
// 委托给Opus音频管理器处理
opusAudioManager.processAudioData(data)
}
@ -1344,6 +1406,8 @@ object BleService {
*/
fun closeCodec(): Boolean {
Log.i(TAG, "关闭编解码...")
recordfile?.closeFile()
recordfile1?.closeFile()
val cmdData = byteArrayOf(
BleConst.CODEC_CONTROL_CLOSE.toByte(),
BleConst.AUDIO_CHANNEL_STEREO.toByte()
@ -1688,5 +1752,3 @@ object BleService {
}
}

Loading…
Cancel
Save