开始使用 Health Connect

本指南与健康数据共享版本 1.1.0-alpha12 兼容。

本指南介绍了如何开始在应用中使用健康数据共享。

第 1 步:准备健康数据共享应用

健康数据共享应用负责处理您的应用通过健康数据共享 SDK 发送的所有请求。这些请求包括存储数据以及管理数据的读写权限。

对健康数据共享的访问权限取决于手机上安装的 Android 版本。 以下部分概述了如何处理多个近期的 Android 版本。

Android 14

从 Android 14(API 级别 34)开始,健康数据共享是 Android 框架的一部分。此版本的健康数据共享是一个框架模块。 因此,无需进行设置。

Android 13 及更低版本

在 Android 13(API 级别 33)及更低版本中,健康数据共享不是 Android 框架的一部分。因此,您需要从 Google Play 商店安装 健康数据共享应用

如果您已在 Android 13 及更低版本中将应用与健康数据共享集成,并且 想要在 Android 14 上进行迁移,请参阅 从 Android 13 迁移到 Android 14

打开健康数据共享应用

健康数据共享默认不再显示在主屏幕上。您可以通过设置打开 健康数据共享,但路径因 Android 版本而异:

  • 在 Android 14 及更高版本中: 依次前往设置 > 安全和隐私 > 隐私控制 > 健康数据共享 ,或在“设置”中搜索健康数据共享
  • 在 Android 13 及更低版本中: 依次前往设置 > 应用 > 健康数据共享 ,或将健康数据共享添加到快捷设置 菜单。

第 2 步:将健康数据共享 SDK 添加到您的应用

Health Connect SDK 负责使用 Health Connect API 发送请求,以对健康数据共享应用中的数据存储执行操作。

在模块级 build.gradle 文件中添加健康数据共享 SDK 依赖项:

dependencies {
  ...
  implementation "androidx.health.connect:connect-client:1.2.0-alpha04"
  ...
}

如需查看最新版本,请参阅 健康数据共享版本

使用 Canary 版本功能

如需使用 Canary 发布渠道中的功能,请修改模块级 build.gradle 文件中 compileSdk 的版本:

android {
  compileSdkPreview = "CANARY"
}

第 3 步:配置您的应用

以下部分介绍了如何配置应用以与健康数据共享集成。

查看功能的适用范围

向健康数据共享添加新功能后,用户可能不会始终更新其健康数据共享版本。借助 Feature Availability API,您可以检查用户设备上是否提供健康数据共享中的某项功能,并决定要采取的操作。

用于检查功能适用范围的主要函数是 getFeatureStatus(). 此函数会返回整数常量 FEATURE_STATUS_AVAILABLEFEATURE_STATUS_UNAVAILABLE

@OptIn(ExperimentalFeatureAvailabilityApi::class)
fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) {
    if (healthConnectClient
            .features
            .getFeatureStatus(
                HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
            ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
    ) {

        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
}

声明权限

访问健康和健身数据是敏感操作。健康数据共享实现了一个安全层来读取和写入操作,以维护用户信任。

在您的应用中,根据所需的数据类型在 AndroidManifest.xml 文件中声明读写权限,这些权限应与您在 Play 管理中心内声明的访问权限相匹配。

健康数据共享使用标准 Android 权限声明格式。 使用 <uses-permission> 标记分配权限。将它们嵌套在 <manifest> 标记内。

<manifest>
  <uses-permission android:name="android.permission.health.READ_HEART_RATE"/>
  <uses-permission android:name="android.permission.health.WRITE_HEART_RATE"/>
  <uses-permission android:name="android.permission.health.READ_STEPS"/>
  <uses-permission android:name="android.permission.health.WRITE_STEPS"/>

  <application>
  ...
  </application>
</manifest>

如需查看权限及其对应数据类型的完整列表,请参阅 数据类型列表

显示应用的隐私权政策对话框

您的 Android 清单需要包含一个 activity,用于显示应用的隐私权政策,即应用请求的权限的理由,说明如何使用和处理用户数据。

声明此 Activity 以处理 ACTION_SHOW_PERMISSIONS_RATIONALE intent,当用户点击健康数据共享权限屏幕中的隐私权政策 链接时,系统会将此 intent 发送到应用。

...
<application>
  ...
  <!-- For supported versions through Android 13, create an activity to show the rationale
       of Health Connect permissions once users click the privacy policy link. -->
  <activity
      android:name=".PermissionsRationaleActivity"
      android:exported="true">
    <intent-filter>
      <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent-filter>
  </activity>

  <!-- For versions starting Android 14, create an activity alias to show the rationale
       of Health Connect permissions once users click the privacy policy link. -->
  <activity-alias
      android:name="ViewPermissionUsageActivity"
      android:exported="true"
      android:targetActivity=".PermissionsRationaleActivity"
      android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
    <intent-filter>
      <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
      <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
    </intent-filter>
  </activity-alias>
  ...
</application>
...

获取健康数据共享客户端

HealthConnectClient 是健康数据共享 API 的入口点。它允许应用使用健康数据共享应用中的数据存储。它会自动管理它与底层存储层的关联,并处理传出请求和传入响应的所有 IPC 和序列化。

如需获取客户端实例,请先在 Android 清单中声明健康数据共享软件包名称。

<application> ... </application>
...
<!-- Check if Health Connect is installed -->
<queries>
    <package android:name="com.google.android.apps.healthdata" />
</queries>

然后在您的 activity 中,检查是否已安装健康数据共享 使用 getSdkStatus。如果是,请获取 HealthConnectClient 实例。

val availabilityStatus = HealthConnectClient.getSdkStatus(context)
if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
    Box(modifier = modifier.padding(16.dp), contentAlignment = Alignment.Center) {
        Text(
            text = "Health Connect is not available on this device. Please ensure it is installed and updated.",
            style = MaterialTheme.typography.bodyLarge,
            textAlign = TextAlign.Center
        )
    }
    return
}

val healthConnectClient = remember {
    if (availabilityStatus == HealthConnectClient.SDK_AVAILABLE) {
        HealthConnectClient.getOrCreate(context)
    } else {
        null
    }
}

第 4 步:向用户请求权限

创建客户端实例后,您的应用需要向用户请求权限。用户必须能够随时授予或拒绝权限。

为此,请为所需的数据类型创建一组权限。 先确保此集中的权限已在 Android 清单中声明。

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(HeartRateRecord::class),
  HealthPermission.getWritePermission(HeartRateRecord::class),
  HealthPermission.getReadPermission(StepsRecord::class),
  HealthPermission.getWritePermission(StepsRecord::class)
)

