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