|
|
|
@ -126,14 +126,19 @@ object BleService { |
|
|
|
private val isAudioSending = AtomicBoolean(false) |
|
|
|
|
|
|
|
// 音频数据分块发送的常量 |
|
|
|
private val AUDIO_CHUNK_SIZE = 40 // 每次发送40字节 |
|
|
|
private val AUDIO_SEND_INTERVAL = 20L // 发送间隔10ms |
|
|
|
private val AUDIO_CHUNK_SIZE = 80 // 每次发送80字节 |
|
|
|
private val AUDIO_SEND_INTERVAL = 40L // 发送间隔20ms |
|
|
|
|
|
|
|
// 音频数据缓冲区,用于累积数据到80字节再发送 |
|
|
|
private val audioBuffer = mutableListOf<Byte>() |
|
|
|
|
|
|
|
// 初始化状态 |
|
|
|
private var isInitialized = false |
|
|
|
|
|
|
|
// 音频数据统计相关变量 |
|
|
|
private var bytesReceivedInCurrentSecond = 0 |
|
|
|
// 添加发送数据统计变量 |
|
|
|
private var bytesSentInCurrentSecond = 0 |
|
|
|
private var lastStatisticsTime = System.currentTimeMillis() |
|
|
|
private val statisticsHandler = Handler(Looper.getMainLooper()) |
|
|
|
private val statisticsRunnable = object : Runnable { |
|
|
|
@ -142,7 +147,9 @@ object BleService { |
|
|
|
val timeDiff = currentTime - lastStatisticsTime |
|
|
|
if (timeDiff >= 1000) { // 每秒统计一次 |
|
|
|
Log.i(TAG, "每秒接收音频数据: $bytesReceivedInCurrentSecond 字节") |
|
|
|
Log.i(TAG, "每秒发送音频数据: $bytesSentInCurrentSecond 字节") |
|
|
|
bytesReceivedInCurrentSecond = 0 |
|
|
|
bytesSentInCurrentSecond = 0 |
|
|
|
lastStatisticsTime = currentTime |
|
|
|
} |
|
|
|
statisticsHandler.postDelayed(this, 1000) // 每秒执行一次 |
|
|
|
@ -1376,28 +1383,33 @@ startBytesStatistics() |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 将音频数据分块并加入发送队列 |
|
|
|
* 将音频数据添加到发送队列 |
|
|
|
* 只有当缓冲区达到80字节时才发送数据 |
|
|
|
* @param data 音频数据字节数组 |
|
|
|
*/ |
|
|
|
private fun addAudioDataToSendQueue(data: ByteArray) { |
|
|
|
try { |
|
|
|
// 将大数据分成40字节的小块 |
|
|
|
var offset = 0 |
|
|
|
while (offset < data.size) { |
|
|
|
val chunkSize = minOf(AUDIO_CHUNK_SIZE, data.size - offset) |
|
|
|
val chunk = ByteArray(chunkSize) |
|
|
|
System.arraycopy(data, offset, chunk, 0, chunkSize) |
|
|
|
// 将新数据添加到缓冲区 |
|
|
|
audioBuffer.addAll(data.toList()) |
|
|
|
|
|
|
|
// 当缓冲区达到80字节时,发送数据 |
|
|
|
while (audioBuffer.size >= 80) { |
|
|
|
// 取出80字节数据 |
|
|
|
val chunk = ByteArray(80) |
|
|
|
for (i in 0 until 80) { |
|
|
|
chunk[i] = audioBuffer.removeAt(0) |
|
|
|
} |
|
|
|
|
|
|
|
// 将分块数据加入队列 |
|
|
|
// 将数据加入发送队列 |
|
|
|
if (!audioSendQueue.offer(chunk)) { |
|
|
|
Log.w(TAG, "音频发送队列已满,丢弃数据块") |
|
|
|
break |
|
|
|
} |
|
|
|
|
|
|
|
offset += chunkSize |
|
|
|
} |
|
|
|
|
|
|
|
Log.d(TAG, "音频数据已分块加入队列,原始大小: ${data.size} 字节,分块数: ${(data.size + AUDIO_CHUNK_SIZE - 1) / AUDIO_CHUNK_SIZE}") |
|
|
|
// Log.d(TAG, "音频数据已加入缓冲区,当前缓冲区大小: ${audioBuffer.size} 字节") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "分块音频数据异常: ${e.message}", e) |
|
|
|
Log.e(TAG, "处理音频数据异常: ${e.message}", e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -1448,11 +1460,13 @@ startBytesStatistics() |
|
|
|
isAudioSending.set(false) |
|
|
|
audioSendThread?.interrupt() |
|
|
|
audioSendQueue.clear() |
|
|
|
Log.i(TAG, "音频发送线程已停止,队列已清空") |
|
|
|
audioBuffer.clear() // 清空音频缓冲区 |
|
|
|
Log.i(TAG, "音频发送线程已停止,队列和缓冲区已清空") |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送单个音频数据块 |
|
|
|
* 发送音频数据块到设备 |
|
|
|
* @param chunk 要发送的音频数据块 |
|
|
|
*/ |
|
|
|
private fun sendAudioChunk(chunk: ByteArray) { |
|
|
|
try { |
|
|
|
@ -1468,9 +1482,61 @@ startBytesStatistics() |
|
|
|
val isSuccess = bluetoothGatt?.writeCharacteristic(callWriteChar) |
|
|
|
|
|
|
|
if (isSuccess == true) { |
|
|
|
// 累加发送成功的字节数 |
|
|
|
bytesSentInCurrentSecond += chunk.size |
|
|
|
Log.d(TAG, "成功发送音频数据块,大小: ${chunk.size} 字节") |
|
|
|
} else { |
|
|
|
Log.e(TAG, "发送音频数据块失败,大小: ${chunk.size} 字节") |
|
|
|
// 详细的失败原因分析 |
|
|
|
val failureReason = StringBuilder("发送音频数据块失败,大小: ${chunk.size} 字节") |
|
|
|
|
|
|
|
// 检查蓝牙连接状态 |
|
|
|
if (bluetoothGatt == null) { |
|
|
|
failureReason.append(" - 原因: BluetoothGatt为空") |
|
|
|
} else { |
|
|
|
// 检查连接状态 |
|
|
|
val connectionState = bluetoothManager.getConnectionState( |
|
|
|
bluetoothGatt!!.device, |
|
|
|
BluetoothProfile.GATT |
|
|
|
) |
|
|
|
when (connectionState) { |
|
|
|
BluetoothProfile.STATE_DISCONNECTED -> { |
|
|
|
failureReason.append(" - 原因: 设备已断开连接") |
|
|
|
} |
|
|
|
BluetoothProfile.STATE_CONNECTING -> { |
|
|
|
failureReason.append(" - 原因: 设备正在连接中") |
|
|
|
} |
|
|
|
BluetoothProfile.STATE_DISCONNECTING -> { |
|
|
|
failureReason.append(" - 原因: 设备正在断开连接") |
|
|
|
} |
|
|
|
BluetoothProfile.STATE_CONNECTED -> { |
|
|
|
// 连接正常,检查其他原因 |
|
|
|
if (callWriteChar == null) { |
|
|
|
failureReason.append(" - 原因: 写入特征值为空") |
|
|
|
} else { |
|
|
|
// 检查特征值属性 |
|
|
|
val properties = callWriteChar!!.properties |
|
|
|
if ((properties and BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 && |
|
|
|
(properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) { |
|
|
|
failureReason.append(" - 原因: 特征值不支持写入操作") |
|
|
|
} else if (chunk.size > 512) { // BLE MTU通常限制 |
|
|
|
failureReason.append(" - 原因: 数据块过大 (${chunk.size} > 512字节)") |
|
|
|
} else { |
|
|
|
failureReason.append(" - 原因: 未知错误,可能是设备忙碌或缓冲区满") |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else -> { |
|
|
|
failureReason.append(" - 原因: 未知连接状态($connectionState)") |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 检查蓝牙适配器状态 |
|
|
|
if (bluetoothAdapter?.isEnabled != true) { |
|
|
|
failureReason.append(" - 蓝牙适配器未启用") |
|
|
|
} |
|
|
|
|
|
|
|
Log.e(TAG, failureReason.toString()) |
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "发送音频数据块异常: ${e.message}", e) |
|
|
|
|