Well being Join Android API | Kodeco, the brand new raywenderlich.com


Learn to use the Well being Join Android API to create an app that reads and writes well being information and manages well being permissions.

Well being Join is an Android API and Platform. For builders, it gives a single interface for dealing with customers’ well being information. For customers, it’s a central place to get an summary of well being information and permissions granted to different apps.

On this tutorial, you’ll study Well being Join by making a pattern app — fitLogger. In doing so, you’ll be taught the next within the context of the Well being Join Android API:

  • Dealing with permissions
  • Writing information
  • Studying information

Getting Began

Establishing an Emulator to Check the Well being Join API

Until you’re utilizing an actual gadget to construct and run this app, you’ll want an emulator with Play Retailer help. To create an emulator, go to Instruments ▸ System Supervisor and click on Create gadget. From the checklist of units, select a tool with an icon within the Play Retailer column.

A screenshot of AVD Manager

Throughout the subsequent steps choose a system picture, select an AVD identify and click on End.

Downloading and Exploring the Starter Undertaking

Use the Obtain Supplies button on the high or backside of this tutorial to obtain the starter undertaking. Open the undertaking in Android Studio Bumblebee (2021.1.1) or later. Go to Run ▸ Run ´app´.

A screenshot of the fitLogger sample application for Android Health Connect

To maintain the concentrate on Well being Join, the required format for this tutorial is created within the activity_main.xml file. You’ll join this format with the precise performance to learn and write the well being information.

Introducing Well being Join

Many well being and health apps run on Android. Google Match is an analogous app made by Google. These apps can accumulate lots of information and deal with permissions. Customers can use one app to retailer well being info and one other for health monitoring. With information unfold amongst a number of apps, customers should go into many apps to get an summary. Additionally, privateness generally is a fear when information is on a number of apps.

Well being Join is an API and a platform. As an API, it helps builders use a single interface. As a platform, it helps customers have an summary of all the things in a single place.

A diagram showing how Android Health Connect works as both a platform and an API

Well being Join gives the next options to builders and customers:

Privateness Controls

Android OS ensures consumer apps request permissions earlier than accessing information or {hardware} on the gadget. Well being Join gives built-in permission controls. Builders request permissions via the API, and customers can see the Well being Join app to overview permission requests and grant or deny permissions.

Customers can use the Well being Join app to find out which apps have permission to entry well being information. If wanted, they’ll revoke these permissions via the app. Well being Join ensures that consumer apps can solely learn information when the app is working within the foreground.

Storage

Well being Join gives on-device storage, so all the info is in a central place. As a developer, it can save you the info utilizing the API and retrieve the info saved by one other app.

A consumer can use the platform to get an summary of well being and health information. The platform also can delete information.

Knowledge Varieties

Well being Join gives an intensive vary of knowledge sorts to let customers monitor varieties of health- and fitness-related information. Varied apps can contribute or devour information within the Android ecosystem by having unified information sorts.

Key information classes:

  • Exercise: This captures any exercise by a consumer, together with working, swimming, sleeping and meditation.
  • Physique Measurement: That is widespread information associated to the physique, together with top, weight and BMR (Basal Metabolic Fee).
  • Cycle Monitoring: Knowledge recorded right here embody menstrual cycles and different associated information factors.
  • Vitamin: Hydration and diet information sorts, together with water, energy, sugar and magnesium.
  • Sleep: Interval information associated to a consumer’s size and kind of sleep.
  • Vitals: Important details about the consumer’s basic well being, together with blood glucose, physique temperature and blood oxygen saturation is recorded underneath this class.

Well being Join APK

The Well being Join APK must be out there on the consumer’s gadget. It incorporates the Permissions Administration and Knowledge Administration parts. It can deal with requests despatched by any utility utilizing the Well being Join SDK.

Open the Play Retailer in your gadget or emulator. If you happen to’re utilizing a brand new emulator, signal into your Google account. Then, seek for Well being Join by Android and set up the app.

An animation showing how to install Android Health Connect application from the Google Play Store

Dealing with Dependencies

Now that you’ve got an summary of Well being Join, it’s coding time!

Add the next dependency on the backside of the module’s construct.gradle file:


implementation 'androidx.well being:health-connect-client:1.0.0-alpha03'

By together with this SDK in your utility, you should utilize the Well being Join API. Click on the construct button to obtain dependencies and recompile the undertaking.

