import Foundation import CoreBluetooth import AVFoundation import UIKit /// 蓝牙事件处理协议 @objc protocol BluetoothEventHandler: AnyObject { func sendEvent(_ event: [String: Any]) } @objc class ClassicBluetoothHelper: NSObject { // MARK: - 属性 // 音频会话管理器 private let audioSessionManager = AudioSessionManager.shared // 事件处理器 private weak var eventHandler: BluetoothEventHandler? // MARK: - 初始化与设置 override init() { super.init() } // 设置事件处理器 @objc func setEventHandler(_ handler: BluetoothEventHandler) { eventHandler = handler } // MARK: - 设备监控 // 获取蓝牙状态字符串 private func getBluetoothStateString(state: CBManagerState) -> String { switch state { case .poweredOn: return "on" case .poweredOff: return "off" default: return "unknown" } } // 发送蓝牙状态事件 private func sendBluetoothStateEvent(state: String) { let event: [String: Any] = [ "type": "bluetoothStateChanged", "state": state, "timestamp": Int(Date().timeIntervalSince1970 * 1000) ] eventHandler?.sendEvent(event) } // 启动蓝牙设备监控 @objc func startBluetoothDeviceMonitoring() { NotificationCenter.default.removeObserver(self) audioSessionManager.addRouteChangeListener(self, selector: #selector(handleRouteChange(_:))) BluetoothMediaButtonHelper.shared.startButtonListening() } // 处理音频路由变化 @objc private func handleRouteChange(_ notification: Notification) { guard let userInfo = notification.userInfo, let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else { return } // 获取当前设备 let currentDevices = getConnectedAudioDevices() // 检查原因 switch reason { case .newDeviceAvailable: // 新设备已连接 for device in currentDevices { // 发送设备连接事件 NSLog("发送设备连接事件 - 设备: \(device["name"] ?? "未知设备") [\(device["address"] ?? "未知地址")]") sendDeviceConnectedEvent(device: device) } case .oldDeviceUnavailable: // 获取断开之前的路由 if let previousRoute = userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription { // 过滤蓝牙相关设备 for output in previousRoute.outputs where isBluetoothOutput(output.portType) { let device: [String: String] = [ "name": output.portName, "address": cleanDeviceAddress(output.uid) ] // 发送设备断开事件 sendDeviceDisconnectedEvent(device: device) } } default: break } } // 检查是否为蓝牙输出 private func isBluetoothOutput(_ portType: AVAudioSession.Port) -> Bool { return portType == .bluetoothA2DP || portType == .bluetoothHFP || portType == .bluetoothLE } // MARK: - 设备事件 // 发送设备已连接事件 private func sendDeviceConnectedEvent(device: [String: String]) { let event: [String: Any] = [ "type": "deviceConnected", "device": device, "timestamp": Int(Date().timeIntervalSince1970 * 1000) ] eventHandler?.sendEvent(event) } // 发送设备已断开事件 private func sendDeviceDisconnectedEvent(device: [String: String]) { let event: [String: Any] = [ "type": "deviceDisconnected", "device": device, "timestamp": Int(Date().timeIntervalSince1970 * 1000) ] eventHandler?.sendEvent(event) } // MARK: - 公共API // 获取当前连接的耳机设备 @objc func getConnectedHeadsetDevices(_ completion: @escaping ([[String: String]]?, String?) -> Void) { do { // 获取设备 let devices = getConnectedAudioDevices() completion(devices, nil) } catch { completion(nil, "获取设备失败: \(error.localizedDescription)") } } // 获取当前连接的音频设备 private func getConnectedAudioDevices() -> [[String: String]] { var result: [[String: String]] = [] // 获取当前音频路由 let outputs = audioSessionManager.getCurrentRoute().outputs // 过滤蓝牙相关设备 for output in outputs where isBluetoothOutput(output.portType) { let device: [String: String] = [ "name": output.portName, "address": cleanDeviceAddress(output.uid) // 处理设备地址,移除后缀 ] result.append(device) } return result } // 检查蓝牙是否启用 @objc func isBluetoothEnabled() -> Bool { return audioSessionManager.isBluetoothEnabled() } // 清理设备地址,移除后缀 private func cleanDeviceAddress(_ address: String) -> String { // 检查是否包含常见分隔符 if let range = address.range(of: "-") ?? address.range(of: ":") ?? address.range(of: "_") { // 只保留分隔符之前的部分 return String(address[..