HealthConnectClient


public interface HealthConnectClient

Known direct subclasses
FakeHealthConnectClient

Fake HealthConnectClient to be used in tests for components that use it as a dependency.


Interface to access health and fitness records.

Summary

Nested types

public static class HealthConnectClient.Companion

Constants

default static final int

The Health Connect SDK APIs are available.

default static final int

The Health Connect SDK is unavailable on this device at the time.

default static final int

The Health Connect SDK APIs are currently unavailable, the provider is either not installed or needs to be updated.

Public methods

abstract @NonNull AggregationResult

Reads AggregateMetrics according to requested read criteria: Records from AggregateRequest.dataOriginFilter and within AggregateRequest.timeRangeFilter.

abstract @NonNull List<@NonNull AggregationResultGroupedByDuration>

Reads AggregateMetrics according to requested read criteria specified in AggregateGroupByDurationRequest.

abstract @NonNull List<@NonNull AggregationResultGroupedByPeriod>

Reads AggregateMetrics according to requested read criteria specified in AggregateGroupByPeriodRequest.

default @NonNull MedicalDataSource

Creates a MedicalDataSource using a CreateMedicalDataSourceRequest.

default void
@ExperimentalPersonalHealthRecordApi
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
deleteMedicalDataSourceWithData(@NonNull String id)

Deletes a MedicalDataSource and all data contained within it.

default void

Deletes a list of MedicalResources by the provided list of MedicalResourceIds.

default void

Deletes MedicalResources based on given filters in request.

abstract void
deleteRecords(
    @NonNull KClass<@NonNull Record> recordType,
    @NonNull TimeRangeFilter timeRangeFilter
)

Deletes any Record of the given recordType in the given timeRangeFilter (automatically filtered to Record belonging to the calling application).

abstract void
deleteRecords(
    @NonNull KClass<@NonNull Record> recordType,
    @NonNull List<@NonNull String> recordIdsList,
    @NonNull List<@NonNull String> clientRecordIdsList
)

Deletes one or more Record by their identifiers.

abstract @NonNull ChangesResponse
getChanges(@NonNull String changesToken)

Retrieves changes in Health Connect, from a specific point in time represented by provided changesToken.

abstract @NonNull String

Retrieves a changes-token, representing a point in time in the underlying Android Health Platform for a given ChangesTokenRequest.

default @NonNull HealthConnectFeatures

Access operations related to feature availability.

default static final @NonNull Intent
getHealthConnectManageDataIntent(
    @NonNull Context context,
    @NonNull String providerPackageName
)

Intent to open Health Connect data management screen on this phone.

default static final @NonNull String

Intent action to open Health Connect settings on this phone.

default @NonNull List<@NonNull MedicalDataSource>

Gets MedicalDataSources for the provided list of ids.

default @NonNull List<@NonNull MedicalDataSource>

Gets the requested MedicalDataSources using GetMedicalDataSourcesRequest.

default static final @NonNull HealthConnectClient
getOrCreate(@NonNull Context context, @NonNull String providerPackageName)

Retrieves an IPC-backed HealthConnectClient instance binding to an available implementation.

abstract @NonNull PermissionController

Access operations related to permissions.

default static final int
getSdkStatus(@NonNull Context context, @NonNull String providerPackageName)

Determines whether the Health Connect SDK is available on this device at the moment.

abstract @NonNull InsertRecordsResponse

Inserts one or more Record and returns newly assigned androidx.health.connect.client.records.metadata.Metadata.id generated.

default @NonNull List<@NonNull MedicalResource>

Reads a collection of MedicalResources given a list of MedicalResourceIds.

default @NonNull ReadMedicalResourcesResponse

Reads MedicalResources by request, either ReadMedicalResourcesInitialRequest or ReadMedicalResourcesPageRequest.

abstract @NonNull ReadRecordResponse<@NonNull T>
<T extends Record> readRecord(
    @NonNull KClass<@NonNull T> recordType,
    @NonNull String recordId
)

Reads one Record point with its recordType and recordId.

