📈

【Android】今から学ぶHealthConnectからの数値取得

に公開

株式会社PREVENTでAndroidアプリエンジニアの千野です。
この記事はPREVENTアドベントカレンダーの10日目の記事です。
https://adventar.org/calendars/12152

直近AndroidのHealthConnectアプリから数値を取るという実装をすることになり、その時の実装の備忘録となります。

前提

  • Android Studio Narwhal 3 Feature Drop | 2025.1.3
  • Kotlin 2.2.20

やり方

大体は公式にやり方が書いてあります。
https://developer.android.com/health-and-fitness/health-connect/get-started?hl=ja

今回はHealthConnectから体重をとるよう実装してみます。

AndroidManifest編集

まずAndroidManifestに体重読み取りの権限を追記します。

<manifest>
  <uses-permission android:name="android.permission.health.READ_WEIGHT"/>
  <application>
  ...
  </application>
</manifest>

こんな感じです。
次にHealthConnectからデータ取得の許可ダイアログを出すための記述を同じくManifestにします。
必要なのは
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
という設定

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:label="@string/app_name"
    android:theme="@style/Theme.TestApp">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        // ココ!
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

こんな感じで、許可ダイアログを出したいAcitivtyに設定します。
最後にHealthConnect APIへの接続を行うための設定をManifest末尾に追加します。

    <queries>
        <package android:name="com.google.android.apps.healthdata" />
    </queries>

これでManifest側の設定は終了です。

コード側の実装

Manifestをいじったら次にコードの実装に入ります。
早速許可ダイアログを出したいところですが最初に端末にHealthConnectが存在するかを確認しないといけません。
まずはHealthConnect自体が使えるかの確認とHealthConnectの存在確認をする必要があります。
自分は下記のような関数を作り2つのチェックを行うようにしました。

fun checkAvailabilityAndRequest(): HealthConnectClient? {
        val status = HealthConnectClient.getSdkStatus(context)
        // HealthConnectが利用可能か確認
        if (status == HealthConnectClient.SDK_UNAVAILABLE) return null

        // HealthConnectが存在するか確認
        if (status == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
            // HealthConnectが存在しない・アップデートが必要ならストアに飛ばす
            val providerPackageName = "com.google.android.apps.healthdata"
            val uriString =
                "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
            val intent = Intent(Intent.ACTION_VIEW).apply {
                setPackage("com.android.vending")
                data = Uri.parse(uriString)
                putExtra("overlay", true)
                putExtra("callerId", context.packageName)
            }
            context.startActivity(intent)
            return null
        }
        return HealthConnectClient.getOrCreate(context)
}

ここまでチェックが通過したら次に許可ダイアログを出してあげます。

// 取得したい項目
private val permission = setOf(
        HealthPermission.getReadPermission(WeightRecord::class)
)
    
        fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
        val granted = healthConnectClient.permissionController.getGrantedPermissions()
        // permission に許可されていない権限がある場合ダイアログを出す
        if (!granted.containsAll(permission)) {
            requestPermissions.launch(permission)
        }
}

これを呼ぶことで許可ダイアログを出すことができるようになります。

許可ダイアログを出し、体重の取得を許可したらいよいよ体重の取得コードの実装に入ります。
自分は下記のようなメソッドを作って体重を取得するようにしました。

    fun getWeightData(
        healthConnectClient: HealthConnectClient,
        startTime: java.time.Instant,
        endTime: java.time.Instant
    ): List<WeightRecord> {
        return try {
            // 指定した期間の体重を取得する
            val response = healthConnectClient.readRecords(
                ReadRecordsRequest(
                    WeightRecord::class,
                    timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
                )
            )
            response.records
        } catch (e: Exception) {
            Timber.e(e)
            emptyList()
        }
    }

これで体重の取得を行うことができるようになりました。
他の数値を取得したい場合は適宜Manfest, permission を書き換えてあげればよいかなと思います。

実装中に引っかかったところ

権限の許可ダイアログを出すまでにHealthConnectアプリを開いていないと権限許可ダイアログが表示されずに初回起動画面が開いてしまい権限の許可ができないということがありました。
エミュレーターで検証する際は一度HealthConnectを開いておいてから権限許可を行うとスムーズかもしれません。

Discussion