mcpField
A
audioaccessorykit

audioaccessorykit

github.com/dpearson2699開発1.2k3.1k 回インストール13 週間前に更新
リポジトリ

audioaccessorykit について

AudioAccessoryKitは、サードパーティ製オーディオアクセサリをシステムの自動切り替えに対応させるためのiOS・iPadOS開発ガイドです。コンパニオンアプリとその拡張機能によるアクセサリ登録、装着状態やBluetooth音源の更新を説明します。

主な機能

  1. 01ペアリング後のアクセサリ登録
  2. 02オーディオ切り替え機能の設定
  3. 03装着位置の報告
  4. 04接続中のBluetooth音源の更新
  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

他社製オーディオアクセサリ向けの自動オーディオ切り替えサポートと、インテリジェントなオーディオルーティング入力を提供します。コンパニオンアプリからシステムにオーディオアクセサリの構成を登録できるようにし、アプリ拡張機能から設置状態や接続ソースの変更を報告して、システムがオーディオ出力を切り替えられるようにします。iOS 26.4+ / iPadOS 26.4+ で利用できます。

ベータ版のため、情報は変更される可能性があります。 AudioAccessoryKit は iOS 26.4 で新たに導入されました。特定の API の詳細に依存する前に、最新の Apple ドキュメントを再確認してください。

AudioAccessoryKit は AccessorySetupKit を基盤としています。オーディオ機能に登録する前に、AccessorySetupKit を使ってアクセサリをペアリングする必要があります。中心となる型は AccessoryControlDevice です。コンテナアプリから Configuration を登録し、アプリ拡張機能から継続的な構成の更新を適用します。

目次

セットアップ

前提条件
  1. AccessorySetupKit を使って Bluetooth 経由でアクセサリをペアリングします。これにより ASAccessory オブジェクトが取得されます。
  2. 必要に応じて、コンテナアプリと拡張機能にフレームワークをインポートします。
import AccessorySetupKit
import AudioAccessoryKit
フレームワークの利用可能状況
プラットフォーム最小バージョン
iOS26.4+
iPadOS26.4+

現在の Xcode 26.6 ツールチェーンでは、AudioAccessoryKit はデバイス SDK に含まれていますが、iPhone Simulator 26.5 SDK には含まれていません。このターゲットには実機のデスティネーションを使用してください。アプリの残りの部分を Simulator 向けにビルドする必要がある場合は、ターゲットメンバーシップを分離するか、インポートと実装を #if canImport(AudioAccessoryKit) でガードし、Simulator 用のスタブを用意してください。

セッション管理

アクセサリの登録

AccessorySetupKit でペアリングした後、アクセサリがサポートする機能と初期状態を記述する AccessoryControlDevice.Configuration を渡して、コンテナアプリからアクセサリを登録します。

let accessory: ASAccessory  // Obtained from AccessorySetupKit pairing

let configuration = AccessoryControlDevice.Configuration(
    devicePlacement: .offHead,
    deviceCapabilities: [.audioSwitching, .placement]
)

try await AccessoryControlDevice.register(accessory, configuration)

登録すると、指定した機能が有効になり、オーディオルーティングの判断に参加するために必要な構成がシステムに提供されます。

現在の構成の取得

アプリ拡張機能で、静的な current(for:) メソッドを使ってデバイスの現在の構成にアクセスします。

let device = try AccessoryControlDevice.current(for: accessory)
let currentConfig = device.configuration

これにより、ペアリング済みの ASAccessory に関連付けられた AccessoryControlDevice インスタンスが返されます。このデバイスは accessory 参照と現在の configuration の両方を公開します。Apple は current(for:) をアプリ拡張機能専用として指定しています。

構成の更新

アプリ拡張機能で 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(_:) を実行します。このメソッドは構成値を返しません。アプリ側のミラーは呼び出しが成功した後にのみ更新してください。失敗した場合は、エラー処理に記載された処理方法を使用します。Apple は update(_:) をアプリ拡張機能専用として指定しています。

オーディオ切り替え

自動オーディオ切り替えにより、設置状態と接続ソースに基づいて、システムがオーディオ出力を適切なデバイスにインテリジェントにルーティングできます。

オーディオ切り替えの有効化

