diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt index fdd51c709..ad17ede21 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt @@ -26,6 +26,7 @@ import com.deep_voice.speech.tts.TtsEventListener import com.deep_voice.speech.tts.TtsEventType import com.deep_voice.bytedance_speech.BytedanceTTS import java.util.UUID +import com.yunqiinnovation.agent_service.Utils /** * 代理服务事件监听接口 @@ -1164,6 +1165,22 @@ object AgentService : CoroutineScope { class AudioPlayer(private val context: Context) { private var mediaPlayer: MediaPlayer? = null private var isInitialized = false + private val playbackLock = Object() // 添加同步锁 + + /** + * 安全检查 MediaPlayer 是否正在播放 + */ + private fun isMediaPlayerPlaying(): Boolean { + return try { + mediaPlayer?.isPlaying == true + } catch (e: IllegalStateException) { + Log.w(TAG, "MediaPlayer 状态异常,假定未播放: ${e.message}") + false + } catch (e: Exception) { + Log.w(TAG, "检查播放状态时发生异常: ${e.message}") + false + } + } /** * 播放音频资源 @@ -1172,75 +1189,167 @@ object AgentService : CoroutineScope { * @param volume 音量大小,范围0.0-1.0,默认1.0 */ fun playAudio(resId: Int, isLooping: Boolean = false, volume: Float = 1.0f) { - try { - // 释放之前的资源 - release() + synchronized(playbackLock) { + try { + // 强制停止并释放之前的资源 + forceStop() - // 创建播放器并设置资源 - mediaPlayer = MediaPlayer().apply { - // 设置资源 - context.resources.openRawResourceFd(resId)?.use { fd -> - setDataSource(fd.fileDescriptor, fd.startOffset, fd.length) - } + // 创建播放器并设置资源 + mediaPlayer = MediaPlayer().apply { + // 设置资源 + context.resources.openRawResourceFd(resId)?.use { fd -> + setDataSource(fd.fileDescriptor, fd.startOffset, fd.length) + } - this.isLooping = isLooping // 设置循环属性 - setVolume(volume, volume) // 设置音量(左声道,右声道) + this.isLooping = isLooping // 设置循环属性 + setVolume(volume, volume) // 设置音量(左声道,右声道) - setOnCompletionListener { - if (!isLooping) { - release() + setOnCompletionListener { + if (!isLooping) { + release() + } } - } - prepare() - start() + setOnErrorListener { _, what, extra -> + Log.e(TAG, "MediaPlayer 错误: what=$what, extra=$extra") + forceRelease() + true // 返回true表示错误已处理 + } + + prepare() + start() + Log.d(TAG, "开始播放音频资源: $resId, 循环: $isLooping") + } + isInitialized = true + } catch (e: Exception) { + Log.e(TAG, "播放音频资源异常: ${e.message}", e) + forceRelease() } - } catch (e: Exception) { - Log.e(TAG, "播放音频资源异常: ${e.message}", e) - release() } } + /** + * 停止音频播放 + */ fun stopAudio() { - try { - mediaPlayer?.apply { - when { - isPlaying -> { + synchronized(playbackLock) { + try { + mediaPlayer?.apply { + if (isMediaPlayerPlaying()) { stop() Log.d(TAG, "音频已停止") - } - else -> { + } else { Log.d(TAG, "音频未在播放状态,无需停止") } } + } catch (e: IllegalStateException) { + Log.e(TAG, "MediaPlayer 状态异常,无法停止: ${e.message}", e) + forceRelease() + } catch (e: Exception) { + Log.e(TAG, "停止音频播放异常: ${e.message}", e) + forceRelease() } - } catch (e: IllegalStateException) { - Log.e(TAG, "MediaPlayer 状态异常,无法停止: ${e.message}", e) - // 重置 MediaPlayer - release() - } catch (e: Exception) { - Log.e(TAG, "停止音频播放异常: ${e.message}", e) } } /** - * 释放资源 + * 强制停止播放(不释放资源) */ - fun release() { + private fun forceStop() { try { mediaPlayer?.apply { - if (isPlaying) { - stop() + if (isMediaPlayerPlaying()) { + try { + stop() + Log.d(TAG, "强制停止音频播放") + } catch (e: Exception) { + Log.w(TAG, "强制停止时异常: ${e.message}") + } + } + try { + reset() + } catch (e: Exception) { + Log.w(TAG, "重置时异常: ${e.message}") } - reset() - release() } - mediaPlayer = null - isInitialized = false } catch (e: Exception) { - Log.e(TAG, "释放音频资源异常: ${e.message}", e) - mediaPlayer = null - isInitialized = false + Log.w(TAG, "强制停止过程中异常: ${e.message}") + } + } + + /** + * 释放资源 + */ + fun release() { + synchronized(playbackLock) { + try { + mediaPlayer?.apply { + // 安全停止播放 + if (isMediaPlayerPlaying()) { + try { + stop() + } catch (e: IllegalStateException) { + Log.w(TAG, "停止播放时状态异常: ${e.message}") + } + } + + // 安全重置 + try { + reset() + } catch (e: IllegalStateException) { + Log.w(TAG, "重置 MediaPlayer 时状态异常: ${e.message}") + } + + // 安全释放 - 修复递归调用问题 + try { + release() // 这里调用的是 MediaPlayer.release(),不是递归 + } catch (e: Exception) { + Log.w(TAG, "释放 MediaPlayer 时异常: ${e.message}") + } + } + } catch (e: Exception) { + Log.e(TAG, "释放音频资源异常: ${e.message}", e) + } finally { + // 确保变量被清理 + mediaPlayer = null + isInitialized = false + } + } + } + + /** + * 强制释放资源,不进行状态检查 + */ + private fun forceRelease() { + synchronized(playbackLock) { + try { + mediaPlayer?.apply { + try { + reset() + } catch (e: Exception) { + Log.w(TAG, "重置 MediaPlayer 失败: ${e.message}") + } + try { + release() + } catch (e: Exception) { + Log.w(TAG, "释放 MediaPlayer 失败: ${e.message}") + } + } + } catch (e: Exception) { + Log.w(TAG, "强制释放资源时发生异常: ${e.message}") + } finally { + mediaPlayer = null + isInitialized = false + } + } + } + + /** + * 检查是否正在播放 + */ + fun isPlaying(): Boolean { + synchronized(playbackLock) { + return isMediaPlayerPlaying() } } }