From b5cb6a62a19f90ed3a14e20fdfe4dce3ef901b62 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Fri, 8 Aug 2025 19:18:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E6=88=9080=E5=AD=97=E8=8A=82=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/login/bindings/login_binding.dart | 5 +- .../login/controllers/login_controller.dart | 35 ++++-- .../yunqiinnovation/ble_service/BleService.kt | 100 +++++++++++++++--- 3 files changed, 113 insertions(+), 27 deletions(-) diff --git a/lib/modules/login/bindings/login_binding.dart b/lib/modules/login/bindings/login_binding.dart index 6729681f9..28907a22e 100644 --- a/lib/modules/login/bindings/login_binding.dart +++ b/lib/modules/login/bindings/login_binding.dart @@ -4,6 +4,7 @@ import '../controllers/login_controller.dart'; class LoginBinding extends Bindings { @override void dependencies() { - Get.lazyPut(() => LoginController()); + // 使用 put 而不是 lazyPut,确保控制器立即创建 + Get.put(LoginController(), permanent: false); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/lib/modules/login/controllers/login_controller.dart b/lib/modules/login/controllers/login_controller.dart index bb93f65f3..334681334 100644 --- a/lib/modules/login/controllers/login_controller.dart +++ b/lib/modules/login/controllers/login_controller.dart @@ -211,15 +211,30 @@ class LoginController extends GetxController { String get displayContact => _displayContact.value; List get verificationCode => _verificationCode; - // 文本控制器 - TextEditingController contactController = TextEditingController(); - TextEditingController verificationCodeController = TextEditingController(); + // 文本控制器 - 延迟初始化 + TextEditingController? _contactController; + TextEditingController? _verificationCodeController; + + // Getter 方法,确保控制器存在 + TextEditingController get contactController { + _contactController ??= TextEditingController(); + return _contactController!; + } + + TextEditingController get verificationCodeController { + _verificationCodeController ??= TextEditingController(); + return _verificationCodeController!; + } @override void onInit() { super.onInit(); _viewState.value = LoginViewState.welcome; + // 初始化控制器 + _contactController = TextEditingController(); + _verificationCodeController = TextEditingController(); + isChinaMainland.value = Get.deviceLocale?.countryCode?.toUpperCase() == 'CN'; @@ -236,17 +251,21 @@ class LoginController extends GetxController { @override void onClose() { - // Safely dispose controllers + // 安全地销毁控制器 try { - contactController.dispose(); + _contactController?.dispose(); + _contactController = null; } catch (e) { - // Controller already disposed + Logger().e('销毁 contactController 失败: $e'); } + try { - verificationCodeController.dispose(); + _verificationCodeController?.dispose(); + _verificationCodeController = null; } catch (e) { - // Controller already disposed + Logger().e('销毁 verificationCodeController 失败: $e'); } + super.onClose(); } diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt index 299005b5f..b56963757 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt @@ -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() // 初始化状态 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)