import Foundation import CoreBluetooth import AVFoundation import UIKit /// 蓝牙事件处理协议 @objc protocol BluetoothEventHandler: AnyObject { func sendEvent(_ event: [String: Any]) } @objc class ClassicBluetoothHelper: NSObject, CBCentralManagerDelegate { // MARK: - 属性 // 音频会话管理器 private let audioSessionManager = AudioSessionManager.shared // 蓝牙管理器 private var centralManager: CBCentralManager? // 事件处理器 private weak var eventHandler: BluetoothEventHandler? // MARK: - 初始化与设置 override init() { super.init() } // 设置事件处理器 @objc func setEventHandler(_ handler: BluetoothEventHandler) { eventHandler = handler } // MARK: - CBCentralManagerDelegate func centralManagerDidUpdateState(_ central: CBCentralManager) { let stateString = getBluetoothStateString(state: central.state) sendBluetoothStateEvent(state: stateString) } // 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 initialize() { if centralManager == nil { centralManager = CBCentralManager(delegate: self, queue: nil) } // 发送当前蓝牙状态 if let manager = centralManager { let stateString = getBluetoothStateString(state: manager.state) sendBluetoothStateEvent(state: stateString) } // 移除之前的监听器 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]) { guard let name = device["name"], let address = device["address"] else { return } let deviceMap: [String: Any] = [ "name": name, "address": address, "type": "headset" ] let event: [String: Any] = [ "type": "deviceConnected", "device": deviceMap, "timestamp": Int(Date().timeIntervalSince1970 * 1000) ] eventHandler?.sendEvent(event) } // 发送设备断开事件 private func sendDeviceDisconnectedEvent(device: [String: String]) { guard let name = device["name"], let address = device["address"] else { return } let deviceMap: [String: Any] = [ "name": name, "address": address, "type": "headset" ] let event: [String: Any] = [ "type": "deviceDisconnected", "device": deviceMap, "timestamp": Int(Date().timeIntervalSince1970 * 1000) ] eventHandler?.sendEvent(event) } // MARK: - 公共API // 获取当前连接的耳机设备 @objc func getConnectedHeadsetDevices(_ completion: @escaping ([[String: String]]?, String?) -> Void) { // 检查蓝牙状态 if centralManager?.state != .poweredOn { completion(nil, "蓝牙未启用") return } 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 dispose() { audioSessionManager.removeRouteChangeListener(self) eventHandler = nil } // 检查蓝牙是否启用 @objc func isBluetoothEnabled() -> Bool { return centralManager?.state == .poweredOn } // 清理设备地址,移除后缀 private func cleanDeviceAddress(_ address: String) -> String { // 检查是否包含常见分隔符 if let range = address.range(of: "-") ?? address.range(of: ":") ?? address.range(of: "_") { // 只保留分隔符之前的部分 return String(address[..