diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart index b55927d5a..4c885ecc7 100644 --- a/lib/data/services/ble_manager.dart +++ b/lib/data/services/ble_manager.dart @@ -549,6 +549,40 @@ class BleManager extends GetxService { // 从Flutter资源包中加载.mcp.json final jsonData = AppConfig.mcpConfig(); + // 根据APP语言动态配置语音识别语言 + List supportedLanguages = []; + try { + // 使用 GetX 获取 APP 当前语言环境 (Locale) + final appLocale = Get.locale; + + if (appLocale != null) { + final lang = appLocale.languageCode; // e.g., 'en' + final country = appLocale.countryCode; // e.g., 'US' + + // 构造 Azure SDK 需要的格式 (e.g., 'en-US') + if (country != null && country.isNotEmpty) { + supportedLanguages.add('$lang-$country'); + } else { + supportedLanguages.add(lang); // fallback only language code + } + } + + // 添加 en-US 作为备选 + if (!supportedLanguages.contains('en-US')) { + supportedLanguages.add('en-US'); + } + + // 最终兜底 + if (supportedLanguages.isEmpty) { + supportedLanguages.add('en-US'); + } + + Logger.info('动态配置语音识别语言: ${supportedLanguages.join(', ')}'); + } catch (e) { + Logger.error('获取APP语言配置失败,使用默认语言: $e'); + supportedLanguages = ['zh-CN', 'en-US']; + } + final config = { // 语音代理配置参数 'azureSpeechKey': azureSpeechKey, @@ -563,7 +597,7 @@ class BleManager extends GetxService { 'volcanoToken': 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En', 'serverurl': serverurl, 'usertoken': jsonString, - 'supportedLanguages': ['zh-CN'], + 'supportedLanguages': supportedLanguages, }; // 记录日志(不记录敏感信息) diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index c29675888..dda9ed2c4 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -153,7 +153,7 @@ class AgentController extends GetxController { _setupMediaSessionCallbacks(); //设置媒体会话回调 _setupTextInputListener(); //设置文本输入监听器 - _configureSpeechRecognitionLanguages(); //配置语音识别语言 + startVoiceInput(); //开启语音输入 } @@ -1013,49 +1013,7 @@ class AgentController extends GetxController { } } -//根据APP语言配置语音识别语言 - Future _configureSpeechRecognitionLanguages() async { - try { - // 1. 使用 GetX 获取 APP 当前语言环境 (Locale) - final appLocale = Get.locale; - List languagesToSupport = []; - - if (appLocale != null) { - final lang = appLocale.languageCode; // e.g., 'en' - final country = appLocale.countryCode; // e.g., 'US' - - // 2. 构造 Azure SDK 需要的格式 (e.g., 'en-US') - if (country != null && country.isNotEmpty) { - languagesToSupport.add('$lang-$country'); - } else { - languagesToSupport.add(lang); // fallback only language code - } - } - // 3. 添加 en-US 作为备选 - if (!languagesToSupport.contains('en-US')) { - languagesToSupport.add('en-US'); - } - - // 4. 最终兜底 - if (languagesToSupport.isEmpty) { - languagesToSupport.add('en-US'); - } - - // 5. 调用原生设置 - Logger.i(TAG, '支持的语言: ${languagesToSupport.join(', ')}'); - AgentService.setSupportedLanguages(languagesToSupport).then((success) { - if (success) { - Logger.i(TAG, 'asr的语言已根据 APP 设置语言: ${languagesToSupport.join(', ')}'); - } else { - Logger.w(TAG, '根据 APP 设置asr语言失败'); - } - }); - } catch (e) { - Logger.e(TAG, "获取 APP 语言并设置失败: $e"); - AgentService.setSupportedLanguages(['zh-CN', 'en-US']); - } - } // 开始语音输入 Future startVoiceInput() async { 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 8229f4863..60b919843 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 @@ -74,6 +74,19 @@ class AgentServicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stream config["serverurl"]?.toString()?.let { intent.putExtra("serverurl", it) } config["usertoken"]?.toString()?.let { intent.putExtra("usertoken", it) } + // 添加 supportedLanguages 参数处理 + config["supportedLanguages"]?.let { languages -> + when (languages) { + is List<*> -> { + // 将 List 转换为 ArrayList 以便传递给 Intent + val languageList = languages.filterIsInstance() + if (languageList.isNotEmpty()) { + intent.putStringArrayListExtra("supportedLanguages", ArrayList(languageList)) + } + } + } + } + // 启动前台服务 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt index 93c016657..9eb03b1f3 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt @@ -51,6 +51,7 @@ class BleMediaService : Service(), CoroutineScope { private const val KEY_SERVER_URL = "serverurl" private const val KEY_USER_TOKEN = "usertoken" + private const val KEY_SUPPORTED_LANGUAGES = "supportedLanguages" // 用于跟踪服务是否正在运行 private val isRunning = AtomicBoolean(false) @@ -130,7 +131,10 @@ class BleMediaService : Service(), CoroutineScope { Log.d(TAG, "当前配置参数: $config") // 检查必要的配置是否存在 - if (config[KEY_AZURE_SPEECH_KEY].isNullOrEmpty() || config[KEY_OPENAI_API_KEY].isNullOrEmpty()) { + val azureSpeechKey = config[KEY_AZURE_SPEECH_KEY]?.toString() ?: "" + val openaiApiKey = config[KEY_OPENAI_API_KEY]?.toString() ?: "" + + if (azureSpeechKey.isEmpty() || openaiApiKey.isEmpty()) { Log.w(TAG, "语音代理初始化失败: API密钥未配置") return } @@ -159,8 +163,8 @@ class BleMediaService : Service(), CoroutineScope { /** * 从Intent中提取配置参数 */ - private fun extractConfigFromIntent(intent: Intent?): Map { - val config = mutableMapOf() + private fun extractConfigFromIntent(intent: Intent?): Map { + val config = mutableMapOf() intent?.let { // 提取可能存在的配置参数 it.getStringExtra(KEY_AZURE_SPEECH_KEY)?.let { value -> config[KEY_AZURE_SPEECH_KEY] = value } @@ -175,6 +179,13 @@ class BleMediaService : Service(), CoroutineScope { it.getStringExtra(KEY_VOLCANO_TOKEN)?.let { value -> config[KEY_VOLCANO_TOKEN] = value } it.getStringExtra(KEY_SERVER_URL)?.let { value -> config[KEY_SERVER_URL] = value } it.getStringExtra(KEY_USER_TOKEN)?.let { value -> config[KEY_USER_TOKEN] = value } + + // 提取 supportedLanguages 参数 + it.getStringArrayListExtra(KEY_SUPPORTED_LANGUAGES)?.let { languages -> + if (languages.isNotEmpty()) { + config[KEY_SUPPORTED_LANGUAGES] = languages + } + } } Log.i(TAG, "从Intent中提取到配置参数: $config") return config @@ -183,11 +194,25 @@ class BleMediaService : Service(), CoroutineScope { /** * 将配置参数保存到SharedPreferences */ - private fun saveConfigToPreferences(config: Map, prefs: SharedPreferences) { + private fun saveConfigToPreferences(config: Map, prefs: SharedPreferences) { prefs.edit().apply { config.forEach { (key, value) -> - if (value.isNotEmpty()) { - putString(key, value) + when (value) { + is String -> { + if (value.isNotEmpty()) { + putString(key, value) + } + } + is List<*> -> { + // 处理 supportedLanguages 列表 + if (key == KEY_SUPPORTED_LANGUAGES) { + val languageList = value.filterIsInstance() + if (languageList.isNotEmpty()) { + // 将语言列表转换为逗号分隔的字符串保存 + putString(key, languageList.joinToString(",")) + } + } + } } } apply() @@ -197,21 +222,34 @@ class BleMediaService : Service(), CoroutineScope { /** * 从SharedPreferences获取配置 */ - private fun getConfigFromPreferences(prefs: SharedPreferences): Map { - return mapOf( - KEY_AZURE_SPEECH_KEY to getConfigString(prefs, KEY_AZURE_SPEECH_KEY, ""), - KEY_AZURE_SPEECH_REGION to getConfigString(prefs, KEY_AZURE_SPEECH_REGION, "eastasia"), - KEY_OPENAI_API_KEY to getConfigString(prefs, KEY_OPENAI_API_KEY, ""), - KEY_OPENAI_BASE_URL to getConfigString(prefs, KEY_OPENAI_BASE_URL, "https://api.openai.com/v1"), - KEY_OPENAI_MODEL to getConfigString(prefs, KEY_OPENAI_MODEL, "gpt-3.5-turbo"), - KEY_OPENAI_VISION_MODEL to getConfigString(prefs, KEY_OPENAI_VISION_MODEL, "gpt-4-vision-preview"), - KEY_SYSTEM_PROMPT to getConfigString(prefs, KEY_SYSTEM_PROMPT, "gpt-3.5-turbo"), - KEY_MCP_SERVER to getConfigString(prefs, KEY_MCP_SERVER, ""), - KEY_VOLCANO_APP_ID to getConfigString(prefs, KEY_VOLCANO_APP_ID, ""), - KEY_VOLCANO_TOKEN to getConfigString(prefs, KEY_VOLCANO_TOKEN, ""), - KEY_SERVER_URL to getConfigString(prefs, KEY_SERVER_URL, ""), - KEY_USER_TOKEN to getConfigString(prefs, KEY_USER_TOKEN, "") - ) + private fun getConfigFromPreferences(prefs: SharedPreferences): Map { + val config = mutableMapOf() + + // 添加字符串类型的配置参数 + config[KEY_AZURE_SPEECH_KEY] = getConfigString(prefs, KEY_AZURE_SPEECH_KEY, "") + config[KEY_AZURE_SPEECH_REGION] = getConfigString(prefs, KEY_AZURE_SPEECH_REGION, "eastasia") + config[KEY_OPENAI_API_KEY] = getConfigString(prefs, KEY_OPENAI_API_KEY, "") + config[KEY_OPENAI_BASE_URL] = getConfigString(prefs, KEY_OPENAI_BASE_URL, "https://api.openai.com/v1") + config[KEY_OPENAI_MODEL] = getConfigString(prefs, KEY_OPENAI_MODEL, "gpt-3.5-turbo") + config[KEY_OPENAI_VISION_MODEL] = getConfigString(prefs, KEY_OPENAI_VISION_MODEL, "gpt-4-vision-preview") + config[KEY_SYSTEM_PROMPT] = getConfigString(prefs, KEY_SYSTEM_PROMPT, "gpt-3.5-turbo") + config[KEY_MCP_SERVER] = getConfigString(prefs, KEY_MCP_SERVER, "") + config[KEY_VOLCANO_APP_ID] = getConfigString(prefs, KEY_VOLCANO_APP_ID, "") + config[KEY_VOLCANO_TOKEN] = getConfigString(prefs, KEY_VOLCANO_TOKEN, "") + config[KEY_SERVER_URL] = getConfigString(prefs, KEY_SERVER_URL, "") + config[KEY_USER_TOKEN] = getConfigString(prefs, KEY_USER_TOKEN, "") + + // 添加 supportedLanguages 参数处理 + val supportedLanguagesStr = getConfigString(prefs, KEY_SUPPORTED_LANGUAGES, "") + if (supportedLanguagesStr.isNotEmpty()) { + // 将逗号分隔的字符串转换回语言列表 + val languageList = supportedLanguagesStr.split(",").map { it.trim() }.filter { it.isNotEmpty() } + if (languageList.isNotEmpty()) { + config[KEY_SUPPORTED_LANGUAGES] = languageList + } + } + + return config } /** diff --git a/local_plugins/agent_service/lib/agent_service.dart b/local_plugins/agent_service/lib/agent_service.dart index ede6b56dc..5871bd8fe 100644 --- a/local_plugins/agent_service/lib/agent_service.dart +++ b/local_plugins/agent_service/lib/agent_service.dart @@ -332,20 +332,7 @@ class AgentService { } } - /// 设置支持的语音识别语言 - /// - /// [languages] 支持的语言列表,如 ['zh-CN', 'en-US'] - /// 返回是否设置成功 - static Future setSupportedLanguages(List languages) async { - try { - final bool result = await _channel.invokeMethod('setSupportedLanguages', { - 'languages': languages, - }); - return result; - } on PlatformException catch (e) { - throw AgentServiceException(e.code, e.message ?? '设置支持语言失败', e.details); - } - } + /// 停止语音合成 static Future stopAiSteam() async {