From 1a9b9049566eace36200dc7debe8c0c0f1575db5 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Fri, 12 Sep 2025 16:36:04 +0800 Subject: [PATCH] add. --- .../azure_speech/AzureAsrHelper.kt | 81 ++++++++++++++++++- .../azure_speech/tools/SimpleAudioReceiver.kt | 13 +-- .../ble_service/BleCompanionManager.kt | 2 +- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt index 08bf94688..8fc25365a 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt @@ -12,7 +12,7 @@ import android.os.Looper import java.util.concurrent.TimeUnit import com.yunqiinnovation.azure_speech.tools.RecordFile import com.microsoft.cognitiveservices.speech.audio.AudioConfig - +import com.yunqiinnovation.azure_speech.tools.AudioRecordingForegroundService /** @@ -31,6 +31,8 @@ class AzureAsrHelper(private val context: Context) { private var audioConfig: AudioConfig? = null private var continuousCallback: ContinuousRecognizeCallback? = null + // 添加前台服务管理标志 + private var isForegroundServiceRunning = false // 配置参数 private var currentLanguage = "zh-CN" private var supportedLanguages = arrayOf("zh-CN") @@ -247,6 +249,20 @@ class AzureAsrHelper(private val context: Context) { if (audioStream.isContinuousRecognitionActive) { return true } + + // 启动前台服务(在开始音频录制前) + if (!isForegroundServiceRunning && audioSourceType == AudioSourceType.MICROPHONE) { + try { + AudioRecordingForegroundService.startService(context) + isForegroundServiceRunning = true + Log.d(tag, "前台服务已启动") + } catch (e: Exception) { + Log.e(tag, "启动前台服务失败: ${e.message}") + continuousCallback?.onError(1003, "启动前台服务失败: ${e.message}") + return false + } + } + if (!isRecognizerValid()) { Log.d(tag, "重新启动连续识别") val callback = continuousCallback @@ -393,6 +409,18 @@ class AzureAsrHelper(private val context: Context) { recognizer?.close() recognizer = null audioStream.isContinuousRecognitionActive = false + + // 停止前台服务 + if (isForegroundServiceRunning) { + try { + AudioRecordingForegroundService.stopService(context) + isForegroundServiceRunning = false + Log.d(tag, "前台服务已停止") + } catch (e: Exception) { + Log.e(tag, "停止前台服务失败: ${e.message}") + } + } + return true } catch (e: Exception) { // 强制重置状态 @@ -404,6 +432,17 @@ class AzureAsrHelper(private val context: Context) { recognizer?.close() recognizer = null audioStream.isContinuousRecognitionActive = false + + // 确保前台服务被停止 + if (isForegroundServiceRunning) { + try { + AudioRecordingForegroundService.stopService(context) + isForegroundServiceRunning = false + } catch (e2: Exception) { + Log.e(tag, "强制停止前台服务失败: ${e2.message}") + } + } + return false } } @@ -442,6 +481,18 @@ class AzureAsrHelper(private val context: Context) { // 释放音频配置 audioConfig?.close() audioConfig = null + + // 确保前台服务被停止 + if (isForegroundServiceRunning) { + try { + AudioRecordingForegroundService.stopService(context) + isForegroundServiceRunning = false + Log.d(tag, "dispose时前台服务已停止") + } catch (e: Exception) { + Log.e(tag, "dispose时停止前台服务失败: ${e.message}") + } + } + // 确保状态被重置 audioStream.isContinuousRecognitionActive = false @@ -451,6 +502,7 @@ class AzureAsrHelper(private val context: Context) { audioConfig = null recognizer = null speechConfig = null + isForegroundServiceRunning = false } } @@ -479,11 +531,23 @@ class AzureAsrHelper(private val context: Context) { */ fun enableRecord(audioSourceType: AudioSourceType = AudioSourceType.MICROPHONE,filePath: String, audioDataCallback: SimpleAudioReceiver.AudioDataCallback? = null) { Log.i(tag, "开启录音:") - this.audioSourceType = audioSourceType + this.audioSourceType = audioSourceType if(audioSourceType == AudioSourceType.EXTERNAL){ - Log.i(tag, "外部音频源不在这里录音") + Log.i(tag, "外部音频源不在这里录音") return } + + // 启动前台服务(在开始录音前) + if (!isForegroundServiceRunning) { + try { + AudioRecordingForegroundService.startService(context) + isForegroundServiceRunning = true + Log.d(tag, "录音前台服务已启动") + } catch (e: Exception) { + Log.e(tag, "启动录音前台服务失败: ${e.message}") + } + } + // Initialize if not already done if (!audioStream.isInitialized()) { audioStream.initAudioRecord() @@ -574,6 +638,17 @@ class AzureAsrHelper(private val context: Context) { if (!audioStream.isContinuousRecognitionActive) { audioStream.stopMicrophoneCapture() + + // 停止录音时也停止前台服务(如果没有其他音频任务) + if (isForegroundServiceRunning) { + try { + AudioRecordingForegroundService.stopService(context) + isForegroundServiceRunning = false + Log.d(tag, "录音前台服务已停止") + } catch (e: Exception) { + Log.e(tag, "停止录音前台服务失败: ${e.message}") + } + } } audioStream.isRecord = false diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt index 5dddebd68..cc72aa389 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt @@ -17,7 +17,7 @@ import android.media.AudioFocusRequest import android.media.AudioAttributes import com.yunqiinnovation.azure_speech.tools.RecordFile import android.os.Build // 新增:用于获取设备信息 -import com.yunqiinnovation.azure_speech.tools.AudioRecordingForegroundService + /** * 简单音频接收器类,用于处理音频录制和流传输 @@ -219,8 +219,6 @@ fun startAudioRecord(audioSourceType: AudioSourceType, callback: AudioDataCallba pushAudioStream?.close() pushAudioStream = null isWriting.set(false) - // 停止前台服务 - AudioRecordingForegroundService.stopService(context) throw e // 重新抛出异常让调用者处理 } } @@ -296,8 +294,7 @@ fun startAudioRecord(audioSourceType: AudioSourceType, callback: AudioDataCallba */ private fun runMicrophoneCapture() { try { - // 启动前台服务 - AudioRecordingForegroundService.startService(context) + Log.d(TAG, "前台服务已启动,开始音频录制") // 根据手机品牌决定是否设置通话音频模式 if (isHonorDevice()) { @@ -410,8 +407,7 @@ fun startAudioRecord(audioSourceType: AudioSourceType, callback: AudioDataCallba try { writeQueue.clear() isWriting.set(false) - // 停止前台服务 - AudioRecordingForegroundService.stopService(context) + // 停止录音 @@ -431,8 +427,7 @@ fun startAudioRecord(audioSourceType: AudioSourceType, callback: AudioDataCallba try { isRunning.set(false) isWriting.set(false) - // 停止前台服务 - AudioRecordingForegroundService.stopService(context) + Log.d(TAG, "前台服务已停止,音频资源已释放") // 中断并等待捕获线程结束 writeThread?.interrupt() diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCompanionManager.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCompanionManager.kt index 5694090f6..5e73b6aaf 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCompanionManager.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCompanionManager.kt @@ -396,7 +396,7 @@ class BleCompanionManager(private val context: Context) { val filter = ScanFilter.Builder() .setDeviceAddress(mac) // .setServiceUuid(ParcelUuid(java.util.UUID.fromString("0000FEAA-0000-1000-8000-00805F9B34FB"))) - .setManufacturerData(0xEFAB, byteArrayOf(0xA0.toByte(), 0x01)) + //.setManufacturerData(0xEFAB, byteArrayOf(0xA0.toByte(), 0x01)) .build() // 扫描设置