借助 AudioAccessoryKit 为已配对的第三方蓝牙耳机(头戴式或入耳式)提供自动音频切换支持。适用于以下场景:主 App 注册音频配件、App Extension 上报佩戴/摘下状态或已连接源设备变更、以及处理 AccessoryControlDevice 的功能与错误。请勿用于常规 AVAudioSession 路由、蓝牙传输或初始配件配对。
AudioAccessoryKit
为第三方音频配件提供自动音频切换支持及智能音频路由输入。支持主 App 向系统注册音频配件配置,并允许 App Extension 上报佩戴状态和已连接源设备变更,从而协助系统完成音频输出的自动切换。适用于 iOS 26.4+ / iPadOS 26.4+。
Beta 阶段提醒:AudioAccessoryKit 是 iOS 26.4 的新增框架。在依赖特定 API 细节前,请重新查阅 Apple 最新官方文档。
AudioAccessoryKit 基于 AccessorySetupKit 构建。配件必须先通过 AccessorySetupKit 完成配对,然后才能注册使用音频相关功能。核心类型为 AccessoryControlDevice,负责注册来自主 App(container app)的 Configuration,并应用来自 App Extension 的持续配置更新。
目录
快速配置
前置条件
- 使用 AccessorySetupKit 通过蓝牙完成配件配对,获取
ASAccessory对象。 - 在主 App 和 Extension 中根据需要导入相关框架:
import AccessorySetupKit
import AudioAccessoryKit
框架可用性
| 平台 | 最低版本 |
|---|---|
| iOS | 26.4+ |
| iPadOS | 26.4+ |
在当前的 Xcode 26.6 工具链中,AudioAccessoryKit 仅包含在真机设备 SDK 中,暂未引入 iPhone Simulator 26.5 SDK。针对该 Target 请使用真机进行调试。如果 App 的其他模块必须支持模拟器编译,请隔离 Target 成员资格,或者使用 #if canImport(AudioAccessoryKit) 条件编译包裹导入与具体实现,并提供模拟器存根(stub)。
会话管理
注册配件
通过 AccessorySetupKit 完成配对后,在主 App 中传入描述配件支持的功能及初始状态的 AccessoryControlDevice.Configuration 来注册配件:
let accessory: ASAccessory // 通过 AccessorySetupKit 配对获取
let configuration = AccessoryControlDevice.Configuration(
devicePlacement: .offHead,
deviceCapabilities: [.audioSwitching, .placement]
)
try await AccessoryControlDevice.register(accessory, configuration)
注册操作会激活指定的 Capabilities,并为系统提供参与音频路由决策所需的配置信息。
获取当前配置
在 App Extension 中,可以使用静态方法 current(for:) 获取设备的当前配置:
let device = try AccessoryControlDevice.current(for: accessory)
let currentConfig = device.configuration
该方法会返回与已配对 ASAccessory 关联的 AccessoryControlDevice 实例。设备对象暴露了 accessory 引用以及当前的 configuration。注意:Apple 将 current(for:) 标记为仅限 App Extension 使用。
更新配置
在 App Extension 中,使用 update(_:) 将配置变更推送给系统。注意:只能更新注册时已声明的 Capabilities 对应的字段:
let device = try AccessoryControlDevice.current(for: accessory)
var config = device.configuration
config.devicePlacement = .onHead
try await device.update(config)
建议采用门控写入流程(gated write workflow):先确认注册阶段已声明该功能,复制并修改 device.configuration,然后调用 try await update(_:)。该方法无返回值;请仅在调用成功后再更新 App 侧的镜像状态。若调用失败,请按照错误处理中的策略进行处理。Apple 将 update(_:) 标记为仅限 App Extension 使用。
音频切换
自动音频切换可以让系统根据佩戴状态和已连接的设备源,智能地将音频输出路由至最合适的设备。
开启自动音频切换
在上述标准注册流程中声明 .audioSwitching 即可。仅当配件能够持续上报佩戴状态变更时,才需要同时包含 .placement 及初始佩戴状态。
功能集合(Capabilities)
自动切换通常使用以下 AccessoryControlDevice.Capabilities:
| 功能 | 作用 |
|---|---|
.audioSwitching |
设备支持自动音频切换 |
.placement |
设备可以上报其物理佩戴状态 |
可根据需求组合使用这些功能。如果配件无法向系统实时更新真实的佩戴状态,请勿声明 .placement。
设备佩戴状态
在 App Extension 中上报配件的物理佩戴位置,以帮助系统做出路由决策。每当配件检测到佩戴位置发生变化时,即应更新佩戴状态。
佩戴状态枚举值
AccessoryControlDevice.Placement 定义了四种情况:
| 佩戴状态 | 含义 |
|---|---|
.inEar |
配件已戴入耳中(例如入耳式耳机) |
.onHead |
配件已佩戴在头部(例如头戴式耳机) |
.overTheEar |
配件已罩在耳朵上(例如包耳式耳机) |
.offHead |
用户未佩戴配件 |
更新佩戴状态
config.devicePlacement = .inEar
请在上述标准的 current→copy→update 流程中应用此修改。
常见状态转换场景:
- 用户戴上配件时:从
.offHead转换为.onHead或.inEar - 摘下配件时:从
.onHead或.inEar转换为.offHead - 检测到变化后须立即上报,以确保音频路由响应敏捷
已连接音频源
对于支持同时连接多个蓝牙设备的配件,需要从 App Extension 中告知系统当前已连接了哪些设备。这样系统才能从正确的来源路由音频。
设置音频源标识符
将已连接设备的蓝牙地址以 Data 形式传入:
let primaryBTAddress = Data([0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC])
config.primaryAudioSourceDeviceIdentifier = primaryBTAddress
let secondaryBTAddress = Data([0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45])
config.secondaryAudioSourceDeviceIdentifier = secondaryBTAddress
当蓝牙连接状态发生变化(新设备连接、现有设备断开)时更新这些标识符,然后调用标准的 update(_:) 流程。
配置属性说明
自动切换会用到以下配置字段:
| 属性 | 类型 | 作用 |
|---|---|---|
deviceCapabilities |
Capabilities |
已声明的设备功能 |
devicePlacement |
Placement? |
当前物理佩戴状态 |
primaryAudioSourceDeviceIdentifier |
Data? |
主连接蓝牙设备地址 |
secondaryAudioSourceDeviceIdentifier |
Data? |
次连接蓝牙设备地址 |
功能探索与查询
查询设备功能
在 App Extension 中,可通过配置检查设备已声明的功能:
let device = try AccessoryControlDevice.current(for: accessory)
let caps = device.configuration.deviceCapabilities
if caps.contains(.audioSwitching) {
// 设备支持自动音频切换
}
if caps.contains(.placement) {
// 设备支持上报物理佩戴状态
}
检查佩戴状态
读取当前佩戴状态以判断配件是否正在被佩戴:
let device = try AccessoryControlDevice.current(for: accessory)
if let placement = device.configuration.devicePlacement {
switch placement {
case .inEar, .onHead, .overTheEar:
// 用户正在佩戴配件
break
case .offHead:
// 用户未佩戴配件
break
@unknown default:
break
}
}
错误处理
AccessoryControlDevice.Error 涵盖了注册和更新过程中的失败情况:
| 错误 | 原因 |
|---|---|
.accessoryNotCapable |
配件不支持请求的功能 |
.invalidRequest |
请求参数无效 |
.invalidated |
设备注册已失效/被作废 |
.unknown |
发生了未知错误 |
捕获并处理注册及更新调用中抛出的错误:
let configuration = AccessoryControlDevice.Configuration(
devicePlacement: .offHead,
deviceCapabilities: [.audioSwitching, .placement]
)
do {
try await AccessoryControlDevice.register(accessory, configuration)
} catch let error as AccessoryControlDevice.Error {
switch error {
case .accessoryNotCapable:
// 配件硬件不支持请求的功能
break
case .invalidRequest:
// 检查注册参数是否正确
break
case .invalidated:
// 重新协调主 App 进行注册
break
case .unknown:
// 记录日志、抛出或向上传播;Apple 未将其归类为暂态错误
throw error
@unknown default:
throw error
}
}
切勿直接假设 .invalidated 或 .unknown 是暂态错误。请修正无效的功能声明或请求参数,丢弃已失效的句柄并通知主 App 重新评估注册,同时妥善抛出未知错误。参阅 错误恢复模式 了解完整的处理策略与失效交接流程。
常见误区
切勿:未通过 AccessorySetupKit 配对就直接注册
必须使用 AccessorySetupKit 完成配对后返回的 ASAccessory 对象来进行注册。
切勿:声明了 placement 功能却不上报佩戴状态
如果注册时声明了 .placement,Extension 必须在每次检测到状态变化时通过标准更新流程同步佩戴状态。
切勿:忽略多设备配件的连接状态变更
蓝牙连接一旦改变,应立即清空或替换主/次音频源标识符;使用陈旧的标识符会导致音频切换准确率下降。
切勿:遗漏对 invalidated 错误的处理
// 错误示范 —— 忽略失效错误,继续使用已失效的设备引用
try await device.update(config) // 抛出 .invalidated,未被处理
// 正确示范 —— 丢弃句柄,让主 App 重新评估并重新注册
do {
try await device.update(config)
} catch AccessoryControlDevice.Error.invalidated {
await notifyContainerAppToReevaluateRegistration(accessory)
}
检查清单
- [ ] 在调用 AudioAccessoryKit 注册前,配件已通过 AccessorySetupKit 完成配对
- [ ] 已同时导入
AccessorySetupKit与AudioAccessoryKit - [ ] 主 App 使用
AccessoryControlDevice.Configuration调用了register(_: _:) - [ ] App Extension 正确调用了
current(for:)和update(_:) - [ ] 注册配置中的 Capabilities 与实际硬件支持相匹配
- [ ] 更新配置时仅触及注册时已声明功能对应的字段
- [ ] 声明
.placement功能的同时配有持续的佩戴状态更新 - [ ] 佩戴状态转换(戴上/摘下)能第一时间上报
- [ ] 蓝牙连接发生变化时能够及时更新音频源设备标识符
- [ ] 已妥善处理所有
AccessoryControlDevice.Error情况,包含@unknown default - [ ]
update(_:)调用使用了try await并进行了错误捕获 - [ ] 设备引用失效(Invalidated)时能触发主 App 恢复注册流程
- [ ] Deployment Target 已设为 iOS 26.4+ 或 iPadOS 26.4+
参考资料
- 进阶模式(注册流程、佩戴状态监听、多设备协同):references/audioaccessorykit-patterns.md
- [AudioAccessoryKit
<!-- truncated for translation batch; full body continues in source -->