abstract @NonNull ReadRecordsResponse<@NonNull T>
<T extends Record> readRecords(@NonNull ReadRecordsRequest<@NonNull T> request)

Retrieves a collection of Records.

abstract void

Updates one or more Record of given UIDs to newly specified values.

default @NonNull List<@NonNull MedicalResource>
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
@ExperimentalPersonalHealthRecordApi
upsertMedicalResources(
    @NonNull List<@NonNull UpsertMedicalResourceRequest> requests
)

Inserts or updates a list of MedicalResources using UpsertMedicalResourceRequests.

Extension functions

default final void
<T extends Record> HealthConnectClientExt.deleteRecords(
    @NonNull HealthConnectClient receiver,
    @NonNull TimeRangeFilter timeRangeFilter
)

Deletes any Record of type T in the given timeRangeFilter (automatically filtered to Record belonging to the calling application).

default final void
<T extends Record> HealthConnectClientExt.deleteRecords(
    @NonNull HealthConnectClient receiver,
    @NonNull List<@NonNull String> recordIdsList,
    @NonNull List<@NonNull String> clientRecordIdsList
)

Deletes one or more Record by their identifiers.

default final @NonNull ReadRecordResponse<@NonNull T>
<T extends Record> HealthConnectClientExt.readRecord(
    @NonNull HealthConnectClient receiver,
    @NonNull String recordId
)

Reads one Record point of type T and with the specified recordId.

Constants

SDK_AVAILABLE

Added in 1.1.0-rc01
default static final int SDK_AVAILABLE = 3

The Health Connect SDK APIs are available.

Apps can subsequently call getOrCreate to get an instance of HealthConnectClient.

SDK_UNAVAILABLE

Added in 1.1.0-rc01
default static final int SDK_UNAVAILABLE = 1

The Health Connect SDK is unavailable on this device at the time. This can be due to the device running a lower than required Android Version.

Apps should hide any integration points to Health Connect in this case.

SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED

Added in 1.1.0-rc01
default static final int SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED = 2

The Health Connect SDK APIs are currently unavailable, the provider is either not installed or needs to be updated.

Apps may choose to redirect to package installers to find a suitable APK.

Public methods

aggregate

abstract @NonNull AggregationResult aggregate(@NonNull AggregateRequest request)

Reads AggregateMetrics according to requested read criteria: Records from AggregateRequest.dataOriginFilter and within AggregateRequest.timeRangeFilter.

import androidx.health.connect.client.records.DistanceRecord
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter

val response =
    healthConnectClient.aggregate(
        AggregateRequest(
            metrics = setOf(DistanceRecord.DISTANCE_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
// The result may be null if no data is available in the time range.
val distanceTotalInMeters = response[DistanceRecord.DISTANCE_TOTAL]?.inMeters

Example code to retrieve statistical aggregates like maximum or minimum heart rate:

import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter

val response =
    healthConnectClient.aggregate(
        AggregateRequest(
            setOf(HeartRateRecord.BPM_MAX, HeartRateRecord.BPM_MIN),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
// The result may be null if no data is available in the time range.
val minimumHeartRate = response[HeartRateRecord.BPM_MIN]
val maximumHeartRate = response[HeartRateRecord.BPM_MAX]
Parameters
@NonNull AggregateRequest request

AggregateRequest object specifying AggregateMetrics to aggregate and other filters.

Returns
@NonNull AggregationResult

the AggregationResult that contains aggregated values.

Throws
android.os.RemoteException

For any IPC transportation failures.

java.lang.SecurityException

For requests with unpermitted access.

java.io.IOException

For any disk I/O issues.

Example code to aggregate cumulative data like distance:

aggregateGroupByDuration

abstract @NonNull List<@NonNull AggregationResultGroupedByDurationaggregateGroupByDuration(
    @NonNull AggregateGroupByDurationRequest request
)

Reads AggregateMetrics according to requested read criteria specified in AggregateGroupByDurationRequest.

This method is similar to aggregate but instead of returning one AggregationResult for the entire query's time interval, it returns a list of AggregationResultGroupedByDuration, with each row keyed by start and end time. For example: steps for today bucketed by hours.

An AggregationResultGroupedByDuration is returned only if there are Record to aggregate within start and end time of the row.

import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.request.AggregateGroupByDurationRequest
import androidx.health.connect.client.time.TimeRangeFilter

val response =
    healthConnectClient.aggregateGroupByDuration(
        AggregateGroupByDurationRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            timeRangeSlicer = Duration.ofMinutes(1)
        )
    )
for (monthlyResult in response) {
    // The result may be null if no data is available in the time range.
    val totalSteps = monthlyResult.result[StepsRecord.COUNT_TOTAL]
}
Parameters
@NonNull AggregateGroupByDurationRequest request

AggregateGroupByDurationRequest object specifying AggregateMetrics to aggregate and other filters.

Returns
@NonNull List<@NonNull AggregationResultGroupedByDuration>

a list of AggregationResultGroupedByDurations, each contains aggregated values and start/end time of the row. The list is sorted by time in ascending order.

Throws
android.os.RemoteException

For any IPC transportation failures.

java.lang.SecurityException

For requests with unpermitted access.

java.io.IOException

For any disk I/O issues.

Example code to retrieve cumulative step count for each minute within provided time range:

aggregateGroupByPeriod

abstract @NonNull List<@NonNull AggregationResultGroupedByPeriodaggregateGroupByPeriod(@NonNull AggregateGroupByPeriodRequest request)

Reads AggregateMetrics according to requested read criteria specified in AggregateGroupByPeriodRequest.

This method is similar to aggregate but instead of returning one AggregationResult for the entire query's time interval, it returns a list of AggregationResultGroupedByPeriod, with each row keyed by start and end time. For example: steps for this month bucketed by day.

An AggregationResultGroupedByPeriod is returned only if there are Record to aggregate within start and end time of the row.

import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
import androidx.health.connect.client.time.TimeRangeFilter

val response =
    healthConnectClient.aggregateGroupByPeriod(
        AggregateGroupByPeriodRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            timeRangeSlicer = Period.ofMonths(1)
        )
    )
for (monthlyResult in response) {
    // The result may be null if no data is available in the time range.
    val totalSteps = monthlyResult.result[StepsRecord.COUNT_TOTAL]
}
Parameters
@NonNull AggregateGroupByPeriodRequest request

AggregateGroupByPeriodRequest object specifying AggregateMetrics to aggregate and other filters.

Returns
@NonNull List<@NonNull AggregationResultGroupedByPeriod>

a list of AggregationResultGroupedByPeriods, each contains aggregated values and start/end time of the row. The list is sorted by time in ascending order.

Throws
android.os.RemoteException

For any IPC transportation failures.

java.lang.SecurityException

For requests with unpermitted access.

java.io.IOException

For any disk I/O issues.

Example code to retrieve cumulative step count for each month within provided time range:

createMedicalDataSource

@ExperimentalPersonalHealthRecordApi
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
default @NonNull MedicalDataSource createMedicalDataSource(@NonNull CreateMedicalDataSourceRequest request)

Creates a MedicalDataSource using a CreateMedicalDataSourceRequest.

Regarding permissions:

Medical data is represented using the Fast Healthcare Interoperability Resources (FHIR) standard.

A MedicalDataSource needs to be created before any MedicalResources for that source can be inserted. Separate MedicalDataSources should be created for medical records coming from different sources (e.g. different FHIR endpoints, different healthcare systems), unless the data has been reconciled and all records have a unique combination of resource type and resource id.

The CreateMedicalDataSourceRequest.displayName must be unique across all medical data sources created by an app, otherwise an IllegalArgumentException will be thrown. See CreateMedicalDataSourceRequest.fhirBaseUri for more details on the FHIR base URI. The data source can not be updated after creation.

This feature is dependent on the version of HealthConnect installed on the device. To check if it's available call HealthConnectFeatures.getFeatureStatus and pass FEATURE_PERSONAL_HEALTH_RECORD as an argument. An UnsupportedOperationException would be thrown if the feature is not available.

import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_PERSONAL_HEALTH_RECORD
import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_STATUS_AVAILABLE
import androidx.health.connect.client.records.FhirVersion
import androidx.health.connect.client.records.MedicalDataSource
import androidx.health.connect.client.request.CreateMedicalDataSourceRequest

// Ensure `FEATURE_PERSONAL_HEALTH_RECORD` is available before calling PHR apis
if (
    healthConnectClient.features.getFeatureStatus(FEATURE_PERSONAL_HEALTH_RECORD) !=
        FEATURE_STATUS_AVAILABLE
) {
    return
}

// Create a `MedicalDataSource`
// Note that `displayName` must be unique across `MedicalDataSource`s
val medicalDataSource: MedicalDataSource =
    healthConnectClient.createMedicalDataSource(
        CreateMedicalDataSourceRequest(
            fhirBaseUri = Uri.parse("https://fhir.com/oauth/api/FHIR/R4/"),
            displayName = "Test Data Source",
            fhirVersion = FhirVersion(4, 0, 1)
        )
    )
Parameters
@NonNull CreateMedicalDataSourceRequest request

request containing details of the MedicalDataSource to be created

deleteMedicalDataSourceWithData

Added in 1.1.0-rc01
@ExperimentalPersonalHealthRecordApi
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
default void deleteMedicalDataSourceWithData(@NonNull String id)

Deletes a MedicalDataSource and all data contained within it.

Regarding permissions:

Medical data is represented using the Fast Healthcare Interoperability Resources (FHIR) standard.

This feature is dependent on the version of HealthConnect installed on the device. To check if it's available call HealthConnectFeatures.getFeatureStatus and pass FEATURE_PERSONAL_HEALTH_RECORD as an argument. An UnsupportedOperationException would be thrown if the feature is not available.

import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_PERSONAL_HEALTH_RECORD
import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_STATUS_AVAILABLE
import androidx.health.connect.client.records.FhirVersion
import androidx.health.connect.client.records.MedicalDataSource
import androidx.health.connect.client.request.CreateMedicalDataSourceRequest

// Ensure `FEATURE_PERSONAL_HEALTH_RECORD` is available before calling PHR apis
if (
    healthConnectClient.features.getFeatureStatus(FEATURE_PERSONAL_HEALTH_RECORD) !=
        FEATURE_STATUS_AVAILABLE
) {
    return
}

// Get or creates a `MedicalDataSource`
// Each `MedicalDataSource` is assigned an `id` by the system on creation
val medicalDataSource: MedicalDataSource =
    healthConnectClient.createMedicalDataSource(
        CreateMedicalDataSourceRequest(
            fhirBaseUri = Uri.parse("https://fhir.com/oauth/api/FHIR/R4/"),
            displayName = "Test Data Source",
            fhirVersion = FhirVersion(4, 0, 1)
        )
    )

// Delete the `MedicalDataSource` that has the specified `id`
healthConnectClient.deleteMedicalDataSourceWithData(medicalDataSource.id)
Parameters
@NonNull String id

The id of the data source to delete.

Throws
kotlin.IllegalArgumentException

if id is invalid, does not exist, or owned by another app.

deleteMedicalResources

Added in 1.1.0-rc01
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
@ExperimentalPersonalHealthRecordApi
default void deleteMedicalResources(@NonNull List<@NonNull MedicalResourceId> ids)

Deletes a list of MedicalResources by the provided list of MedicalResourceIds.

  • If any ID in ids is invalid, the API will throw an IllegalArgumentException, and nothing will be deleted.

  • If any ID in ids does not exist, that ID will be ignored, while deletion on other IDs will be performed.

Regarding permissions:

  • Caller must hold PERMISSION_WRITE_MEDICAL_DATA in order to call this API, even then, it can only delete its own data. If any of the items in ids belongs to another app, they will be ignored.

  • Deletes are permitted in the foreground or background.

This feature is dependent on the version of HealthConnect installed on the device. To check if it's available call HealthConnectFeatures.getFeatureStatus and pass FEATURE_PERSONAL_HEALTH_RECORD as an argument. An UnsupportedOperationException would be thrown if the feature is not available.

import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_PERSONAL_HEALTH_RECORD
import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_STATUS_AVAILABLE
import androidx.health.connect.client.records.FhirVersion
import androidx.health.connect.client.records.MedicalDataSource
import androidx.health.connect.client.records.MedicalResource
import androidx.health.connect.client.records.MedicalResourceId
import androidx.health.connect.client.request.CreateMedicalDataSourceRequest
import androidx.health.connect.client.request.UpsertMedicalResourceRequest

// Ensure `FEATURE_PERSONAL_HEALTH_RECORD` is available before calling PHR apis
if (
    healthConnectClient.features.getFeatureStatus(FEATURE_PERSONAL_HEALTH_RECORD) !=
        FEATURE_STATUS_AVAILABLE
) {
    return
}

// Get or create a `MedicalDataSource`
val medicalDataSource: MedicalDataSource =
    healthConnectClient.createMedicalDataSource(
        CreateMedicalDataSourceRequest(
            fhirBaseUri = Uri.parse("https://fhir.com/oauth/api/FHIR/R4/"),
            displayName = "Test Data Source",
            fhirVersion = FhirVersion(4, 0, 1)
        )
    )

// Insert `MedicalResource`s into the `MedicalDataSource`
val medicalResources: List<MedicalResource> =
    healthConnectClient.upsertMedicalResources(
        listOf(
            UpsertMedicalResourceRequest(
                medicalDataSource.id,
                medicalDataSource.fhirVersion,
                medicationJsonToInsert // a valid FHIR json string
            )
        )
    )

// Delete `MedicalResource`s matching the specified `dataSourceId`, `type` and `fhirResourceId`
healthConnectClient.deleteMedicalResources(
    medicalResources.map { medicalResource: MedicalResource ->
        MedicalResourceId(
            dataSourceId = medicalDataSource.id,
            fhirResourceType = medicalResource.id.fhirResourceType,
            fhirResourceId = medicalResource.id.fhirResourceId
        )
    }
)
Parameters
@NonNull List<@NonNull MedicalResourceId> ids

The ids to delete.

deleteMedicalResources

Added in 1.1.0-rc01
@RequiresPermission(value = "android.permission.health.WRITE_MEDICAL_DATA")
@ExperimentalPersonalHealthRecordApi
default void deleteMedicalResources(@NonNull DeleteMedicalResourcesRequest request)

Deletes MedicalResources based on given filters in request.

Only MedicalResources inserted by the calling app will be deleted. If the request matches any other MedicalResources, these will be ignored.

Regarding permissions:

This feature is dependent on the version of HealthConnect installed on the device. To check if it's available call HealthConnectFeatures.getFeatureStatus and pass FEATURE_PERSONAL_HEALTH_RECORD as an argument. An UnsupportedOperationException would be thrown if the feature is not available.

import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_PERSONAL_HEALTH_RECORD
import androidx.health.connect.client.HealthConnectFeatures.Companion.FEATURE_STATUS_AVAILABLE
import androidx.health.connect.client.records.FhirVersion
import androidx.health.connect.client.records.MedicalDataSource
import androidx.health.connect.client.records.MedicalResource
import androidx.health.connect.client.records.MedicalResource.Companion.MEDICAL_RESOURCE_TYPE_MEDICATIONS
import androidx.health.connect.client.request.CreateMedicalDataSourceRequest
import androidx.health.connect.client.request.DeleteMedicalResourcesRequest
import androidx.health.connect.client.request.UpsertMedicalResourceRequest

// Ensure `FEATURE_PERSONAL_HEALTH_RECORD` is available before calling PHR apis
if (
    healthConnectClient.features.getFeatureStatus(FEATURE_PERSONAL_HEALTH_RECORD) !=
        FEATURE_STATUS_AVAILABLE
) {
    return
}

// Get or create a `MedicalDataSource`
val medicalDataSource: