🏃

iPhoneとAppleWatch間でWorkoutを同期する

2024/06/21に公開

HealthKitのAPIを活用したワークアウトセッションの同期

AppleWatchとiPhone間でワークアウトセッションを同期する方法に焦点を当て、詳細に説明します。このAPIを使用することで、AppleWatchで実行中のワークアウトをiPhoneに同期し、リアルタイムでデータを表示・制御することができます。今回はWorkoutに関しての詳細は記載しません。Workoutに関しては過去に記事を書きましたので、参考までにご覧ください。

https://zenn.dev/muranaka/articles/2_e775b55b2e90ec

ワークアウトセッションの構成

ワークアウトセッションは、AppleWatchで開始され、iPhoneで受信されます。

1. ワークアウトセッションの開始

AppleWatchでワークアウトセッションを開始します。このセッションは「Primary Session」と呼ばれ、ワークアウトのライフサイクル(開始、停止、再開など)を管理します。

2. ミラーリングの開始

AppleWatchでPrimarySessionを開始した後、startMirroringToCompanionDeviceメソッドを呼び出して同期を開始します。このメソッドにより、iPhoneアプリがバックグラウンドで起動され、ワークアウトセッションが渡されます。

try await session?.startMirroringToCompanionDevice()

3. ミラーリングの開始を検知する

iPhoneアプリでは、アプリの起動シーケンスでハンドラを設定して、HealthStoreを使用してセッションを受け取る準備をします。

healthStore.workoutSessionMirroringStartHandler = { mirroredSession in
    Task { @MainActor in
        Logger.shared.log("リモートセッションのミラーリングを開始: \(mirroredSession)")
    }
}

4. セッション状態の同期

Apple WatchとiPhoneの両方でセッションの状態を監視するために、デリゲートを設定します。

デリゲートにより、セッションの状態変更(開始、停止、再開など)が両デバイスで同期されます。デリゲートの実装方法に関しては、こちらの記事をご覧ください。

ミラーリング中のデータ交換

HealthKitはミラーリングセッション間でデータを受け渡しが可能です。これにより、ワークアウトデータやイベントをリアルタイムで同期できます。

データの送信

AppleWatchからiPhoneへのデータ送信は、sendToRemoteWorkoutSession(data:completion:)メソッドを使用します。ワークアウトデータのリアルタイムでの取得は、HKLiveWorkoutBuilderDelegateworkoutBuilder(_:didCollectDataOf:)メソッドで、取得したデータを検知し送信します。

extension WorkoutManager: HKLiveWorkoutBuilderDelegate {
    nonisolated func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
        Task { @MainActor in
            // 処理を省略 Data型に変換して送信する
            do {
                try await session?.sendToRemoteWorkoutSession(data: ...)
            } catch {
                Logger.shared.log("データ送信に失敗しました: \(error)")
            }
        }
    }
}

データの受信

iPhone側でデータを受信するには、HKWorkoutSessionDelegateworkoutSession(_:didReceiveDataFromRemoteWorkoutSession:)メソッドを実装します。この実装により、AppleWatch側から送信されたData型を、iPhone側で受け取ることが可能です。

extension WorkoutManager: HKWorkoutSessionDelegate {
    nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
                                    didReceiveDataFromRemoteWorkoutSession data: [Data]) {
        Logger.shared.log("\(#function): \(data.debugDescription)")
        Task { @MainActor in
            do {
                for anElement in data {
                    try handleReceivedData(anElement)
                }
            } catch {
                Logger.shared.log("データの処理に失敗しました: \(error)")
            }
        }
    }
}

今回の事例ではAppleWatchからiPhoneへのデータ送信を記載しますが、iPhoneからAppleWatchへのデータ送信も同様の実装で可能です。

ミラーリングの停止

ワークアウトセッションのミラーリングを停止するには、stopMirroringToCompanionDevice(completion:)メソッドを呼び出します。

do {
    try await session.stopMirroringToCompanionDevice()
} catch {
    fatalError("*** ミラーリングワークアウトの停止中にエラーが発生しました: \(error.localizedDescription) ***")
}

まとめ

HealthKitのミラーリングAPIを使用することで、Apple WatchとiPhone間でリアルタイムにワークアウトセッションを同期し、データを交換することが可能になります。ユーザーはより良いワークアウト体験を得ることができます。以上が、HealthKitのミラーリングAPIを活用したワークアウトセッションの同期方法です。

最後に

間違い・気になる部分がありましたら、コメントいただけると大変うれしいです。
良かったと思ったら記事へのいいねXのフォローをよろしくお願いいたします。

https://sites.google.com/view/muranakar

個人でアプリを作成しています。良かったら覗いてみてください。

参考資料

https://developer.apple.com/videos/play/wwdc2023/10023/

https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/building_a_multidevice_workout_app

Discussion