From fe2c3c52431a8d4016e12a8beccb5bd28cadfdfd Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sun, 24 Aug 2025 12:38:21 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift index 398c0eadb..bf79cb7cb 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift @@ -561,7 +561,7 @@ private func convertAudioBuffer(_ buffer: AVAudioPCMBuffer, to targetFormat: AVA * @throws 音频会话配置失败时抛出错误 */ private func setupAudioSession() throws { - try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth]) + try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth,.mixWithOthers]) try audioSession.setActive(true) // // 设置首选的音频参数 - 修改为16000Hz以匹配Azure Speech要求 From 0527554eb94935a6a53f91311175e53e65e886e5 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sun, 24 Aug 2025 12:57:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat_api/QQMusicSystemFunctionHandler.swift | 10 +++++----- .../qq_music/Sources/qq_music/QPlayAutoManager.swift | 3 --- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift index 41021c005..c8c3144aa 100644 --- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift @@ -205,7 +205,7 @@ private class QQMusicSearchHandler: FunctionHandler { private class QQMusicPauseHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { QPlayAutoManager.shared.pause() - let result: [String: Any] = ["success": true, "message": "Music paused"] + let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music paused"] let jsonData = try JSONSerialization.data(withJSONObject: result) return String(data: jsonData, encoding: .utf8) ?? "{}" } @@ -214,7 +214,7 @@ private class QQMusicPauseHandler: FunctionHandler { private class QQMusicResumeHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { QPlayAutoManager.shared.play() - let result: [String: Any] = ["success": true, "message": "Music resumed"] + let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music resumed"] let jsonData = try JSONSerialization.data(withJSONObject: result) return String(data: jsonData, encoding: .utf8) ?? "{}" } @@ -223,7 +223,7 @@ private class QQMusicResumeHandler: FunctionHandler { private class QQMusicStopHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { QPlayAutoManager.shared.stop() - let result: [String: Any] = ["success": true, "message": "Music stopped"] + let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music stopped"] let jsonData = try JSONSerialization.data(withJSONObject: result) return String(data: jsonData, encoding: .utf8) ?? "{}" } @@ -232,7 +232,7 @@ private class QQMusicStopHandler: FunctionHandler { private class QQMusicNextHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { QPlayAutoManager.shared.next() - let result: [String: Any] = ["success": true, "message": "Skipped to next song"] + let result: [String: Any] = ["success": true, "broadcast": false, "message": "Skipped to next song"] let jsonData = try JSONSerialization.data(withJSONObject: result) return String(data: jsonData, encoding: .utf8) ?? "{}" } @@ -241,7 +241,7 @@ private class QQMusicNextHandler: FunctionHandler { private class QQMusicPreviousHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { QPlayAutoManager.shared.previous() - let result: [String: Any] = ["success": true, "message": "Skipped to previous song"] + let result: [String: Any] = ["success": true, "broadcast": false, "message": "Skipped to previous song"] let jsonData = try JSONSerialization.data(withJSONObject: result) return String(data: jsonData, encoding: .utf8) ?? "{}" } diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift index e08fa3bef..081961674 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift @@ -840,9 +840,6 @@ extension QPlayAutoManager: QPlayAutoSDKDelegate { for weakDelegate in delegates { weakDelegate.delegate?.onConnectStateChanged?(newState) } - if newState == QPlayAutoConnectState.disconnect { - connect(forceLogin: false) - } } public func onQPlayAutoPlayStateChanged(_ playState: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) { From 7cd02f35ff59319a3e42e47645b9b6284e7b8acf Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sun, 24 Aug 2025 14:03:30 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9F=B3=E9=87=8F?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent_service/AudioSessionHub.swift | 118 +++++++++--------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift index a742994dd..d008a4a79 100644 --- a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift +++ b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift @@ -541,11 +541,19 @@ public class AudioSessionHub { } private func performVolumeControlWithMPVolumeView(action: VolumeControlAction, value: Float?, completion: @escaping (Bool, String) -> Void) { - // 创建更大的 frame,有助于子视图正确初始化 + // 确保在有音频会话的情况下进行音量控制 + do { + try audioSession.setActive(true) + // 设置为播放类别,这样音量控制才能生效 + try audioSession.setCategory(.playback, mode: .default, options: []) + } catch { + os_log("设置音频会话失败: %{public}@", log: logger, type: .error, error.localizedDescription) + } + let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) volumeView.showsVolumeSlider = true volumeView.showsRouteButton = false - volumeView.alpha = 0.01 // 几乎透明 + volumeView.alpha = 0.01 guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first else { @@ -557,71 +565,63 @@ public class AudioSessionHub { volumeView.setNeedsLayout() volumeView.layoutIfNeeded() - var retryCount = 0 - let maxRetries = 5 - - func attemptVolumeControl() { - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - os_log("尝试第 %d 次音量控制", log: self.logger, type: .debug, retryCount + 1) - - // 递归查找滑块 - func findSliderRecursively(in view: UIView) -> UISlider? { - if let slider = view as? UISlider { - return slider - } - for subview in view.subviews { - if let foundSlider = findSliderRecursively(in: subview) { - return foundSlider - } + // 增加延迟时间,确保滑块完全初始化 + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + func findSliderRecursively(in view: UIView) -> UISlider? { + if let slider = view as? UISlider { + return slider + } + for subview in view.subviews { + if let foundSlider = findSliderRecursively(in: subview) { + return foundSlider } - return nil } + return nil + } + + if let slider = findSliderRecursively(in: volumeView) { + let currentValue = slider.value + let newValue: Float - if let slider = findSliderRecursively(in: volumeView) { - let currentValue = slider.value - let newValue: Float - - switch action { - case .increase: - newValue = min(currentValue + 0.2, 1.0) // 从 0.1 改为 0.2 (20%) - case .decrease: - newValue = max(currentValue - 0.2, 0.0) // 从 0.1 改为 0.2 (20%) - case .mute: - newValue = 0.0 - case .setMax: - newValue = 1.0 - case .setValue(let val): - newValue = max(0.0, min(val, 1.0)) - } - - os_log("设置音量从 %.2f 到 %.2f", log: self.logger, type: .info, currentValue, newValue) - + switch action { + case .increase: + newValue = min(currentValue + 0.1, 1.0) // 改回0.1避免变化过大 + case .decrease: + newValue = max(currentValue - 0.1, 0.0) + case .mute: + newValue = 0.0 + case .setMax: + newValue = 1.0 + case .setValue(let val): + newValue = max(0.0, min(val, 1.0)) + } + + os_log("设置音量从 %.2f 到 %.2f", log: self.logger, type: .info, currentValue, newValue) + + // 模拟用户触摸操作 + slider.setValue(newValue, animated: true) + slider.sendActions(for: .touchDown) + slider.sendActions(for: .valueChanged) + slider.sendActions(for: .touchUpInside) + + // 再次确认设置 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { slider.value = newValue slider.sendActions(for: .valueChanged) - slider.sendActions(for: .touchUpInside) - - let message = self.getVolumeActionMessage(action: action) - completion(true, message) - volumeView.removeFromSuperview() - } else { - retryCount += 1 - if retryCount < maxRetries { - os_log("音量控制重试 %d/%d", log: self.logger, type: .debug, retryCount, maxRetries) - attemptVolumeControl() - } else { - os_log("所有重试都失败,使用备选方案", log: self.logger, type: .error) - volumeView.removeFromSuperview() - - // 备选方案:至少记录当前音量状态 - let currentVolume = self.audioSession.outputVolume - let message = "音量控制请求已处理(当前音量: \(Int(currentVolume * 100))%)" - completion(true, message) - } } + + let message = self.getVolumeActionMessage(action: action) + completion(true, message) + volumeView.removeFromSuperview() + } else { + os_log("无法找到音量滑块", log: self.logger, type: .error) + volumeView.removeFromSuperview() + + // 提供用户友好的反馈 + let message = "音量控制需要在播放音频时才能生效,请先播放音频后再调整音量" + completion(false, message) } } - - attemptVolumeControl() } private func getVolumeActionMessage(action: VolumeControlAction) -> String {