From b448c7717da0ea0775b2b7275bedde179087102c Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 16 Oct 2025 21:11:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0tts=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/models/appconfig_model.g.dart | 7 +++ .../agent/controllers/agent_controller.dart | 51 ++++++++++------- .../agent_service/AgentService.kt | 57 ++++++++++++++++--- .../agent_service/AgentServicePlugin.kt | 5 +- .../agent_service/lib/agent_service.dart | 6 +- 5 files changed, 95 insertions(+), 31 deletions(-) diff --git a/lib/data/models/appconfig_model.g.dart b/lib/data/models/appconfig_model.g.dart index 77b929248..f99ba35c6 100644 --- a/lib/data/models/appconfig_model.g.dart +++ b/lib/data/models/appconfig_model.g.dart @@ -87,5 +87,12 @@ DBProduct _$DBProductFromJson(Map json) => DBProduct( Map _$DBProductToJson(DBProduct instance) => { 'id': instance.id, 'factoryid': instance.factoryid, + 'devicetype': instance.devicetype, + 'productimage': instance.productimage, + 'scanuuid': instance.scanuuid, + 'version': instance.version, + 'iscontinuouschat': instance.iscontinuouschat, 'devicename': instance.devicename, + 'updatedescription': instance.updatedescription, + 'updatepackageaddress': instance.updatepackageaddress, }; diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index 91edf4dc9..1810d0b93 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -41,6 +41,7 @@ enum VoiceInputMode { class AgentController extends GetxController with WidgetsBindingObserver { static AgentController get to => Get.find(); //单例访问模式 + final GetStorage _storage = GetStorage(); // 聊天消息列表 final messages = [].obs; final currsessionid = ''.obs; @@ -79,7 +80,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { // TTS启用状态 final isTtsEnabled = true.obs; // TTS播报打断启用状态 - final isTtsInterruptEnabled = true.obs; + final isTtsInterruptEnabled = false.obs; // 是否显示工具调用 final isShowToolInterruptEnabled = false.obs; // 图片处理状态 @@ -166,6 +167,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { super.onInit(); _initAppDir(); _loadTtsPreference(); //加载TTS偏好设置 + _loadTtsInterrupe(); //加载TTS播报打断偏好设置 _setupScrollListener(); //设置滚动监听器 _loadChatHistory(); //加载聊天历史记录 _subscribeToEvents(); //订阅代理服务事件 @@ -178,14 +180,6 @@ class AgentController extends GetxController with WidgetsBindingObserver { // 监听应用生命周期:当应用切到后台/失焦时兜底结束按住说话,防止 onPointerUp 未触发 WidgetsBinding.instance.addObserver(this); - // 获取设备类型以确定检查策略 - String deviceName = getDeviceName(); - DBProduct? product = AppConfig.getproduct(deviceName); - if (product != null) { - isTtsInterruptEnabled.value = !product.iscontinuouschat!; - } else { - isTtsInterruptEnabled.value = false; - } // _qqmusicManager.syncCurrentPlayInfo(); } @@ -269,30 +263,47 @@ class AgentController extends GetxController with WidgetsBindingObserver { } } + // 加载TTS偏好设置 + Future _loadTtsInterrupe() async { + try { + if (!_storage.hasData("agent_tts_interrupe")) { + // 获取设备类型以确定检查策略 + String deviceName = getDeviceName(); + DBProduct? product = AppConfig.getproduct(deviceName); + if (deviceName != "" && product != null) { + // Logger.d('AgentController', + // 'liwe----------product $deviceName ${product.toJson()}'); + isTtsInterruptEnabled.value = !product.iscontinuouschat!; + } else { + isTtsInterruptEnabled.value = false; + } + } else { + isTtsInterruptEnabled.value = + _storage.read('agent_tts_interrupe') ?? false; + } + } catch (e) { + // 如果读取失败,使用默认值 + Logger.e(TAG, '加载TTS偏好设置失败: $e'); + isTtsInterruptEnabled.value = false; + } + } + /// 切换TTS播报打断状态 /// 当启用播报打断时,用户说话会自动停止当前的TTS播放 Future toggleTtsInterrupt() async { isTtsInterruptEnabled.toggle(); - + await _storage.write('agent_tts_interrupe', isTtsInterruptEnabled.value); // 保存偏好设置 try { - await AgentService.isInterrupt(); + await AgentService.isInterrupt(isTtsInterruptEnabled.value); } catch (e) { Logger.e(TAG, '保存TTS播报打断偏好设置失败: $e'); } } - /// 切换TTS播报打断状态 - /// 当启用播报打断时,用户说话会自动停止当前的TTS播放 + /// 当启用显示工具调用效果 Future toggleShowAIToolInterrupt() async { isShowToolInterruptEnabled.toggle(); - - // 保存偏好设置 - try { - await AgentService.isInterrupt(); - } catch (e) { - Logger.e(TAG, '保存TTS播报打断偏好设置失败: $e'); - } } // 设置文本输入监听器 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 65cd078bb..5ef4e504f 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 @@ -2,6 +2,7 @@ package com.yunqiinnovation.agent_service import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.os.Handler import android.os.Looper import org.json.JSONArray @@ -62,9 +63,12 @@ interface AgentServiceListener { */ object AgentService : CoroutineScope { private val TAG = "AgentService" + + // SharedPreferences 相关常量 + private const val PREF_NAME = "agent_service_prefs" + private const val KEY_IS_INTERRUPT = "is_interrupt" - - private var _isInterrupt = AtomicBoolean(true) + private var _isInterrupt = AtomicBoolean(false) private var azureSpeechKey: String = "" private var azureSpeechRegion: String = "" @@ -201,6 +205,10 @@ object AgentService : CoroutineScope { callingTool = config["callingTool"]?.toString() ?: ""; // 初始化上下文和服务 this.context = appContext.applicationContext + + // 从 SharedPreferences 读取 _isInterrupt 状态 + loadIsInterruptFromCache() + this.chatApiService = ChatApiService(context) this.chatStorageHelper = ChatStorageHelper(context) this.audioPlayer = AudioPlayer(context) @@ -535,11 +543,15 @@ object AgentService : CoroutineScope { * 如果当前为false,则设置为true;如果当前为true,则设置为false * @return 切换后的状态值 */ - fun isInterrupt(): Boolean { - val currentValue = _isInterrupt.get() - val newValue = !currentValue - _isInterrupt.set(newValue) - return newValue + fun isInterrupt(isInterrupt: Boolean): Boolean { + // val currentValue = _isInterrupt.get() + // val newValue = !currentValue + _isInterrupt.set(isInterrupt) + + // 保存到 SharedPreferences + saveIsInterruptToCache(isInterrupt) + + return isInterrupt } /** * 开始语音识别 @@ -2565,4 +2577,35 @@ object AgentService : CoroutineScope { } } } + + /** + * 从 SharedPreferences 加载 _isInterrupt 状态 + */ + private fun loadIsInterruptFromCache() { + try { + if (::context.isInitialized) { + val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + val cachedValue = prefs.getBoolean(KEY_IS_INTERRUPT, false) // 默认值为 false + _isInterrupt.set(cachedValue) + Log.d(TAG, "从缓存加载 _isInterrupt 状态: $cachedValue") + } + } catch (e: Exception) { + Log.e(TAG, "加载 _isInterrupt 缓存状态时发生异常: ${e.message}", e) + } + } + + /** + * 保存 _isInterrupt 状态到 SharedPreferences + */ + private fun saveIsInterruptToCache(isInterrupt: Boolean) { + try { + if (::context.isInitialized) { + val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + prefs.edit().putBoolean(KEY_IS_INTERRUPT, isInterrupt).apply() + Log.d(TAG, "保存 _isInterrupt 状态到缓存: $isInterrupt") + } + } catch (e: Exception) { + Log.e(TAG, "保存 _isInterrupt 缓存状态时发生异常: ${e.message}", e) + } + } } \ No newline at end of file diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt index 27ecd2105..735672a7c 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt @@ -132,8 +132,9 @@ class AgentServicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stream } "isInterrupt" -> { try { - val isInterrupt = AgentService.isInterrupt() - result.success(isInterrupt) + val isinterrupt = call.argument("isinterrupt") + val _isInrrupt = isinterrupt?.let { AgentService.isInterrupt(isinterrupt) } + result.success(_isInrrupt) } catch (e: Exception) { Log.e(TAG, "检查是否打断失败", e) result.error("IS_INTERRUPT_ERROR", "检查是否打断失败: ${e.message}", null) diff --git a/local_plugins/agent_service/lib/agent_service.dart b/local_plugins/agent_service/lib/agent_service.dart index 35fe573f0..689a17c6c 100644 --- a/local_plugins/agent_service/lib/agent_service.dart +++ b/local_plugins/agent_service/lib/agent_service.dart @@ -266,9 +266,11 @@ class AgentService { } } - static Future isInterrupt() async { + static Future isInterrupt(bool isInterrupt) async { try { - final bool result = await _channel.invokeMethod('isInterrupt'); + final bool result = await _channel.invokeMethod('isInterrupt', { + 'isinterrupt': isInterrupt, + }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '检查是否打断失败', e.details);