前述の標準的な登録フローで .audioSwitching を宣言します。アクセサリが設置状態の変化を継続的に報告できる場合に限り、.placement と初期の設置状態を含めてください。

機能

自動切り替えでは、一般に次の AccessoryControlDevice.Capabilities を使用します。

機能目的
.audioSwitchingデバイスがオーディオの自動切り替えに対応している
.placementデバイスが物理的な装着状態を報告できる

必要に応じて機能を組み合わせてください。アクセサリが実際の装着状態をシステムに継続的に通知できない場合は、.placement を宣言しないでください。

デバイスの装着状態

システムのルーティング判断に役立つよう、アプリ拡張からアクセサリの物理的な装着位置を報告します。アクセサリが装着位置の変化を検出するたびに、装着状態を更新してください。

装着状態の値

AccessoryControlDevice.Placement では、次の 4 つのケースを定義しています。

装着状態意味
.inEarアクセサリが耳に装着されている(例:イヤーバッド)
.onHeadアクセサリが頭に装着されている(例:ヘッドバンド型ヘッドフォン)
.overTheEarアクセサリが耳を覆っている(例:オーバーイヤー型ヘッドフォン)
.offHeadアクセサリが装着されていない
装着状態の更新
config.devicePlacement = .inEar

この変更は、前述の標準的な現在値→コピー→更新の手順で適用してください。

一般的な遷移:

  • ユーザーがアクセサリを装着したとき、.offHead から .onHead または .inEar に変更する
  • アクセサリを外したとき、.onHead または .inEar から .offHead に変更する
  • オーディオのルーティングをすばやく反映できるよう、検出した変化ごとに速やかに更新する

接続済みオーディオソース

複数の Bluetooth デバイスに同時に接続するアクセサリの場合、どのデバイスが接続されているかをアプリ拡張からシステムに通知します。これにより、システムは適切なソースからオーディオをルーティングできます。

オーディオソース識別子の設定

接続済みデバイスの Bluetooth アドレスを 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

Bluetooth 接続状態が変化したとき(新しいデバイスの接続、既存デバイスの切断)にこれらの識別子を更新し、続けて標準の update(_:) 手順を呼び出してください。

構成プロパティ

自動切り替えでは、次の構成フィールドを使用します。

プロパティ型目的
deviceCapabilitiesCapabilities宣言されたデバイスの機能
devicePlacementPlacement?現在の物理的な装着状態
primaryAudioSourceDeviceIdentifierData?プライマリ接続済み Bluetooth デバイスのアドレス
secondaryAudioSourceDeviceIdentifierData?セカンダリ接続済み Bluetooth デバイスのアドレス

機能の検出

機能の確認

アプリ拡張で、構成を通じてデバイスに宣言された機能を確認します。

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 を宣言した場合、拡張機能は検出した遷移ごとに、標準の更新手順を使用して装着状態を更新する必要があります。

してはいけないこと:複数デバイス対応アクセサリの接続状態の変化を無視する

Bluetooth 接続が変化するたびに、プライマリおよびセカンダリのソース識別子を消去または置き換えてください。古い識別子が残っていると、切り替えの精度が低下します。

やってはいけないこと:無効化されたエラーへの対処を忘れる
// 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 の両方がインポートされている
  • コンテナアプリが AccessoryControlDevice.Configuration を指定して register(_: _:) を呼び出している
  • アプリ拡張が current(for:) と update(_:) を呼び出している
  • 登録設定の機能が、実際のハードウェアの対応状況と一致している
  • 更新では、登録時に宣言した機能のフィールドのみを変更している
  • .placement 機能を指定する場合、継続的な装着状態の更新も行っている
  • 装着状態の切り替わり(頭への装着/取り外し)を速やかに報告している
  • Bluetooth 接続の変更時に、オーディオソースデバイスの識別子を更新している
  • @unknown default を含め、すべての AccessoryControlDevice.Error ケースを処理している
  • update(_:) の呼び出しで try await を使用し、エラーを処理している
  • 無効化されたデバイス参照が発生した場合、コンテナアプリによる登録の復旧を開始している
  • デプロイメントターゲットが iOS 26.4 以降、または iPadOS 26.4 以降に設定されている

参考資料

コメント