关于 audioaccessorykit
AudioAccessoryKit 是面向 iOS 和 iPadOS 开发者的指南,用于配置第三方音频配件参与系统音频切换。它介绍如何通过配套应用及其扩展注册配件,并更新佩戴状态和蓝牙音源。
主要功能
- 01配对后的配件注册
- 02音频切换能力配置
- 03佩戴位置状态上报
- 04已连接蓝牙音源更新
- 05能力查询与错误处理
适用场景
- 01为已配对配件启用自动切换
- 02上报耳机佩戴或摘下状态
- 03为多设备配件更新音源标识
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dpearson2699/ swift-ios-skills --skill audioaccessorykit安装后在 Claude Code 中输入/audioaccessorykit确认已加载。
附带文件evals/evals.jsonreferences/audioaccessorykit-patterns.md
详细介绍
AudioAccessoryKit
为第三方音频配件提供自动音频切换支持和智能音频路由输入。允许配套 App 向系统注册音频配件配置,并由 App 扩展报告放置位置和已连接音源的变化,帮助系统切换音频输出。 适用于 iOS 26.4+ / iPadOS 26.4+。
对 Beta 敏感。 AudioAccessoryKit 在 iOS 26.4 中首次推出。依赖特定 API 细节前,请重新查阅 Apple 文档。
AudioAccessoryKit 基于 AccessorySetupKit 构建。配件必须先通过 AccessorySetupKit 配对,然后才能注册音频功能。核心类型是 AccessoryControlDevice,它负责从容器 App 注册 Configuration,并应用 App 扩展后续推送的配置更新。
目录
设置
前置条件
- 使用 AccessorySetupKit 通过蓝牙配对配件。此操作会生成一个
ASAccessory对象。 - 根据需要,在容器 App 和扩展中导入框架:
import AccessorySetupKit
import AudioAccessoryKit
框架可用性
| 平台 | 最低版本 |
|---|---|
| iOS | 26.4+ |
| iPadOS | 26.4+ |
在当前的 Xcode 26.6 工具链中,设备 SDK 包含 AudioAccessoryKit,但 iPhone Simulator 26.5 SDK 不包含。请为此目标使用实体设备作为运行目标。如果 App 的其余部分必须构建为 Simulator 版本,请隔离目标成员资格,或使用 #if canImport(AudioAccessoryKit) 保护导入和实现,并提供 Simulator 存根。
会话管理
注册配件
通过 AccessorySetupKit 完成配对后,在容器 App 中传入 AccessoryControlDevice.Configuration 来注册配件,描述配件支持的功能以及支持的任何初始状态:
let accessory: ASAccessory // Obtained from AccessorySetupKit pairing
let configuration = AccessoryControlDevice.Configuration(
devicePlacement: .offHead,
deviceCapabilities: [.audioSwitching, .placement]
)
try await AccessoryControlDevice.register(accessory, configuration)
注册会启用指定功能,并向系统提供参与音频路由决策所需的配置。
获取当前配置
在 App 扩展中,使用静态方法 current(for:) 访问设备的当前配置:
let device = try AccessoryControlDevice.current(for: accessory)
let currentConfig = device.configuration
此方法会返回与已配对的 ASAccessory 关联的 AccessoryControlDevice 实例。该设备提供 accessory 引用和当前 configuration。Apple 指出,current(for:) 仅适用于 App 扩展。
更新配置
在 App 扩展中,使用 update(_:) 向系统推送配置更改。只能更新注册时声明的功能对应的字段:
let device = try AccessoryControlDevice.current(for: accessory)
var config = device.configuration
config.devicePlacement = .onHead
try await device.update(config)
请将其视为有条件的写入工作流:确认注册时已声明该功能,复制并修改 device.configuration,然后执行 try await update(_:)。此方法不返回配置值;只有在调用成功后,才更新 App 端的镜像。若调用失败,请参阅错误处理中的处置方式。Apple 指出,update(_:) 仅适用于 App 扩展。
音频切换
自动音频切换可让系统根据放置位置和已连接音源,将音频输出智能路由到正确的设备。
启用音频切换
在上述标准注册流程中声明 .audioSwitching。仅当配件能够报告持续变化的放置位置时,才加入 .placement 并设置初始放置位置。
功能
自动切换通常会使用这些 AccessoryControlDevice.Capabilities:
| 功能 | 用途 |
|---|---|
.audioSwitching | 设备支持自动切换音频 |
.placement | 设备可以报告其物理佩戴位置 |
根据需要组合功能。除非配件能够持续向系统更新实际佩戴位置,否则不要声明 .placement。
设备佩戴位置
从应用扩展报告配件的物理佩戴位置,帮助系统做出路由决策。每当配件检测到佩戴位置变化时,都要更新佩戴位置。
佩戴位置值
AccessoryControlDevice.Placement 定义了四种情况:
| 佩戴位置 | 含义 |
|---|---|
.inEar | 配件佩戴在耳内(例如耳塞式耳机) |
.onHead | 配件佩戴在头上(例如头戴式耳机) |
.overTheEar | 配件罩在耳朵外(例如包耳式耳机) |
.offHead | 未佩戴配件 |
更新佩戴位置
config.devicePlacement = .inEar
在上述规范的“读取当前值→复制→更新”序列中应用此变更。
常见状态转换:
- 用户戴上配件时,从
.offHead转为.onHead或.inEar - 取下配件时,从
.onHead或.inEar转为.offHead - 每次检测到变化时及时更新,以实现响应迅速的音频路由
已连接的音频源
对于可同时连接多个蓝牙设备的配件,从应用扩展告知系统哪些设备已连接。这样系统就能从适当的来源路由音频。
设置音频源标识符
将已连接设备的蓝牙地址作为 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? | 次要已连接蓝牙设备的地址 |
功能发现
查询功能
在应用扩展中,通过设备配置检查已声明的功能:
let device = try AccessoryControlDevice.current(for: accessory)
let caps = device.configuration.deviceCapabilities
if caps.contains(.audioSwitching) {
// Device supports automatic audio switching
}
if caps.contains(.placement) {
// Device reports physical placement
}
检查佩戴位置
读取当前佩戴位置,以确定配件是否已佩戴:
let device = try AccessoryControlDevice.current(for: accessory)
if let placement = device.configuration.devicePlacement {
switch placement {
case .inEar, .onHead, .overTheEar:
// Accessory is being worn
break
case .offHead:
// Accessory is not being worn
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:
// Accessory hardware does not support requested capabilities
break
case .invalidRequest:
// Check registration parameters
break
case .invalidated:
// Coordinate container-app registration again
break
case .unknown:
// Log, surface, or propagate; Apple does not classify this as transient
throw error
@unknown default:
throw error
}
}
不要假定 .invalidated 或 .unknown 是暂时性的。修正无效的功能声明或请求参数;丢弃已失效的句柄,并在适当情况下通知容器应用重新评估注册;对于未指定的错误,应将其报告出来。阅读错误恢复模式,了解完整的处置流程和失效交接方式。
常见错误
不要:在与 AccessorySetupKit 配对前注册
仅注册 AccessorySetupKit 配对完成后返回的 ASAccessory。
不要:声明佩戴位置功能却不更新佩戴位置
如果注册时声明了 .placement,扩展就必须在每次检测到状态转换时,使用规范的更新序列更新佩戴位置。
不要:忽略多设备配件的连接状态变化
每当蓝牙连接发生变化,都要清除或替换主要和次要音频源标识符;过时的标识符会降低切换准确性。
不要:忘记处理失效错误
// WRONG -- ignores invalidation, keeps using stale device reference
try await device.update(config) // Throws .invalidated, unhandled
// CORRECT -- discard the handle and let the container re-evaluate registration
do {
try await device.update(config)
} catch AccessoryControlDevice.Error.invalidated {
await notifyContainerAppToReevaluateRegistration(accessory)
}
审查清单
- 在注册 AudioAccessoryKit 之前,通过 AccessorySetupKit 配对配件
- 导入
AccessorySetupKit和AudioAccessoryKit - 容器应用调用
register(_: _:),并传入AccessoryControlDevice.Configuration - 应用扩展调用
current(for:)和update(_:) - 注册配置中的功能与硬件实际支持的功能相符
- 仅更新注册时声明的功能对应的字段
-
.placement功能需配合持续的位置更新 - 及时报告位置变更(戴上/摘下头部)
- 蓝牙连接状态变更时更新音频源设备标识符
- 处理所有
AccessoryControlDevice.Error情况,包括@unknown default - 调用
update(_:)时使用try await并处理错误 - 设备引用失效时,触发容器应用恢复注册
- 将部署目标设为 iOS 26.4+ 或 iPadOS 26.4+
参考资料
- 扩展模式(注册流程、位置监控、多设备协调):references/audioaccessorykit-patterns.md
- AudioAccessoryKit 框架
- 支持自动音频切换
- AccessoryControlDevice
- AccessoryControlDevice 注册
- AccessoryControlDevice 查询
- AccessoryControlDevice 更新
- AccessoryControlDevice.Configuration
- AccessoryControlDevice.Capabilities
- AccessoryControlDevice.Placement
- AccessorySetupKit 框架(配对的前置条件)