Tracking Exercises with Galaxy Watch

Samsung Developer

Galaxy Watch offers a convenient way of measuring exercise progress. Modern sensors designed specifically for Health Services provide the most precise readings. After connecting to Health Services, you can measure certain exercises and track their values.

This blog describes all the important steps to build an exercise tracking app using the Health Services API. We use example code introduced in Health Code Lab for Tracking Exercise. You can download the source code from this Code Lab.

Health Services defines a variety of exercise types. For a full exercise type list, take a look at ExerciseType.

On Galaxy Watch4 and Galaxy Watch4 Classic, a repetition counter is available for the following exercises:

  • BACK_EXTENSION
  • BARBELL_SHOULDER_PRESS
  • BENCH_PRESS
  • BENCH_SIT_UP
  • BURPEE
  • CRUNCH
  • DEADLIFT
  • FORWARD_TWIST
  • DUMBBELL_CURL_RIGHT_ARM
  • DUMBBELL_FRONT_RAISE
  • DUMBBELL_LATERAL_RAISE
  • DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM
  • DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM
  • DUMBBELL_TRICEPS_EXTENSION_TWO_ARM
  • DUMBBELL_CURL_LEFT_ARM
  • JUMP_ROPE
  • JUMPING_JACK
  • LAT_PULL_DOWN
  • LUNGE
  • SQUAT
  • UPPER_TWIST

In this application, we are going to use DEADLIFT. The example code used for DEADLIFT can be easily adapted to track all repetition-based exercises.

The basics of connecting to Health Services are covered in the blog Using Health Services on Galaxy Watch.

Setting up an exercise

Once connected to the Health Services API, we are ready to set up the exercise. In this case we use DEADLIFT as a sample exercise.

First, we need to get the exercise client:

ExerciseClient exerciseClient = client.getExerciseClient();

After that, we need to set the exercise type in the configuration builder:

ExerciseType exerciseType = ExerciseType.DEADLIFT
ExerciseConfigBuilder exerciseConfigBuilder = ExerciseConfig.builder()
        .setExerciseType(exerciseType);

To see what can be tracked for our exercise, we need to check its capabilities. We do this by using a ListenableFuture object and listening for a callback from Health Services.

ListenableFuture<ExerciseCapabilities> capabilitiesListenableFuture =  exerciseClient.getCapabilities();

When we receive a callback, we can receive a set with capabilities:

FutureCallback<ExerciseCapabilities>() {
    @Override
    public void onSuccess(@Nullable ExerciseCapabilities result) {
        try {
				ExerciseTypeCapabilities exerciseTypeCapabilities =
        			result.getExerciseTypeCapabilities(exerciseType);
				Set<DataType> exerciseCapabilitiesSet =                                 
    			    exerciseTypeCapabilities.getExerciseCapabilities(result);
    		 }

If you do not want to track some of these values, at this point, you can remove them from a set. By default, all DataTypes that a certain exercise can measure are being stored as a Set. By removing them before setting up a configuration builder, you can exclude tracking unnecessary values.

Once we are ready, we can finish configuring an exercise:

exerciseConfigBuilder = ExerciseConfig.builder()
        .setExerciseType(exerciseType)
        .setDataTypes(exerciseCapabilitiesSet);

Setting up exercise listener

An exercise listener is an object that allows us to get exercise updates from Health Services, whenever they are available. To set up the listener, we need to override three methods:

ExerciseUpdateListener exerciseUpdateListener =
	new ExerciseUpdateListener() {
    	@Override
        public void onExerciseUpdate(ExerciseUpdate update)
        {
        	//Processing your update
        }
        @Override
		public void onAvailabilityChanged(DataType datatype, Availability availability)
        {
        	//Processing Availability
        }
        @Override
        public void onLapSummary(ExerciseLapSummary summary)
        {
        	//Processing Lap Summary
        }
   };

Starting and stopping the exercise

We are ready to start tracking our exercise. To do that, we use the ListenableFuture object that gets callbacks from the HealthServices API whenever an update is available. To build this object, we send our configuration to the exercise client while starting measurement:

ListenableFuture<Void> startExerciseListenableFuture =  exerciseClient.startExercise(exerciseConfigBuilder.build());

When we get a callback from the HealthServices API, we start our listener:

ListenableFuture<Void> updateListenableFuture = exerciseClient.setUpdateListener(exerciseUpdateListener);

We finish exercise in a similar way, by creating a ListenableFuture object that asks the Health Services API to stop tracking exercise:

ListenableFuture<Void> endExerciseListenableFuture =  exerciseClient.endExercise()

Processing Exercise Update data

Exercise Update data contains various information about the performed exercise. After setting up a listener, we retrieve it in a callback:

public void onExerciseUpdate(@NonNull ExerciseUpdate update) {
    try {
        updateRepCount(update);
    } catch (DeadliftException exception) {
        Log.e(TAG, "Error getting exercise update: ", exception);
    }
}

In this example, we focus on one of most important readings—latest metrics. We store them in a map:

Map<DataType, List<DataPoint>> map = update.getLatestMetrics();

Now we can read particular values by looking for their key:

List<DataPoint> repPoints = map.get(DataType.REP_COUNT);
List<DataPoint> caloriesPoints = map.get(DataType.TOTAL_CALORIES);

The last value on the list is the latest reading in the current update. We can use it in our application, for example, when updating a label:

String repValue = String.format("%d", Iterables.getLast(repPoints).getValue().asLong());
txtReps.setText(String.format("Reps count: %s", repValue));

This is how exercise data can be accessed and processed using Health Services on Galaxy Watch. It’s a quick and convenient way to track its progress that everybody can implement into a watch application.