Dealing with Permissions and Privateness Coverage

Earlier than you’ll be able to learn or write information, you could declare all of the permissions your app will use. Create a brand new useful resource file named health_permissions.xml underneath res/values. Add the next permissions:


<assets>
 <array identify="health_permissions">
   <merchandise>androidx.well being.permission.Steps.READ</merchandise>
   <merchandise>androidx.well being.permission.Steps.WRITE</merchandise>
   <merchandise>androidx.well being.permission.TotalCaloriesBurned.READ</merchandise>
   <merchandise>androidx.well being.permission.TotalCaloriesBurned.WRITE</merchandise>
 </array>
</assets>

Every merchandise represents a permission your app will use.

Well being Join wants the consumer app to outline the coverage on dealing with privateness and information.

Go to File ▸ New ▸ Exercise ▸ Empty Exercise. Enter PrivacyPolicyActivity for Exercise Title and click on End.

Open activity_privacy_policy.xml from the format listing and add the next code contained in the ConstraintLayout tag:


<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textSize="16sp"
    android:layout_margin="24dp"
    android:textual content="@string/privacy_policy" />

Add the next within the strings.xml file:


<string identify="privacy_policy">Lorem ipsum dolor sit amet, consectetur adipiscing elit....</string>

Now, in AndroidManifest.xml, substitute the auto-generated ingredient for PrivacyPolicyActivity with the next:


<exercise
 android:exported="true"
 android:identify=".PrivacyPolicyActivity">
 <intent-filter>
   <motion android:identify="androidx.well being.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
 </intent-filter>
 <meta-data android:identify="health_permissions" android:useful resource="@array/health_permissions" />
</exercise>

Right here’s what’s occurring:

  1. You created a brand new exercise PrivacyPolicyActivity.
  2. Within the format file for the exercise, you outlined a dummy privateness coverage.
  3. You then declared the exercise within the manifest so your app can deal with this intent and show a privateness coverage explaining how customers’ information is dealt with.

Now, add the next capabilities after onCreate inside MainActivity.kt:


personal enjoyable checkPermissionsAndRun() {
  // 1
  val consumer = 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 = consumer
    .permissionController
    .createRequestPermissionActivityContract()

  val requestPermissions = registerForActivityResult(
    requestPermissionActivityContract
  ) { granted ->
    if (granted.containsAll(permissionsSet)) {
      // Permissions efficiently granted
      lifecycleScope.launch {
        onPermissionAvailable(consumer)
      }
    } else {
      Toast.makeText(
        this, "Permissions not granted", Toast.LENGTH_SHORT
      ).present()
    }
  }

  // 4
  lifecycleScope.launch {
    val granted = consumer.permissionController
      .getGrantedPermissions(permissionsSet)
    if (granted.containsAll(permissionsSet)) {
      // Permissions already granted
      onPermissionAvailable(consumer)
    } else {
      // Permissions not granted, request permissions.
      requestPermissions.launch(permissionsSet)
    }
  }
}

personal droop enjoyable onPermissionAvailable(consumer: HealthConnectClient) {
 // todo: learn information
}

Be aware: Whereas importing dependencies, there are numerous import choices for Permission. Please select androidx.well being.join.consumer.permission.

Right here’s what’s occurring in checkPermissionsAndRun:

  1. You to start with come up with a HealthConnectClient object. getOrCreate creates a brand new occasion or returns an present one if it’s out there.
  2. Create a set of permissions with required information sorts to request permissions inside your utility. Permissions in these units must be declared within the health_permissions useful resource array.
  3. Create a request permission launcher. On launch, customers will likely be prompted for permissions declared within the health_permissions useful resource array.
  4. Lastly, via HealthConnectClient, you test whether or not you may have the required permissions. If permissions aren’t out there, you request permissions via requestPermissions launcher.

onPermissionAvailable is known as when you may have all required permissions. At this level, it’s doable to learn or write information.

Add the next after the closing utility tag inside AndroidManifest.xml:


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

This checks whether or not Well being Join APK is put in.

Lastly, inside onCreate in MainActivity.kt, substitute // Your code with the next code:


if (HealthConnectClient.isAvailable(this)) {
    // Well being Join is obtainable
    checkPermissionsAndRun()
 } else {
    Toast.makeText(
      this, "Well being Join isn't out there", Toast.LENGTH_SHORT
    ).present()
}

