Diving into the Client Types in Health Services

Samsung Developer

In our Using Health Services on Galaxy Watch article, we introduced you to Health Services and the series of steps you need to follow in order to start using it within your application. Now, we present the different client types provided by Health Services and their core functionality.

ExerciseClient

In recent years, many applications that use and process health data are focused on workouts due to increasing awareness of the importance of maintaining a healthy lifestyle. Some of those applications are more complex than others and have a lot of features, from tracking exercise performance to setting daily, weekly or monthly goals.

Health Services provides a specialized client to facilitate tracking ongoing workouts from a wide range of exercise types, such as running, playing soccer and skiing, among others.

Checking the capabilities on the device

As mentioned in our previous post, you have to ensure at runtime that your configuration is supported. Remember, there is nothing more confusing to users than dealing with an application that does not work as expected.

The code below describes how to check the capabilities of the device for an exercise type for running:

HealthServicesClient healthClient = HealthServices.getClient(this);
ExerciseClient exerciseClient = healthClient.getExerciseClient();

ListenableFuture<ExerciseCapabilities> capabilitiesFuture =
										passiveClient.getCapabilities();
Futures.addCallback(capabilitiesFuture,
        new FutureCallback<ExerciseCapabilities>() {
            @Override
            public void onSuccess(@Nullable ExerciseCapabilities result) {
                runningCapabilities  = result
                        .supportedDataTypesExcercise()
                        .contains(ExerciseType.RUNNING)
            }

            @Override
            public void onFailure(Throwable t) {
                // display an error
            }
        },
        ContextCompat.getMainExecutor(this));

Tracking workouts using ExerciseClient

After ensuring that the device running your application supports the type of exercise(s) you want to track, you must specify the relevant information, such as exercise type, exercise goal, and additional parameters supported by Health Services.

Health Services provides an ExerciseConfig class to help you to define a configuration for an exercise tracked by your application. With the help of this class, you can define and have access to information related to the exercise such as:

  • Exercise type
  • Exercise goals
  • Data type of the exercise
  • Flags to indicate the exercise state

Once you set up your configuration, you can start your exercise and then listen for its progress using an update listener. The basic setup flow should be something like:

  • Set up ExerciseConfig
  • Call exerciseClient.startExercise
  • Set up an update listener
  • Listen for progress and update your app

Finally, Health Services provides a useful class to set goals and keep track of them. The ExerciseGoal class allows you to set goals based on certain parameters, so the users of your application can create milestones or one-time goals.

An example of a milestone could be a hiking app that sets a goal that is achieved multiple times when the user has covered a distance of 200m. The event is triggered every 200m. In contrast, a one-time goal could be defined as a goal that sets a milestone with a threshold equivalent to the height of Mount Everest.

The ability to work with exercise goals in Health Services will be described in more detail in a separate post.

Note: When using ExerciseClient, make sure your app requests and maintains the necessary permissions. If your app uses Location data, you should consider permissions on the device, like checking that GPS is enabled.

Also, you should ensure that a ForegroundService with the appropriate foregroundServiceType is maintained throughout the workout, as shown in the code below:

<!-- Add foreground service location permission for exercise tracking -->
<service
        android:name=".ExerciseService"
        android:foregroundServiceType="location"
        android:exported="false" />

MeasureClient

Using this client is highly recommended if your application requires constant updates. In a real-world scenario, your application should use this client when its UI is in the foreground.

As a good practice, your application should minimize the amount of time reading data with this client. Registering callbacks to read health data can increase sensor sampling rates, increasing power consumption. Use this client carefully, having user experience in mind and taking into account that users want to extend the power of the device as much as possible.

Checking the capabilities on the device

HealthServicesClient healthClient = HealthServices.getClient(this);

ListenableFuture<MeasureCapabilities> capabilitiesFuture =
											healthClient.getCapabilities();
Futures.addCallback(capabilitiesFuture,
        new FutureCallback<Capabilities>() {
            @Override
            public void onSuccess(@Nullable Capabilities result) {
                boolean supportsHeartRate = result
                        .supportedDataTypesMeasure()
                        .contains(DataType.HEART_RATE_BPM)
            }

            @Override
            public void onFailure(Throwable t) {
                // Handle error here.
            }
        },
        ContextCompat.getMainExecutor(this));

PassiveMonitoringClient

This client is suitable for applications that monitor health data in the background. This client makes it easier to keep track of activities during longer periods of time, taking advantage of the fact that it does not require your application to be in the foreground.

Some examples of activities tracked by this client are step count or floors climbed during the day, week or month.

Checking the capabilities on the device

HealthServicesClient healthClient = HealthServices.getClient(this);
PassiveMonitoringClient passiveClient = healthClient.getPassiveMonitoringClient();

ListenableFuture<PassiveMonitoringCapabilities> capabilitiesFuture =
											passiveClient.getCapabilities();
Futures.addCallback(capabilitiesFuture,
        new FutureCallback<PassiveMonitoringCapabilities>() {
            @Override
            public void onSuccess(@Nullable PassiveMonitoringCapabilities result) {
                supportsHeartRate = result
                        .getSupportedDataTypesPassiveMonitoring()
                        .contains(DataType.HEART_RATE_BPM)
                supportsStepsEvent = result
                        .supportedDataTypesEvents()
                        .contains(DataType.STEPS)
            }

            @Override
            public void onFailure(Throwable t) {
                // display an error
            }
        },
        ContextCompat.getMainExecutor(this));

Choosing the right Health Services client

Having a clear understanding of every client type and their applications help you to make informed decisions when creating your application. This information helps you avoid unexpected results while interacting with the sensors on the device and it improves the overall user experience of your application.

Receiving health data updates in the background

To receive data updates in the background, your application must have a BroadcastReceiver declared in its AndroidManifest.xml, as we mentioned in our previous post. The updates from Health Services regarding passive data is delivered to this receiver.

So far, we have presented the key features for every client. You can make a more informed and confident decision of how to make the most of Health Services within your application. We encourage you to check Health Services to take advantage of all of these features.