
Health Connect Android API
Learn how to use the Health Connect Android API to create an app that reads and writes health data and manages health permissions. By Zahid Rasheed.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Health Connect Android API
15 mins
- Getting Started
- Setting up an Emulator to Test the Health Connect API
- Downloading and Exploring the Starter Project
- Introducing Health Connect
- Privacy Controls
- Storage
- Data Types
- Health Connect APK
- Handling Dependencies
- Handling Permissions and Privacy Policy
- Writing Data
- Inserting Records
- Build and Run
- Reading Data
- Reading Data through a ReadRecordsRequest
- Reading Data through an AggregateRequest
- Build and Run
- Where to Go From Here?
Health Connect is an Android API and Platform. For developers, it provides a single interface for handling users’ health data. For users, it’s a central place to get an overview of health data and permissions granted to other apps.
In this tutorial, you’ll learn about Health Connect by making a sample app — fitLogger. In doing so, you’ll learn the following in the context of the Health Connect Android API:
- Handling permissions
- Writing data
- Reading data
Getting Started
Setting up an Emulator to Test the Health Connect API
Unless you’re using a real device to build and run this app, you’ll need an emulator with Play Store support. To create an emulator, go to Tools ▸ Device Manager and click Create device. From the list of devices, choose a device with an icon in the Play Store column.
During the next steps select a system image, choose an AVD name and click Finish.
Downloading and Exploring the Starter Project
Use the Download Materials button at the top or bottom of this tutorial to download the starter project. Open the project in Android Studio Bumblebee (2021.1.1) or later. Go to Run ▸ Run ´app´.
To keep the focus on Health Connect, the required layout for this tutorial is created in the activity_main.xml file. You’ll connect this layout with the actual functionality to read and write the health data.
Introducing Health Connect
Many health and fitness apps run on Android. Google Fit is a similar app made by Google. These apps can collect a lot of data and handle permissions. Users can use one app to store health information and another for fitness tracking. With data spread among several apps, users must go into many apps to get an overview. Also, privacy can be a worry when data is on several apps.
Health Connect is an API and a platform. As an API, it helps developers use a single interface. As a platform, it helps users have an overview of everything in one place.
Health Connect provides the following features to developers and users:
Privacy Controls
Android OS ensures client apps request permissions before accessing data or hardware on the device. Health Connect provides built-in permission controls. Developers request permissions through the API, and users can see the Health Connect app to review permission requests and grant or deny permissions.
Users can use the Health Connect app to determine which apps have permission to access health data. If needed, they can revoke those permissions through the app. Health Connect ensures that client apps can only read data when the app is running in the foreground.
Storage
Health Connect provides on-device storage, so all the data is in a central place. As a developer, you can save the data using the API and retrieve the data stored by another app.
A user can use the platform to get an overview of health and fitness data. The platform can also delete data.
Data Types
Health Connect offers an extensive range of data types to let users track types of health- and fitness-related data. Various apps can contribute or consume data in the Android ecosystem by having unified data types.
Key data categories:
- Activity: This captures any activity by a user, including running, swimming, sleeping and meditation.
- Body Measurement: This is common data related to the body, including height, weight and BMR (Basal Metabolic Rate).
- Cycle Tracking: Data recorded here include menstrual cycles and other related data points.
- Nutrition: Hydration and nutrition data types, including water, calories, sugar and magnesium.
- Sleep: Interval data related to a user’s length and type of sleep.
- Vitals: Essential information about the user’s general health, including blood glucose, body temperature and blood oxygen saturation is recorded under this category.
Health Connect APK
The Health Connect APK needs to be available on the client’s device. It contains the Permissions Management and Data Management components. It will handle requests sent by any application using the Health Connect SDK.
Open the Play Store on your device or emulator. If you’re using a new emulator, sign into your Google account. Then, search for Health Connect by Android and install the app.
Handling Dependencies
Now that you have an overview of Health Connect, it’s coding time!
Add the following dependency at the bottom of the module’s build.gradle file:
implementation 'androidx.health:health-connect-client:1.0.0-alpha03'
By including this SDK in your application, you can use the Health Connect API. Click the build button to download dependencies and recompile the project.
Handling Permissions and Privacy Policy
Before you can read or write data, you need to declare all the permissions your app will use. Create a new resource file named health_permissions.xml under res/values. Add the following permissions:
<resources>
<array name="health_permissions">
<item>androidx.health.permission.Steps.READ</item>
<item>androidx.health.permission.Steps.WRITE</item>
<item>androidx.health.permission.TotalCaloriesBurned.READ</item>
<item>androidx.health.permission.TotalCaloriesBurned.WRITE</item>
</array>
</resources>
Each item represents a permission your app will use.
Health Connect needs the client app to define the policy on handling privacy and data.
Go to File ▸ New ▸ Activity ▸ Empty Activity. Enter PrivacyPolicyActivity for Activity Name and click Finish.
Open activity_privacy_policy.xml from the layout directory and add the following code inside the ConstraintLayout
tag:
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="16sp"
android:layout_margin="24dp"
android:text="@string/privacy_policy" />
Add the following in the strings.xml file:
<string name="privacy_policy">Lorem ipsum dolor sit amet, consectetur adipiscing elit....</string>
Now, in AndroidManifest.xml, replace the auto-generated element for PrivacyPolicyActivity
with the following:
<activity
android:exported="true"
android:name=".PrivacyPolicyActivity">
<intent-filter>
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
</intent-filter>
<meta-data android:name="health_permissions" android:resource="@array/health_permissions" />
</activity>
Here’s what’s happening:
- You created a new activity
PrivacyPolicyActivity
. - In the layout file for the activity, you defined a dummy privacy policy.
- You then declared the activity in the manifest so your app can handle this intent and display a privacy policy explaining how users’ data is handled.
Now, add the following functions after onCreate
within MainActivity.kt:
private fun checkPermissionsAndRun() {
// 1
val client = HealthConnectClient.getOrCreate(this)
// 2
val permissionsSet = setOf(
Permission.createWritePermission(StepsRecord::class),
Permission.createReadPermission(StepsRecord::class),
Permission.createWritePermission(TotalCaloriesBurnedRecord::class),
Permission.createReadPermission(TotalCaloriesBurnedRecord::class),
)
// 3
// Create the permissions launcher.
val requestPermissionActivityContract = client
.permissionController
.createRequestPermissionActivityContract()
val requestPermissions = registerForActivityResult(
requestPermissionActivityContract
) { granted ->
if (granted.containsAll(permissionsSet)) {
// Permissions successfully granted
lifecycleScope.launch {
onPermissionAvailable(client)
}
} else {
Toast.makeText(
this, "Permissions not granted", Toast.LENGTH_SHORT
).show()
}
}
// 4
lifecycleScope.launch {
val granted = client.permissionController
.getGrantedPermissions(permissionsSet)
if (granted.containsAll(permissionsSet)) {
// Permissions already granted
onPermissionAvailable(client)
} else {
// Permissions not granted, request permissions.
requestPermissions.launch(permissionsSet)
}
}
}
private suspend fun onPermissionAvailable(client: HealthConnectClient) {
// todo: read data
}
androidx.health.connect.client.permission
.Here’s what’s happening in checkPermissionsAndRun
:
- You first of all get a hold of a
HealthConnectClient
object.getOrCreate
creates a new instance or returns an existing one if it’s available. - Create a set of permissions with required data types to request permissions within your application. Permissions in these sets need to be declared in the health_permissions resource array.
- Create a request permission launcher. On launch, users will be prompted for permissions declared in the health_permissions resource array.
- Finally, through
HealthConnectClient
, you check whether you have the required permissions. If permissions aren’t available, you request permissions throughrequestPermissions
launcher.
onPermissionAvailable
is called when you have all required permissions. At this point, it’s possible to read or write data.
Add the following after the closing application
tag within AndroidManifest.xml:
<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
This checks whether Health Connect APK is installed.
Finally, inside onCreate
in MainActivity.kt, replace // Your code
with the following code:
if (HealthConnectClient.isAvailable(this)) {
// Health Connect is available
checkPermissionsAndRun()
} else {
Toast.makeText(
this, "Health Connect is not available", Toast.LENGTH_SHORT
).show()
}
Here’s what’s happening:
- Through
HealthConnectClient
, you check whether Health Connect is available. - If it is available, you check required permissions.
You show a Toast
to the user, if Health Connect isn’t available.
That’s it! You’ve integrated Health Connect in the app and can request all required permissions. Give it a try by running the app.
Writing Data
Inserting Records
Add the following code after onPermissionAvailable
.
private fun insertData(client: HealthConnectClient, steps: Long, caloriesBurned: Double) {
// 1
val startTime = ZonedDateTime.now().minusSeconds(1).toInstant()
val endTime = ZonedDateTime.now().toInstant()
// 2
val records = listOf(
StepsRecord(
count = steps,
startTime = startTime,
endTime = endTime,
startZoneOffset = null,
endZoneOffset = null,
),
TotalCaloriesBurnedRecord(
energy = Energy.calories(caloriesBurned),
startTime = startTime,
endTime = endTime,
startZoneOffset = null,
endZoneOffset = null,
)
)
// 3
lifecycleScope.launch {
val insertRecords = client.insertRecords(records)
if (insertRecords.recordUidsList.isNotEmpty()) {
runOnUiThread{
Toast.makeText(
this@MainActivity,
"Records inserted successfully",
Toast.LENGTH_SHORT
).show()
}
}
}
}
With this update,
- You’re creating a time range with a start and end. You record the data in a small interval. This way you can insert the data multiple times in a day.
- Followed by another list that contains
StepsRecord
andTotalCaloriesBurnedRecord
records. - Then finally, you insert the created record through the
HealthConnectClient
instance.recordUidsList
contains theuid
s of inserted records. When the list isn’t empty, you’re showing a success message to the user.
Now, at the end of onCreate
in the MainActivity.kt, add the following code:
val stepsEditText = findViewById<EditText>(R.id.stepsEditText)
val caloriesEditText = findViewById<EditText>(R.id.caloriesEditText)
findViewById<Button>(R.id.submit).setOnClickListener {
val steps = stepsEditText.text.toString().toLong()
val calories = caloriesEditText.text.toString().toDouble()
val client = HealthConnectClient.getOrCreate(this)
insertData(client, steps, calories)
// clear input fields after insertion and close the keyboard
stepsEditText.text.clear()
caloriesEditText.text.clear()
caloriesEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
}
In the code above, when a user taps Button, you read input values and save them with insertData()
. You then clear input fields and close the keyboard.
Build and Run
That’s all you need to do to write data through the Health Connect API. Run the project, input values and tap the button.
Reading Data
You can read data in two ways using HealthConnectClient.
-
ReadRecordsRequest
: Read records determined by time range and other filters. You’ll use this method to read the daily steps count and calories intake. -
AggregateRequest
: Read aggregations for a givenAggregateMetric
. You’ll use this method to read monthly step counts and caloric intakes.
Reading Data through a ReadRecordsRequest
In MainActivity.kt, add the following after insertData()
:
private suspend fun readDailyRecords(client: HealthConnectClient) {
// 1
val today = ZonedDateTime.now()
val startOfDay = today.truncatedTo(ChronoUnit.DAYS)
val timeRangeFilter = TimeRangeFilter.between(
startOfDay.toLocalDateTime(),
today.toLocalDateTime()
)
// 2
val stepsRecordRequest = ReadRecordsRequest(StepsRecord::class, timeRangeFilter)
val numberOfStepsToday = client.readRecords(stepsRecordRequest)
.records
.sumOf { it.count }
val stepsTextView = findViewById<TextView>(R.id.stepsTodayValue)
stepsTextView.text = numberOfStepsToday.toString()
// 3
val caloriesRecordRequest = ReadRecordsRequest(
TotalCaloriesBurnedRecord::class,
timeRangeFilter
)
val caloriesBurnedToday = client.readRecords(caloriesRecordRequest)
.records
.sumOf { it.energy.inCalories }
val caloriesTextView = findViewById<TextView>(R.id.caloriesTodayValue)
caloriesTextView.text = caloriesBurnedToday.toString()
}
And now the breakdown:
- You create a
TimeRangeFilter
from the start of the day until now. - You then create a
ReadRecordRequest
forStepsRecord
. Through theHealthConnectClient
instance, you read records and get the sum. You get the sum because there can be many records for steps taken today. Finally, you display the daily steps count. - This is the same as Step 2, but the
ReadRecordsRequest
is forTotalCaloriesBurnedRecord
.
Reading Data through an AggregateRequest
Add the following method at the bottom of MainActivity:
private suspend fun readAggregatedData(client: HealthConnectClient) {
// 1
val today = ZonedDateTime.now()
val startOfDayOfThisMonth = today.withDayOfMonth(1)
.truncatedTo(ChronoUnit.DAYS)
val elapsedDaysInMonth = Duration.between(startOfDayOfThisMonth, today)
.toDays() + 1
val timeRangeFilter = TimeRangeFilter.between(
startOfDayOfThisMonth.toInstant(),
today.toInstant()
)
// 2
val data = client.aggregate(
AggregateRequest(
metrics = setOf(
StepsRecord.COUNT_TOTAL,
TotalCaloriesBurnedRecord.ENERGY_TOTAL
),
timeRangeFilter = timeRangeFilter,
)
)
// 3
val steps = data[StepsRecord.COUNT_TOTAL] ?: 0
val averageSteps = steps / elapsedDaysInMonth
val stepsAverageTextView = findViewById<TextView>(R.id.stepsAverageValue)
stepsAverageTextView.text = averageSteps.toString()
// 4
val caloriesBurned = data[TotalCaloriesBurnedRecord.ENERGY_TOTAL]
?.inCalories ?: 0.0
val averageCaloriesBurned = caloriesBurned / elapsedDaysInMonth
val caloriesAverageTextView = findViewById<TextView>(
R.id.caloriesAverageValue
)
caloriesAverageTextView.text = getString(R.string.format_calories_average)
.format(averageCaloriesBurned)
}
java.time
.Here’s what’s happening:
- You’re creating a
TimeRangeFilter
from the start of the month until now. Also, you’re calculating the days elapsed in the month so you can calculate the average. - You’re making an
aggregate
request throughHealthConnectClient
with a set of measurements to get the total steps and calories within a specific time range. The benefit of aggregated data is it includes basic aggregations or aggregating data into buckets. - You’re calculating
averageSteps
and updating the layout. - You’re calculating
averageCaloriesBurned
and updating the layout. For a better UI, you’re rounding the calorie values up to two decimals.
Add the following in the strings.xml file.
<string name="format_calories_average">%.2f</string>
You’re almost there. You now have functions that read data, but you need to connect a few final dots.
Add another method in the MainActivity.kt:
private suspend fun readData(client: HealthConnectClient) {
readDailyRecords(client)
readAggregatedData(client)
}
This helper function commands both functions you created above to read data.
Now, inside onPermissionAvailable
, replace // todo: read data
with the following.
readData(client)
By doing so, you can read the data and update the layout as soon as you have permissions available.
Finally, add the following at the end of the lifecycleScope.launch {
block, inside insertData
:
readData(client)
This will ensure you show updated data after a user inserts new data.
Build and Run
You’re done! Build and run the app to see the result. You can now write data and also see your existing data.
Where to Go From Here?
Congratulations! You’ve learned about Health Connect by making a simple app. Now you have one less excuse to get fitter and healthier. Use the Download Materials button at the top or bottom of this article to download the final project.
You can take a few steps to improve your app:
- The app can also track the exact start and end time and write data through sessions.
- You created this sample app with a simple UI. To make it a really beneficial app for a user, follow the Health Connect UX developer guidance.
- Because users can use the Health Connect app to revoke permissions at any time, it’s important to have proper exception handling.
- To keep your app compliant with Android policy, take a look at the Health Connect Policy Requirement FAQs.
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development — plans start at just $19.99/month! Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.
Learn more