Right here’s what’s occurring:

  • By HealthConnectClient, you test whether or not Well being Join is obtainable.
  • Whether it is out there, you test required permissions.

You present a Toast to the consumer, if Well being Join isn’t out there.

That’s it! You’ve built-in Well being Join within the app and may request all required permissions. Give it a attempt by working the app.

An animation showing how to grant permissions in Android Health Connect

Writing Knowledge

Inserting Information

Add the next code after onPermissionAvailable.


personal enjoyable insertData(consumer: HealthConnectClient, steps: Lengthy, caloriesBurned: Double) {
  // 1
  val startTime = ZonedDateTime.now().minusSeconds(1).toInstant()
  val endTime = ZonedDateTime.now().toInstant()

  // 2
  val information = listOf(
   StepsRecord(
     rely = steps,
     startTime = startTime,
     endTime = endTime,
     startZoneOffset = null,
     endZoneOffset = null,
   ),
   TotalCaloriesBurnedRecord(
     power = Vitality.energy(caloriesBurned),
     startTime = startTime,
     endTime = endTime,
     startZoneOffset = null,
     endZoneOffset = null,
   )
  )

  // 3
  lifecycleScope.launch {
    val insertRecords = consumer.insertRecords(information)

    if (insertRecords.recordUidsList.isNotEmpty()) {
      runOnUiThread{
          Toast.makeText(
            [email protected],
            "Information inserted efficiently",
            Toast.LENGTH_SHORT
          ).present()
        }
      }
    }
}

With this replace,

  1. You’re making a time vary with a begin and finish. You report the info in a small interval. This manner you’ll be able to insert the info a number of occasions in a day.
  2. Adopted by one other checklist that incorporates StepsRecord and TotalCaloriesBurnedRecord information.
  3. Then lastly, you insert the created report via the HealthConnectClient occasion. recordUidsList incorporates the uids of inserted information. When the checklist isn’t empty, you’re displaying a hit message to the consumer.

Now, on the finish of onCreate within the MainActivity.kt, add the next code:


val stepsEditText = findViewById<EditText>(R.id.stepsEditText)
val caloriesEditText = findViewById<EditText>(R.id.caloriesEditText)

findViewById<Button>(R.id.submit).setOnClickListener {
  val steps = stepsEditText.textual content.toString().toLong()
  val energy = caloriesEditText.textual content.toString().toDouble()

  val consumer = HealthConnectClient.getOrCreate(this)
  insertData(consumer, steps, energy)

  // clear enter fields after insertion and shut the keyboard
  stepsEditText.textual content.clear()
  caloriesEditText.textual content.clear()
  caloriesEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
}

Within the code above, when a consumer faucets Button, you learn enter values and save them with insertData(). You then clear enter fields and shut the keyboard.

Construct and Run

That’s all you could do to write down information via the Well being Join API. Run the undertaking, enter values and faucet the button.

An animation to demo the input of steps and calories health data

Studying Knowledge

You’ll be able to learn information in two methods utilizing HealthConnectClient.

  • ReadRecordsRequest: Learn information decided by time vary and different filters. You’ll use this methodology to learn the each day steps rely and energy consumption.
  • AggregateRequest: Learn aggregations for a given AggregateMetric. You’ll use this methodology to learn month-to-month step counts and caloric intakes.

Studying Knowledge via a ReadRecordsRequest

In MainActivity.kt, add the next after insertData():


personal droop enjoyable readDailyRecords(consumer: HealthConnectClient) {
  // 1
  val at present = ZonedDateTime.now()
  val startOfDay = at present.truncatedTo(ChronoUnit.DAYS)
  val timeRangeFilter = TimeRangeFilter.between(
    startOfDay.toLocalDateTime(),
    at present.toLocalDateTime()
  )

  // 2
  val stepsRecordRequest = ReadRecordsRequest(StepsRecord::class, timeRangeFilter)
  val numberOfStepsToday = consumer.readRecords(stepsRecordRequest)
    .information
    .sumOf { it.rely }
  val stepsTextView = findViewById<TextView>(R.id.stepsTodayValue)
  stepsTextView.textual content = numberOfStepsToday.toString()

  // 3
  val caloriesRecordRequest = ReadRecordsRequest(
    TotalCaloriesBurnedRecord::class,
    timeRangeFilter
  )
  val caloriesBurnedToday = consumer.readRecords(caloriesRecordRequest)
    .information
    .sumOf { it.power.inCalories }
  val caloriesTextView = findViewById<TextView>(R.id.caloriesTodayValue)
  caloriesTextView.textual content = caloriesBurnedToday.toString()
}

And now the breakdown:

  1. You create a TimeRangeFilter from the beginning of the day till now.
  2. You then create a ReadRecordRequest for StepsRecord. By the HealthConnectClient occasion, you learn information and get the sum. You get the sum as a result of there could be many information for steps taken at present. Lastly, you show the each day steps rely.
  3. This is similar as Step 2, however the ReadRecordsRequest is for TotalCaloriesBurnedRecord.

Studying Knowledge via an AggregateRequest

Add the next methodology on the backside of MainActivity:


personal droop enjoyable readAggregatedData(consumer: HealthConnectClient) {
  // 1
  val at present = ZonedDateTime.now()
  val startOfDayOfThisMonth = at present.withDayOfMonth(1)
    .truncatedTo(ChronoUnit.DAYS)
  val elapsedDaysInMonth = Period.between(startOfDayOfThisMonth, at present)
    .toDays() + 1
  val timeRangeFilter = TimeRangeFilter.between(
    startOfDayOfThisMonth.toInstant(),
    at present.toInstant()
  )

  // 2
  val information = consumer.mixture(
    AggregateRequest(
      metrics = setOf(
        StepsRecord.COUNT_TOTAL,
        TotalCaloriesBurnedRecord.ENERGY_TOTAL
      ),
      timeRangeFilter = timeRangeFilter,
    )
  )

  // 3
  val steps = information[StepsRecord.COUNT_TOTAL] ?: 0
  val averageSteps = steps / elapsedDaysInMonth
  val stepsAverageTextView = findViewById<TextView>(R.id.stepsAverageValue)
  stepsAverageTextView.textual content = averageSteps.toString()

  // 4
  val caloriesBurned = information[TotalCaloriesBurnedRecord.ENERGY_TOTAL]
      ?.inCalories ?: 0.0
  val averageCaloriesBurned = caloriesBurned / elapsedDaysInMonth
  val caloriesAverageTextView = findViewById<TextView>(
    R.id.caloriesAverageValue
  )
  caloriesAverageTextView.textual content = getString(R.string.format_calories_average)
      .format(averageCaloriesBurned)
}

Be aware: Whereas importing dependencies, there are numerous import choices for Period. Please select java.time.

Right here’s what’s occurring:

  1. You’re making a TimeRangeFilter from the beginning of the month till now. Additionally, you’re calculating the times elapsed within the month so you’ll be able to calculate the common.
  2. You’re making an mixture request via HealthConnectClient with a set of measurements to get the entire steps and energy inside a particular time vary. The good thing about aggregated information is it contains primary aggregations or aggregating information into buckets.
  3. You’re calculating averageSteps and updating the format.
  4. You’re calculating averageCaloriesBurned and updating the format. For a greater UI, you’re rounding the calorie values as much as two decimals.

Add the next within the strings.xml file.


<string identify="format_calories_average">%.2f</string>

You’re nearly there. You now have capabilities that learn information, however you could join a number of remaining dots.

Add one other methodology within the MainActivity.kt:


personal droop enjoyable readData(consumer: HealthConnectClient) {
  readDailyRecords(consumer)
  readAggregatedData(consumer)
}

This helper perform instructions each capabilities you created above to learn information.

Now, inside onPermissionAvailable, substitute // todo: learn information with the next.


readData(consumer)

By doing so, you’ll be able to learn the info and replace the format as quickly as you may have permissions out there.

Lastly, add the next on the finish of the lifecycleScope.launch { block, inside insertData:


readData(consumer)

It will make sure you present up to date information after a consumer inserts new information.

Construct and Run

You’re finished! Construct and run the app to see the outcome. Now you can write information and in addition see your present information.

An animation to demo displaying the total steps and calories health data entered today and the average this month

The place to Go From Right here?

Congratulations! You’ve discovered about Well being Join by making a easy app. Now you may have one much less excuse to get fitter and more healthy. Use the Obtain Supplies button on the high or backside of this text to obtain the ultimate undertaking.

You’ll be able to take a number of steps to enhance your app:

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles