You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
8.0 KiB

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
}
}