Google I/O '22 で発表があった「HealthConnect」をとりあえず触ってみたのでその所感を雑にまとめます。
ちゃんと理解したら、また別にブログ書きます。
HealthConnect
I/OのDeveloperKeynoteにあった発表をまとめるとこんな感じ(英語聞き取りミスで間違いあるかも)
- Samsungとのコラボで生まれた新しいプラットフォーム
- アプリ間の接続を簡素化して、少ない作業で多くのユーザーに簡単にアクセス可能
- 権限を使用して、単一のAPIセットですべてのAndroidデバイスのヘルスデータに安全にアクセスして共有できる(マジか?!)
- Sumsung Health, Fitbit, Google Fit はHealth Connectを採用している
Fitbit、Google FitはHealthConnect採用とあるが見てみてもよくわからなかった。
Alpha版公開中
Alpha版が公開されてるので触ってみた。
要件
minSdk 27以上であることを求められます。 Oreo 8.1以上です。きっついですね。
事前準備
HealthConnectのapkをインストールする必要があります。
https://developer.android.com/guide/health-and-fitness/health-connect/get-started
パーミッション
各データタイプに合わせて、読み取り・書き込みパーミッション許可する必要があります。
AndroidManifest.xml
にパーミッションを渡します
<intent-filter> <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/> </intent-filter> <meta-data android:name="health_permissions" android:resource="@array/health_permissions" />
一例ですが、今回体温のデータでサンプルアプリ作ってみたので体温データの読み書きをしたい場合はこうです。
<?xml version="1.0" encoding="utf-8"?> <resources> <array name="health_permissions"> <item>androidx.health.permission.BodyTemperature.READ</item> <item>androidx.health.permission.BodyTemperature.WRITE</item> </array> </resources>
データタイプ
かなりたくさんあります。 ありとあらゆる情報をHealthConnectで管理できます。
androidx.health.connect.client.records | Android Developers
体温管理するサンプル作ってみた
HealthConnectClient生成
if (HealthConnectClient.isAvailable(context)) { val healthConnectClient = HealthConnectClient.getOrCreate(context) }
パーミッション要求
パーミッションはCoroutineScope内で要求します
val requestPermissions = registerForActivityResult(HealthDataRequestPermissions()) { granted -> // success permission } fun checkPermissionsAndRun(requestPermissions: ActivityResultLauncher<Set<Permission>>) { lifecycleScope.launch { val granted = healthConnectClient.permissionController.getGrantedPermissions(PERMISSIONS) if (granted.containsAll(PERMISSIONS)) { // Permissions already granted } else { requestPermissions.launch(PERMISSIONS) } } }
データ書き取り
体温データBodyTemperature
をInsertします。
BodyTemperatureは引数に以下を取ります
temperatureDegreesCelsius
: 摂氏温度measurementLocation
: 測った場所 脇や額、耳、手首などあらゆる検知方法に対応してます。非接触な方法までカバーしているのが今どき。 BodyTemperatureMeasurementLocation | Android Developerstime
: 測った時間。Instant型です。zoneOffset
: TimeZonemetadata
: メタデータ。パッケージネームやデバイス情報を送れます。ウェアラブルなども渡せるすごない。
メタデータでデバイス送れるのが最近の多種多様なデバイス環境をカバーしている印象受けますね。
suspend fun insertBodyTemperature( bodyTemperature: Double, onSuccess: (response: InsertRecordsResponse?) -> Unit, onFailed: (e: Throwable) -> Unit ) { val record = listOf( BodyTemperature( temperatureDegreesCelsius = bodyTemperature, measurementLocation = BodyTemperatureMeasurementLocation.ARMPIT, time = Instant.now(), zoneOffset = ZoneOffset.ofHours(9), metadata = Metadata(dataOrigin = DataOrigin(packageName = BuildConfig.APPLICATION_ID), device = Device(manufacturer = Build.MANUFACTURER, model = Build.MODEL, type = Build.TYPE)) ) ) }
データ読み取り
ReadRecordsRequest
を生成してデータを取得します。スキーマがデータごとではなく共通なところが楽。
recordType
: 欲しいデータを指定しますtimeRangeFilter
: 取得する範囲を時間で指定します。あまりに膨大だとエラー吐きます。(Instant.MIN
とか)pageSize
: 取得件数ascendingOrder
: 並び順デフォルトがTrueなので、降順でほしいならfalseを指定します。
suspend fun getBodyTemperature(onSuccess: (response: ReadRecordsResponse<BodyTemperature>?) -> Unit, onFailed: (e: Throwable) -> Unit) { val request = ReadRecordsRequest( recordType = BodyTemperature::class, timeRangeFilter = TimeRangeFilter.Companion.after(Instant.now(Clock.systemDefaultZone()).minusSeconds(60 * 60 * 24)), pageSize = 30, ascendingOrder = false ) }
こんな感じ
リポジトリ
所感
- デバイス情報を送れるので、ウェアラブルやハードウェアなどのデータソースを渡せるのがよい
- スマートウォッチなどのウェアラブルをつける要因の1つとして健康意識があるので、親和性高そう
- 体重計や血圧計アプリなどでBluetooth経由で取得したデータをHealthConnectで管理するようなことできそう
- 他のアプリから書き込まれた情報も取得できそうだけど、、どうなんだろう
- 固有のアプリを超えた体験ができるといいなあ
- 栄養とかまでインサートできて、本当にデータの種類が豊富
- Android Oreo 8.1以上の要件はちょっときつい