使用 getGrantedPermissions 查看您的应用是否已获得所需的权限。如果未获得,请使用 createRequestPermissionResultContract请求 这些权限。这会显示健康数据共享权限屏幕。

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

由于用户可以随时授予或撤消权限,因此您的应用需要在每次使用权限之前检查权限,并处理权限丢失的情况。

引导用户

许多应用都有自定义的新用户引导流程,例如功能教程或征求用户同意。如需让健康数据共享启动您的引导流程,请将以下内容添加到清单中:

<!-- Required to support pre-Android 14 devices with APK Health Connect -->
<activity
  android:name=".OnboardingActivity"
  android:exported="true"
  android:permission="com.google.android.apps.healthdata.permission.START_ONBOARDING">
  <intent-filter>
    <action android:name="androidx.health.ACTION_SHOW_ONBOARDING"/>
  </intent-filter>
</activity>
<!-- Required to support Android 14+ devices with platform Health Connect -->
<activity-alias
  android:name="UAndAboveOnboardingActivity"
  android:exported="true"
  android:targetActivity=".OnboardingActivity"
  android:permission="android.permission.health.START_ONBOARDING">
  <intent-filter>
    <action android:name="android.health.connect.action.SHOW_ONBOARDING" />
  </intent-filter>
</activity-alias>

用户可以直接从健康数据共享应用(而不是从您的应用内)发起与您的应用的连接。如果您的应用除了获得读取或写入数据的权限之外还需要任何其他互动,请提供新用户引导 activity。

请注意,新用户引导 activity 可能会多次启动,例如,如果用户之后撤消了应用的权限,然后重新连接了该应用。

第 5 步:执行操作

现在,一切都已设置完毕,在您的应用中执行读写操作。

您的用户可能会使用其他应用,这些应用会将数据与健康数据共享同步,以便您的应用访问。如果用户尚未设置这些应用以写入健康数据共享 ,您可以使用 Matchmaking API 为用户无缝连接 这些应用。

写入数据

将您的数据构建成一个记录。查看 Health Connect 中支持的数据类型列表。

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata(
        device = Device(type = Device.TYPE_WATCH),
        recordingMethod = Metadata.RECORDING_METHOD_AUTOMATICALLY_RECORDED
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

然后,使用 insertRecords 写入记录。

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata(
        device = Device(type = Device.TYPE_WATCH),
        recordingMethod = Metadata.RECORDING_METHOD_AUTOMATICALLY_RECORDED
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

读取数据

您可以使用 readRecords 逐个读取数据。

val response = healthConnectClient.readRecords(
    ReadRecordsRequest(
        HeartRateRecord::class,
        timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
    )
)
response.records.forEach { record ->
    /* Process records */
}

您还可以使用 aggregate以汇总方式读取数据。

suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long {
    val response = healthConnectClient.aggregate(
        AggregateRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
    return response[StepsRecord.COUNT_TOTAL] ?: 0L
}

视频教程

观看以下视频,详细了解 Health Connect 功能以及实现顺畅集成方面的最佳实践指南:

资源

查看以下资源,这些资源有助于您在日后进行开发。

后续步骤

查看常见工作流 ,了解如何在健康数据共享中执行以下操作: