import Flutter import UIKit import AVFoundation @main @objc class AppDelegate: FlutterAppDelegate { private var classicBluetoothHelper: ClassicBluetoothHelper? private var mediaButtonHelper: Any? // 添加Azure语音服务辅助类 private var azureAsrHelper: Any? private var azureTtsHelper: Any? // 添加火山AI服务 private var volcanoAIService: VolcanoAIService? // 语音交互服务 private var voiceInteractionService: VoiceInteractionService? private var audioSessionManager: AudioSessionManager? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 获取flutter控制器 guard let controller = window?.rootViewController as? FlutterViewController else { NSLog("AppDelegate: Flutter控制器不可用") return false } // 初始化音频会话管理器 audioSessionManager = AudioSessionManager.shared // 配置音频会话支持画中画 configureAudioSessionForPictureInPicture() // 统一注册所有方法通道 registerMethodChannel() GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func registerMethodChannel() { let controller = window?.rootViewController as? FlutterViewController guard let controller = controller else { NSLog("AppDelegate: FlutterViewController 不可用") return } // 注册经典蓝牙方法通道 registerClassicBluetoothChannels(controller: controller) // 仅在iOS 13.0及以上版本注册媒体按钮通道和Azure语音服务通道 if #available(iOS 13.0, *) { // 注册媒体按钮方法通道 registerMediaButtonChannels(controller: controller) // 注册Azure ASR方法通道 registerAzureAsrChannels(controller: controller) // 注册Azure TTS方法通道 registerAzureTtsChannels(controller: controller) // 注册火山AI服务方法通道 registerVolcanoAIServiceChannels(controller: controller) // 注册语音交互服务方法通道 registerVoiceInteractionChannels(controller: controller) } } // MARK: - 经典蓝牙通道 private func registerClassicBluetoothChannels(controller: FlutterViewController) { // 初始化蓝牙辅助类 if classicBluetoothHelper == nil { classicBluetoothHelper = ClassicBluetoothHelper() } guard let classicBluetoothHelper = self.classicBluetoothHelper else { NSLog("AppDelegate: 经典蓝牙辅助实例不可用") return } // 注册经典蓝牙方法通道 let classicBluetoothChannel = FlutterMethodChannel( name: "com.deep_voice.classic_bluetooth", binaryMessenger: controller.binaryMessenger ) classicBluetoothChannel.setMethodCallHandler { [weak self, weak classicBluetoothHelper] (call, result) in guard let _ = self, let classicBluetoothHelper = classicBluetoothHelper else { result(FlutterError(code: "UNAVAILABLE", message: "经典蓝牙辅助实例不可用", details: nil)) return } switch call.method { case "isBluetoothEnabled": result(classicBluetoothHelper.isBluetoothEnabled()) case "getConnectedHeadsetDevices": // 获取已连接的耳机设备 classicBluetoothHelper.getConnectedHeadsetDevices { devices, error in if let error = error { result(FlutterError(code: "GET_DEVICES_FAILED", message: error, details: nil)) } else { result(devices) } } case "startBluetoothDeviceMonitoring": // 启动蓝牙设备监控 classicBluetoothHelper.startBluetoothDeviceMonitoring() result(true) default: result(FlutterMethodNotImplemented) } } // 注册蓝牙流通道 let classicBluetoothStreamChannel = FlutterEventChannel( name: "com.deep_voice.classic_bluetooth_events", binaryMessenger: controller.binaryMessenger ) // 创建蓝牙流处理器(作为局部变量) let bluetoothStreamHandler = BluetoothStreamHandler(bluetoothHelper: classicBluetoothHelper) classicBluetoothStreamChannel.setStreamHandler(bluetoothStreamHandler) } // MARK: - 消息通道设置 // MARK: - 蓝牙媒体按键通道 @available(iOS 13.0, *) private func registerMediaButtonChannels(controller: FlutterViewController) { // 初始化媒体按钮辅助类 if mediaButtonHelper == nil { mediaButtonHelper = BluetoothMediaButtonHelper() } // guard let mediaButtonHelper = self.mediaButtonHelper as? BluetoothMediaButtonHelper else { // NSLog("AppDelegate: 媒体按钮辅助实例不可用") // return // } // mediaButtonHelper.startButtonListening() // 注册媒体按钮方法通道 let mediaButtonChannel = FlutterMethodChannel( name: "com.deep_voice.bluetooth_media_button", binaryMessenger: controller.binaryMessenger ) mediaButtonChannel.setMethodCallHandler { [weak self] (call, result) in guard let _ = self, let mediaButtonHelper = self?.mediaButtonHelper as? BluetoothMediaButtonHelper else { result(FlutterError(code: "UNAVAILABLE", message: "媒体按钮辅助实例不可用", details: nil)) return } switch call.method { case "startButtonListening": let success = mediaButtonHelper.startButtonListening() result(success) case "stopButtonListening": let success = mediaButtonHelper.stopButtonListening() result(success) default: result(FlutterMethodNotImplemented) } } // 注册媒体按钮流通道 let mediaButtonStreamChannel = FlutterEventChannel( name: "com.deep_voice.bluetooth_media_button_events", binaryMessenger: controller.binaryMessenger ) // 创建媒体按钮流处理器 let mediaButtonStreamHandler = MediaButtonStreamHandler(mediaButtonHelper: mediaButtonHelper as! BluetoothMediaButtonHelper) mediaButtonStreamChannel.setStreamHandler(mediaButtonStreamHandler) } // 注册Azure ASR通道 @available(iOS 13.0, *) private func registerAzureAsrChannels(controller: FlutterViewController) { // 注册Azure ASR方法通道 let azureAsrChannel = FlutterMethodChannel( name: "com.deep_voice.azure_asr", binaryMessenger: controller.binaryMessenger ) // 初始化Azure ASR辅助类 azureAsrHelper = AzureAsrHelper { [weak self] eventName, eventData in // 推送事件到Flutter self?.sendAsrEvent(eventName: eventName, eventData: eventData) } // 设置ASR方法处理器 azureAsrChannel.setMethodCallHandler { [weak self] (call, result) in guard let self = self, let asrHelper = self.azureAsrHelper as? AzureAsrHelper else { result(FlutterError(code: "UNAVAILABLE", message: "Azure ASR辅助实例不可用", details: nil)) return } switch call.method { case "initialize": guard let args = call.arguments as? [String: Any], let key = args["subscriptionKey"] as? String, let region = args["region"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "初始化参数无效", details: nil)) return } let languages = args["supportedLanguages"] as? [String] let success = asrHelper.initialize(speechSubscriptionKey: key, serviceRegion: region, supportedLanguages: languages) result(success) case "recognizeOnce": let success = asrHelper.recognizeOnce() result(success) case "startContinuousRecognition": let success = asrHelper.startContinuousRecognition() result(success) case "stopContinuousRecognition": let success = asrHelper.stopContinuousRecognition() result(success) case "isContinuousRecognitionActive": let isActive = asrHelper.isContinuousRecognitionActive() result(isActive) case "dispose": asrHelper.dispose() result(true) default: result(FlutterMethodNotImplemented) } } // 注册Azure ASR流通道 let azureAsrStreamChannel = FlutterEventChannel( name: "com.deep_voice.azure_asr_events", binaryMessenger: controller.binaryMessenger ) // 创建ASR流处理器 let asrStreamHandler = AsrStreamHandler() azureAsrStreamChannel.setStreamHandler(asrStreamHandler) } // 注册Azure TTS通道 @available(iOS 13.0, *) private func registerAzureTtsChannels(controller: FlutterViewController) { // 注册Azure TTS方法通道 let azureTtsChannel = FlutterMethodChannel( name: "com.deep_voice.azure_tts", binaryMessenger: controller.binaryMessenger ) // 初始化Azure TTS辅助类 azureTtsHelper = AzureTtsHelper { [weak self] eventName, eventData in // 推送事件到Flutter self?.sendTtsEvent(eventName: eventName, eventData: eventData) } // 设置TTS方法处理器 azureTtsChannel.setMethodCallHandler { [weak self] (call, result) in guard let self = self, let ttsHelper = self.azureTtsHelper as? AzureTtsHelper else { result(FlutterError(code: "UNAVAILABLE", message: "Azure TTS辅助实例不可用", details: nil)) return } switch call.method { case "initialize": guard let args = call.arguments as? [String: Any], let key = args["subscriptionKey"] as? String, let region = args["region"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "初始化参数无效", details: nil)) return } let language = args["language"] as? String ?? "zh-CN" let success = ttsHelper.initialize(speechSubscriptionKey: key, serviceRegion: region, language: language) result(success) case "setVoice": guard let args = call.arguments as? [String: Any], let voiceName = args["voiceName"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "语音名称参数无效", details: nil)) return } let success = ttsHelper.setVoice(voiceName: voiceName) result(success) case "setSpeechParams": guard let args = call.arguments as? [String: Any] else { result(FlutterError(code: "INVALID_ARGS", message: "语音参数无效", details: nil)) return } let rate = args["rate"] as? Int ?? 0 let pitch = args["pitch"] as? Int ?? 0 let volume = args["volume"] as? Int ?? 100 let success = ttsHelper.setSpeechParams(rate: rate, pitch: pitch, volume: volume) result(success) case "speakText": guard let args = call.arguments as? [String: Any], let text = args["text"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "文本参数无效", details: nil)) return } let success = ttsHelper.speakText(text: text) result(success) case "stopSpeaking": let success = ttsHelper.stopSpeaking() result(success) case "isSpeaking": let isSpeaking = ttsHelper.isSpeaking() result(isSpeaking) case "dispose": ttsHelper.dispose() result(true) default: result(FlutterMethodNotImplemented) } } // 注册Azure TTS流通道 let azureTtsStreamChannel = FlutterEventChannel( name: "com.deep_voice.azure_tts_events", binaryMessenger: controller.binaryMessenger ) // 创建TTS流处理器 let ttsStreamHandler = TtsStreamHandler() azureTtsStreamChannel.setStreamHandler(ttsStreamHandler) } // 注册火山AI服务方法通道 @available(iOS 13.0, *) private func registerVolcanoAIServiceChannels(controller: FlutterViewController) { guard let volcanoAIService = volcanoAIService else { return } // 注册火山AI方法通道 let volcanoAIChannel = FlutterMethodChannel( name: "com.deep_voice.volcano_ai", binaryMessenger: controller.binaryMessenger ) volcanoAIChannel.setMethodCallHandler { [weak self, weak volcanoAIService] (call, result) in guard let _ = self, let volcanoAIService = volcanoAIService else { result(FlutterError(code: "UNAVAILABLE", message: "火山AI服务实例不可用", details: nil)) return } switch call.method { case "initialize": let apiKey = call.arguments as? String ?? "" let success = volcanoAIService.initialize(apiKey: apiKey) result(success) case "sendMessage": guard let arguments = call.arguments as? [String: Any], let message = arguments["message"] as? String, let systemPrompt = arguments["systemPrompt"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "参数无效", details: nil)) return } if message.isEmpty { result(FlutterError(code: "EMPTY_MESSAGE", message: "消息不能为空", details: nil)) return } // 异步发送消息 Task { do { // 创建用户消息 let userMessage = volcanoAIService.createUserMessage(content: message) // 发送消息并等待响应 let response = try await volcanoAIService.sendMessage( messages: [userMessage], systemPrompt: systemPrompt ) // 返回响应 DispatchQueue.main.async { result(response) } } catch { // 处理错误 DispatchQueue.main.async { result(FlutterError( code: "AI_ERROR", message: "AI请求失败: \(error.localizedDescription)", details: nil )) } } } default: result(FlutterMethodNotImplemented) } } // 注册火山AI流通道 let volcanoAIStreamChannel = FlutterEventChannel( name: "com.deep_voice.volcano_ai_stream", binaryMessenger: controller.binaryMessenger ) // 创建火山AI流处理器(作为局部变量) let volcanoAIStreamHandler = VolcanoAIStreamHandler(volcanoAIService: volcanoAIService) volcanoAIStreamChannel.setStreamHandler(volcanoAIStreamHandler) } // 注册语音交互服务方法通道 @available(iOS 13.0, *) private func registerVoiceInteractionChannels(controller: FlutterViewController) { // 初始化语音交互服务 voiceInteractionService = VoiceInteractionService.shared // 注册语音交互服务方法通道 let voiceInteractionChannel = FlutterMethodChannel( name: "com.deep_voice.voice_interaction", binaryMessenger: controller.binaryMessenger ) voiceInteractionChannel.setMethodCallHandler { [weak self, weak voiceInteractionService] (call, result) in guard let _ = self, let voiceInteractionService = voiceInteractionService else { result(FlutterError(code: "UNAVAILABLE", message: "语音交互服务实例不可用", details: nil)) return } switch call.method { case "startService": guard let args = call.arguments as? [String: Any], let azureKey = args["azure_speech_key"] as? String, let azureRegion = args["azure_speech_region"] as? String, let volcanoKey = args["volcano_ai_api_key"] as? String else { result(FlutterError(code: "INVALID_ARGS", message: "启动服务参数无效", details: nil)) return } let success = voiceInteractionService.start(azureKey: azureKey, azureRegion: azureRegion, volcanoKey: volcanoKey) result(success) case "stopService": voiceInteractionService.stop() result(true) case "isServiceRunning": let isRunning = voiceInteractionService.isServiceRunning() result(isRunning) case "pauseVoiceInteraction": voiceInteractionService.pauseVoiceInteraction() result(true) default: result(FlutterMethodNotImplemented) } } // 注册语音交互流通道 let voiceInteractionStreamChannel = FlutterEventChannel( name: "com.deep_voice.voice_interaction_events", binaryMessenger: controller.binaryMessenger ) // 创建语音交互流处理器(作为局部变量) let voiceInteractionStreamHandler = VoiceInteractionStreamHandler(voiceInteractionService: voiceInteractionService!) voiceInteractionStreamChannel.setStreamHandler(voiceInteractionStreamHandler) } // 存储ASR事件 private var _cachedAsrEvent: [String: Any]? // 发送ASR事件 @available(iOS 13.0, *) private func sendAsrEvent(eventName: String, eventData: [String: Any]) { // 调整格式:将event改为type,并将data的内容提升到顶层 var eventMap = eventData eventMap["type"] = eventName _cachedAsrEvent = eventMap NotificationCenter.default.post( name: Notification.Name("AzureAsrEvent"), object: nil, userInfo: eventMap ) } // 存储TTS事件 private var _cachedTtsEvent: [String: Any]? // 发送TTS事件 @available(iOS 13.0, *) private func sendTtsEvent(eventName: String, eventData: [String: Any]) { // 调整格式:将event改为type,并将data的内容提升到顶层 var eventMap = eventData eventMap["type"] = eventName _cachedTtsEvent = eventMap NotificationCenter.default.post( name: Notification.Name("AzureTtsEvent"), object: nil, userInfo: eventMap ) } // 配置音频会话支持画中画 private func configureAudioSessionForPictureInPicture() { do { let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(.playback, mode: .default, options: [.allowBluetooth, .allowBluetoothA2DP, .mixWithOthers]) try audioSession.setActive(true) } catch { NSLog("AppDelegate: 配置音频会话失败: %@", error.localizedDescription) } } } // 蓝牙事件流处理器 class BluetoothStreamHandler: NSObject, FlutterStreamHandler, BluetoothEventHandler { private let bluetoothHelper: ClassicBluetoothHelper private var eventSink: FlutterEventSink? init(bluetoothHelper: ClassicBluetoothHelper) { self.bluetoothHelper = bluetoothHelper super.init() // 设置事件处理器 bluetoothHelper.setEventHandler(self) } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { // NSLog("BluetoothStreamHandler: 开始监听蓝牙事件") self.eventSink = events return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { // NSLog("BluetoothStreamHandler: 取消监听蓝牙事件") eventSink = nil return nil } // 实现BluetoothEventHandler协议 func sendEvent(_ event: [String: Any]) { NSLog("BluetoothStreamHandler: 接收到蓝牙事件: \(event)") DispatchQueue.main.async { [weak self] in self?.eventSink?(event) } } } // 媒体按钮事件流处理器 @available(iOS 13.0, *) class MediaButtonStreamHandler: NSObject, FlutterStreamHandler, MediaButtonEventHandler { private let mediaButtonHelper: BluetoothMediaButtonHelper private var eventSink: FlutterEventSink? init(mediaButtonHelper: BluetoothMediaButtonHelper) { self.mediaButtonHelper = mediaButtonHelper super.init() // 设置事件处理器 mediaButtonHelper.setEventHandler(self) } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { NSLog("MediaButtonStreamHandler: 开始监听媒体按钮事件") self.eventSink = events return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { NSLog("MediaButtonStreamHandler: 取消监听媒体按钮事件") eventSink = nil return nil } // 实现MediaButtonEventHandler协议 func sendEvent(_ event: [String: Any]) { NSLog("MediaButtonStreamHandler: 收到按钮事件 \(event)") DispatchQueue.main.async { [weak self] in self?.eventSink?(event) } } } // ASR事件流处理器 @available(iOS 13.0, *) class AsrStreamHandler: NSObject, FlutterStreamHandler { private var eventSink: FlutterEventSink? private var notificationObserver: Any? deinit { if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) } } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = events // 注册通知观察者 notificationObserver = NotificationCenter.default.addObserver( forName: Notification.Name("AzureAsrEvent"), object: nil, queue: .main) { [weak self] notification in if let userInfo = notification.userInfo as? [String: Any], let eventSink = self?.eventSink { // 确保在主线程上发送事件 DispatchQueue.main.async { eventSink(userInfo) } } } return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { eventSink = nil // 移除通知观察者 if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) notificationObserver = nil } return nil } } // TTS事件流处理器 @available(iOS 13.0, *) class TtsStreamHandler: NSObject, FlutterStreamHandler { private var eventSink: FlutterEventSink? private var notificationObserver: Any? deinit { if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) } } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = events // 注册通知观察者 notificationObserver = NotificationCenter.default.addObserver( forName: Notification.Name("AzureTtsEvent"), object: nil, queue: .main) { [weak self] notification in if let userInfo = notification.userInfo as? [String: Any], let eventSink = self?.eventSink { // 确保在主线程上发送事件 DispatchQueue.main.async { eventSink(userInfo) } } } return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { eventSink = nil // 移除通知观察者 if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) notificationObserver = nil } return nil } } // 火山AI事件流处理器 @available(iOS 13.0, *) class VolcanoAIStreamHandler: NSObject, FlutterStreamHandler { private let volcanoAIService: VolcanoAIService private var eventSink: FlutterEventSink? init(volcanoAIService: VolcanoAIService) { self.volcanoAIService = volcanoAIService super.init() } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = events return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { eventSink = nil return nil } // 处理来自Flutter的流式请求 func handleStreamRequest(messages: [[String: Any]], systemPrompt: String) { volcanoAIService.sendMessageStream(messages: messages, systemPrompt: systemPrompt, streamCallback: VolcanoAIService.StreamCallback( onToken: { [weak self] token in guard let self = self, let eventSink = self.eventSink else { return } let event: [String: Any] = [ "type": "token", "token": token ] DispatchQueue.main.async { eventSink(event) } }, onComplete: { [weak self] in guard let self = self, let eventSink = self.eventSink else { return } let event: [String: Any] = [ "type": "complete" ] DispatchQueue.main.async { eventSink(event) } }, onError: { [weak self] error in guard let self = self, let eventSink = self.eventSink else { return } let event: [String: Any] = [ "type": "error", "error": error.localizedDescription ] DispatchQueue.main.async { eventSink(event) } } )) } } // 语音交互事件处理器协议 @available(iOS 13.0, *) protocol VoiceInteractionEventHandler: AnyObject { func sendEvent(_ event: [String: Any]) } // 语音交互流处理器 @available(iOS 13.0, *) class VoiceInteractionStreamHandler: NSObject, FlutterStreamHandler, VoiceInteractionEventHandler { private let voiceInteractionService: VoiceInteractionService private var eventSink: FlutterEventSink? init(voiceInteractionService: VoiceInteractionService) { self.voiceInteractionService = voiceInteractionService super.init() // 设置事件处理器 voiceInteractionService.setEventHandler(self) } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { NSLog("VoiceInteractionStreamHandler: 开始监听语音交互事件") self.eventSink = events return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { NSLog("VoiceInteractionStreamHandler: 取消监听语音交互事件") eventSink = nil return nil } // 实现VoiceInteractionEventHandler协议 func sendEvent(_ event: [String: Any]) { NSLog("VoiceInteractionStreamHandler: 收到事件 \(event)") DispatchQueue.main.async { [weak self] in self?.eventSink?(event) } } }