mcpField
A
audioaccessorykit

audioaccessorykit

github.com/dpearson2699开发1.2k3.1k 次安装13 周前更新
代码仓库

关于 audioaccessorykit

AudioAccessoryKit 是面向 iOS 和 iPadOS 开发者的指南,用于配置第三方音频配件参与系统音频切换。它介绍如何通过配套应用及其扩展注册配件,并更新佩戴状态和蓝牙音源。

主要功能

  1. 01配对后的配件注册
  2. 02音频切换能力配置
  3. 03佩戴位置状态上报
  4. 04已连接蓝牙音源更新
  5. 05能力查询与错误处理

适用场景

  1. 01为已配对配件启用自动切换
  2. 02上报耳机佩戴或摘下状态
  3. 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 扩展后续推送的配置更新。

目录

设置

前置条件
  1. 使用 AccessorySetupKit 通过蓝牙配对配件。此操作会生成一个 ASAccessory 对象。
  2. 根据需要,在容器 App 和扩展中导入框架:
import AccessorySetupKit
import AudioAccessoryKit
框架可用性
平台最低版本
iOS26.4+
iPadOS26.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(_:) 序列。

配置属性

自动切换会使用以下配置字段:

属性类型用途
deviceCapabilitiesCapabilities声明的设备功能
devicePlacementPlacement?当前物理佩戴位置
primaryAudioSourceDeviceIdentifierData?主要已连接蓝牙设备的地址
secondaryAudioSourceDeviceIdentifierData?次要已连接蓝牙设备的地址

功能发现

查询功能

在应用扩展中,通过设备配置检查已声明的功能:

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+

参考资料

评论

支持 Markdown