every Tech Blog

株式会社エブリーのTech Blogです。

iOSのヘルスケアアプリ連携について

はじめに

iOSにはデフォルトで「ヘルスケア」というアプリが存在することをご存知でしょうか。
弊社のDELISH KITCHENアプリでは昨年ヘルスケアという新機能をリリースしましたが、日々改修を重ねていく中でヘルスケアアプリにも着目し、色々と調査を行いました。

今回はその調査内容について纏めていきたいと思います。

ヘルスケアアプリとは

赤丸で囲ったものがヘルスケアアプリです。

こちらのアプリでは、歩数などのアクティビティ情報や、血圧などのバイタル情報といった健康・医療情報を一つのアプリで管理できるものとなっており、簡単に情報を閲覧・編集することができます。

私の場合、Apple Watchで歩数を記録し、ヘルスケアアプリで一週間の平均歩数を確認する、といった使い方をしています。
まだ使用されたことがない方は一度触れてみてはいかがでしょうか。

HealthKitについて

https://developer.apple.com/jp/health-fitness/

プログラムからヘルスケアアプリの情報にアクセスする場合、HealthKitを使用します。
HealthKitを使用することで容易にヘルスケアアプリの情報にアクセスすることができます。

https://www.proofpoint.com/jp/threat-reference/hipaa-compliance

余談にはなりますが、医療分野で業務を行う立場の場合はHIPAAという法律に従うことになります。
今回はHIPAAについて深くは触れませんが、健康情報を記録するアプリ(非HIPAAアプリ)と医療行為に関わるアプリ(HIPAA対象アプリ)で作成するプライバシーポリシーやアプリ申請内容が異なりますので、よく内容を理解してから実装することをお勧めします。

ヘルスケア連携手順

ここからは実際にプログラムからヘルスケアに連携する方法を纏めていきたいと思います。
今回はHealthKitを使って歩数の情報を取得する方法を纏めます。

開発環境

  • Xcode Version 14.3.1 (14E300c)
  • 開発言語 : swift

Capability追加

TARGETS > Signing & Capabilitiesにて、HealthKitを追加

今回、臨床記録のデータにアクセス、およびバックグラウンド配信は行わないため、以下のチェックは不要です。

info.plist更新

info.plistにて、以下2項目を追加
- Privacy - Health Update Usage Description … ヘルスケアのデータを更新するための許可を求める時に表示される文言
- Privacy - Health Share Usage Description … ヘルスケアのデータを取得するための許可を求める時に表示される文言

Valueに書かれた文字列が、後述する権限確認ダイアログに表示されます。

認証処理実装

ここからは実装に入ります。

    let healthStore: HKHealthStore
    
    init() {
        healthStore = HKHealthStore()
    }

HKHealthStoreのインスタンスを介して認証、取得、更新を行いますので、まずはインスタンスの生成をしておきます。

    func auth() {
        // 更新したいデータ
        let shareTypes = Set([
            // 歩数
            HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        ])
        
        // 取得したいデータ
        let readTypes = Set([
            // 歩数
            HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        ])
        
        // 認証実施
        healthStore.requestAuthorization(
            toShare: shareTypes,
            read: readTypes,
            completion: { success, error in
                if success { print("許可されました") }
                else { print("却下されました") }
            }
        )
    }

次に認証処理となります。

requestAuthorizationでユーザに対してアクセスする情報の権限確認ダイアログを表示します。
toShareには更新したいデータを設定、readには取得したいデータを設定します。
※plistで設定する情報とshareの意味が異なるので注意が必要です。

実行すると上記のような権限確認ダイアログが表示されます。
このダイアログには前述したplistに設定した文言が表示されます。

取得処理実装

ヘルスケアアプリからデータを取得する処理を実装します。

    func getStepCount(fromDate: Date, endDate: Date) {
        let query = HKSampleQuery(
            // 取得したいデータの種別
            sampleType: HKSampleType.quantityType(forIdentifier: .stepCount)!,
            // データの期間
            predicate: HKQuery.predicateForSamples(withStart: fromDate, end: endDate),
            // 取得件数の上限
            limit: HKObjectQueryNoLimit,
            // ソート
            sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)],
            resultsHandler: { (query, results, error) in
                guard error == nil else { return }
                
                // 取得した結果をサンプリングデータの型に変換
                if let itemList = results as? [HKQuantitySample] {
                    for item in itemList {
                        print("記録日時 : \(item.endDate)")
                        print("歩数 : \(String(item.quantity.doubleValue(for: .count())))")
                    }
                }
            }
        )
        healthStore.execute(query)
    }

HKSampleQueryでクエリの情報を作成し、executeメソッドに流すという実装となります。

更新処理実装

ヘルスケアアプリからデータを更新する処理を実装します。

    func updateStepCount(targetData: Date, stepCount: Double) {
        // 更新したいデータの種別
        let type = HKObjectType.quantityType(forIdentifier: .stepCount)!
        // 設定するデータ
        let quantity = HKQuantity(unit: .count(), doubleValue: stepCount)
        // サンプリングデータ作成
        let sample = HKQuantitySample(type: type, quantity: quantity, start: targetData, end: targetData)
        healthStore.save(sample, withCompletion: { (success, error) in if success {
            print("成功")
        } else {
            print("失敗") }
        })
    }

HKQuantitySampleでサンプリングデータを作成し、saveメソッドに流すという実装となります。

取得・更新時の注意点

取得・更新処理を前述しましたが、データを取り扱う際の注意点があります。

        // 設定するデータ
        let quantity = HKQuantity(unit: .count(), doubleValue: stepCount)

更新処理のこちらの部分ですが、インスタンスを生成する際に第1引数にHKUnitを設定しています。

https://developer.apple.com/documentation/healthkit/hkunit

HKUnitは「単位」のクラスになりますが、実装する際は設定するデータと単位が一致しないとExceptionが発生してしまいます。
今回は歩数のため、カウントの単位を返す.count()を設定していますが、

        let quantity = HKQuantity(unit: .kilocalorie(), doubleValue: stepCount)

のように、歩数にキロカロリーの単位を返す.kilocalorie()を設定してもビルド時にはエラーを検知できず、実行できてしまいます。
ヘルスケアアプリでは複数の情報を管理する都合上、単位の種類も多いのですが、適切な単位を設定する必要がある点に注意してください。

おわりに

HealthKitを使用したヘルスケアアプリとの連携方法を纏めましたが、前述の設定、実装のみでアクセスできるため、敷居は低く、簡単に実装ができました。

近年、UIUXを向上させるためには簡単にデータを取得・編集ができる、別アプリと連携できることが必須だと感じていますが、健康志向の方も多くなり、またスマートウォッチが普及したこともあり、ヘルスケアアプリでデータを記録しているユーザも増えている印象なので、健康情報などヘルスケアアプリでも管理している情報を扱う際はHealthKitを導入することで十分な効果が見込めると思います。

今回はHealthKitの触り部分の紹介となりますが、ヘルスケア連携の実装を考えている方にとって少しでも参考になれば幸いです。