import Foundation import CoreBluetooth import os.log // 条件编译只导入在iOS 18+上可用的框架 #if canImport(AccessorySetupKit) && swift(>=5.9) import AccessorySetupKit import UIKit #endif class BleAccessorySetup: NSObject { // 单例实现 static let shared = BleAccessorySetup() // 基本属性 private var bleService: Any? private let logger = OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleAccessorySetup") // iOS 18+ 特定属性和回调 #if canImport(AccessorySetupKit) && swift(>=5.9) @available(iOS 18.0, *) class AccessorySessionWrapper { var session: ASAccessorySession init() { self.session = ASAccessorySession() } } var accessorySessionWrapper: Any? typealias DeviceDiscoveredCallback = (UUID) -> Void private var onDeviceDiscovered: DeviceDiscoveredCallback? #endif private override init() { super.init() } // 设置BLE服务实例 func setBleService(_ service: Any) { self.bleService = service } // 设置设备发现回调 func setDeviceDiscoveredCallback(_ callback: @escaping (UUID) -> Void) { #if canImport(AccessorySetupKit) && swift(>=5.9) if #available(iOS 18.0, *) { self.onDeviceDiscovered = callback } #endif } // 初始化设备发现会话 func initializeDiscoverySession() { #if canImport(AccessorySetupKit) && swift(>=5.9) if #available(iOS 18.0, *) { os_log("初始化iOS 18 AccessorySetupKit会话", log: logger, type: .info) // 创建会话 accessorySessionWrapper = AccessorySessionWrapper() // 激活会话并设置事件处理 if let wrapper = accessorySessionWrapper as? AccessorySessionWrapper { wrapper.session.activate(on: .main) { [weak self] event in guard let self = self else { return } switch event.eventType { case .activated: os_log("AccessorySetupKit会话已激活", log: self.logger, type: .info) case .accessoryAdded: if let accessory = event.accessory, let uuid = accessory.bluetoothIdentifier { os_log("发现新设备: %{public}@", log: self.logger, type: .info, accessory.displayName) self.onDeviceDiscovered?(uuid) } case .accessoryRemoved: if let accessory = event.accessory { os_log("设备已移除: %{public}@", log: self.logger, type: .info, accessory.displayName) } // 根据WWDC24视频,正确的事件类型为accessoryChanged case .accessoryChanged: if let accessory = event.accessory { os_log("设备已更新: %{public}@", log: self.logger, type: .info, accessory.displayName) } // 根据WWDC24视频,失败事件类型已变更 case .pickerSetupFailed: if let error = event.error { os_log("会话出错: %{public}@", log: self.logger, type: .error, error.localizedDescription) } default: os_log("收到其他会话事件: %{public}d", log: self.logger, type: .debug, event.eventType.rawValue) } } // 检查现有授权设备 if !wrapper.session.accessories.isEmpty { os_log("发现%{public}d个已授权设备", log: logger, type: .info, wrapper.session.accessories.count) // 如果有现有设备,触发回调 for accessory in wrapper.session.accessories { if let uuid = accessory.bluetoothIdentifier { os_log("处理已授权设备: %{public}@", log: logger, type: .info, accessory.displayName) self.onDeviceDiscovered?(uuid) } } } } } else { os_log("iOS 18 AccessorySetupKit不可用", log: logger, type: .info) } #else os_log("iOS 18 AccessorySetupKit不可用", log: logger, type: .info) #endif } // 显示设备选择器 func showDevicePicker() { #if canImport(AccessorySetupKit) && swift(>=5.9) if #available(iOS 18.0, *) { if let wrapper = accessorySessionWrapper as? AccessorySessionWrapper { os_log("显示iOS 18设备选择器", log: logger, type: .info) // 创建描述符和选择器项,这些API也需要iOS 18 @available(iOS 18.0, *) func createAndShowPicker() { // 根据WWDC24视频,正确的类名是ASDiscoveryDescriptor let descriptor = ASDiscoveryDescriptor() // 设置过滤条件 // 使用ASBluetoothCompanyIdentifier类型 descriptor.bluetoothCompanyIdentifier = ASBluetoothCompanyIdentifier(UInt16(0xABEF)) // BleConst.MANUFACTURER_ID descriptor.bluetoothServiceUUID = CBUUID(string: "0000abc0-0000-1111-2222-123456789abc") // BleConst.PRIMARY_SERVICE_UUID // 创建默认图像以防系统图标不可用 let headphonesImage = UIImage(systemName: "headphones") ?? UIImage() // 根据WWDC24视频,正确的类名是ASPickerDisplayItem let displayItem = ASPickerDisplayItem( name: "语音助理耳机", productImage: headphonesImage, descriptor: descriptor ) // 显示选择器 wrapper.session.showPicker(for: [displayItem]) { error in if let error = error { // 修复OSLog的错误用法 os_log("设备选择器显示错误: %{public}@", log: self.logger, type: .error, error.localizedDescription) } } } // 调用内部函数 createAndShowPicker() } else { os_log("会话未初始化", log: logger, type: .error) } } else { os_log("iOS 18 AccessorySetupKit不可用", log: logger, type: .info) } #else os_log("iOS 18 AccessorySetupKit不可用", log: logger, type: .info) #endif } // 处理发现的设备 func handleDiscoveredAccessory(uuid: UUID) { #if canImport(AccessorySetupKit) && swift(>=5.9) if #available(iOS 18.0, *) { guard let service = bleService as? BleService else { os_log("BLE服务未设置", log: logger, type: .error) return } // 获取中央管理器 let centralManager = service.getCentralManager() // 通过UUID检索外设 let peripherals = centralManager.retrievePeripherals(withIdentifiers: [uuid]) if let peripheral = peripherals.first { os_log("连接到UUID对应的设备: %{public}@", log: logger, type: .info, peripheral.name ?? uuid.uuidString) service.connect(to: peripheral) } else { os_log("未找到UUID对应的设备: %{public}@", log: logger, type: .error, uuid.uuidString) } } #endif } }