DEV Community

Jackson for HMS Core

Posted on

How to Monitor Health and Fitness Data During Home Workouts

As a busy developer, I can hardly spare the time to go to the gym, but I know that I should. Then I came across the videos of Pamela Reif, a popular fitness blogger, which gave me the idea of working out from home. I followed a home workout regimen, but found it hard to track my training load systematically, such through heart rate and calories burned. And that's exactly how my app, Fitness Manager came into being. I developed this app by harnessing the extended capabilities in HUAWEI Health Kit. Next, I'll show you how you can do the same!

Demo

Image description

About Health Kit

Health Kit offers both basic and extended capabilities to be integrated. Its basic capabilities allow your app to add, delete, modify, and query user fitness and health data upon obtaining the user's authorization, so that you can provide a rich array of fitness and health services. Its extended capabilities open a greater range of real-time fitness and health data and solutions.
Fitness Manager was solely developed from the extended capabilities in Health Kit.

Development Process

Environment Requirements

Android platform:

  • Android Studio: 3.X or later
  • JDK 1.8.211 or later

SDK and Gradle:

  • minSdkVersion 24
  • targetSdkVersion 29
  • compileSdkVersion 29
  • Gradle: 4.6 or later
  • Test device: You'll need a Huawei phone that runs Android 6.0 or later, and has installed the HUAWEI Health app.

Development Procedure

Here I'll detail the entire process for developing an app using the extended capabilities mentioned above.
Before getting started, register and apply for the HUAWEI ID service, and then apply for the Health Kit service on HUAWEI Developers. You can skip this step if you have already created an app using the kit's basic capabilities. Then, apply for the data read and write scopes you need for your app. If you have any special needs, send an email to hihealth@huawei.com.
Now, integrate the SDK for the extended capabilities to your project in Android Studio. Before building the APK, make sure that you have configured the obfuscation script to prevent the HMS Core SDK from being obfuscated. Once the integration is complete, test your app against the test cases, and submit it for review. After passing the review, your app will obtain the formal scopes, and can be finally released.
Now, I'll show you how to implement some common features in your app using the kit's capabilities.

Starting and Stopping a Workout

To control workouts and obtain real-time workout data, call the following APIs in sequence:

  • registerSportData: Starts obtaining real-time workout data.
  • startSport: Starts a workout.
  • stopSport: Stops a workout.
  • unregisterSportData: Stops obtaining real-time workout data.

Key Code
1) Starting obtaining real-time workout data

  • Call the registerSportData method of the HiHealthDataStore object to start obtaining real-time workout data.
  • Obtain the workout data through HiSportDataCallback.
HiHealthDataStore.registerSportData(context, new HiSportDataCallback() {
    @Override
    public void onResult(int resultCode) {
        // API calling result.
        Log.i(TAG, "registerSportData onResult resultCode:" + resultCode);
    }

    @Override
    public void onDataChanged(int state, Bundle bundle) {
        // Real-time data change callback.
        Log.i(TAG, "registerSportData onChange state: " + state);        
        StringBuffer stringBuffer = new StringBuffer("");              
        if (state == HiHealthKitConstant.SPORT_STATUS_RUNNING) {
            Log.i(TAG, "heart rate : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_HEARTRATE));
            Log.i(TAG, "distance : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_DISTANCE));
            Log.i(TAG, "duration : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_DURATION));
            Log.i(TAG, "calorie : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_CALORIE));
            Log.i(TAG, "totalSteps : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_TOTAL_STEPS));
            Log.i(TAG, "totalCreep : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_TOTAL_CREEP));
            Log.i(TAG, "totalDescent : " + bundle.getInt(HiHealthKitConstant.BUNDLE_KEY_TOTAL_DESCENT));
        }        
    }
});
Enter fullscreen mode Exit fullscreen mode

2) Starting a workout
The following table lists supported workout constants.

Open Data Type Constant
Outdoor walking HiHealthKitConstant.SPORT_TYPE_WALK
Outdoor running HiHealthKitConstant.SPORT_TYPE_RUN
Outdoor cycling HiHealthKitConstant.SPORT_TYPE_BIKE
Indoor running HiHealthKitConstant.SPORT_TYPE_TREADMILL
  • Call the startSport method of the HiHealthDataStore object to start a specific type of workout.
  • Obtain the calling result through ResultCallback.
// Outdoor running.
int sportType = HiHealthKitConstant.SPORT_TYPE_RUN;
HiHealthDataStore.startSport(context, sportType, new ResultCallback() {
    @Override
    public void onResult(int resultCode, Object message) {
        if (resultCode == HiHealthError.SUCCESS) {
            Log.i(TAG, "start sport success");
        }
    }
});
Enter fullscreen mode Exit fullscreen mode

3) Stopping a workout

  • Call the stopSport method of the HiHealthDataStore object to stop a specific type of workout.
  • Obtain the calling result through ResultCallback.
HiHealthDataStore.stopSport(context, new ResultCallback() {
    @Override
    public void onResult(int resultCode, Object message) {
        if (resultCode == HiHealthError.SUCCESS) {
            Log.i(TAG, "stop sport success");
        }
    }
});
Enter fullscreen mode Exit fullscreen mode

4) Stopping obtaining real-time workout data

  • Call the unregisterSportData method of the HiHealthDataStore object to stop obtaining the real-time workout data.
  • Obtain the calling result through HiSportDataCallback.
HiHealthDataStore.unregisterSportData(context, new HiSportDataCallback() {
    @Override
    public void onResult(int resultCode) {
        // API calling result.
        Log.i(TAG, "unregisterSportData onResult resultCode:" + resultCode);
    }

    @Override
    public void onDataChanged(int state, Bundle bundle) {
       // The API is not called at the moment.
    }
});
Enter fullscreen mode Exit fullscreen mode

Querying Daily Activities

You can allow your users to query their daily activities in your app, such as step count details and statistics, distance, calories burned, and medium- and high-intensity activities. These data comes from Huawei phones or Huawei wearable devices. Before data query, you'll need to apply for the corresponding permissions, and obtain authorization from users. Otherwise, your API calling will fail.
1) Querying daily activity data by calling execQuery

  • Call the execQuery method of the HiHealthDataStore object to query user's daily activities.
  • Obtain the query result through ResultCallback.

The following takes querying step statistics as an example:

int timeout = 0;
// Query the step count of the current day.
Calendar currentDate = Calendar.getInstance();
currentDate.set(Calendar.HOUR_OF_DAY, 0);
currentDate.set(Calendar.MINUTE, 0);
currentDate.set(Calendar.SECOND, 0);
long startTime = currentDate.getTimeInMillis();
long endTime = System.currentTimeMillis();
// Query the step count.
HiHealthDataQuery hiHealthDataQuery = new HiHealthDataQuery(HiHealthPointType.DATA_POINT_STEP_SUM, startTime,
        endTime, new HiHealthDataQueryOption());
HiHealthDataStore.execQuery(context, hiHealthDataQuery, timeout, new ResultCallback() {
    @Override
    public void onResult(int resultCode, Object data) {
        Log.i(TAG, "query steps resultCode: " + resultCode);
        if (resultCode == HiHealthError.SUCCESS && data instanceof List) {
            List dataList = (ArrayList) data;
            for (Object obj : dataList) {
                HiHealthPointData pointData = (HiHealthPointData) obj;
                Log.i(TAG, "start time : " + pointData.getStartTime());
                Log.i(TAG, "query steps : " + String.valueOf(pointData.getValue()));
            }
        }
    }
});
Enter fullscreen mode Exit fullscreen mode

Parameters required for query and the query results

Open Data Type Parameter for Query Method for Obtaining the Result Result Value Type Result Description
Daily activities Step count statistics HiHealthPointType.DATA_POINT_STEP_SUM HiHealthPointData.getValue() int Step count (unit: step). For the current day, the value is updated in real time. For each of the previous days, the value is the total step count of that day.
Step count details HiHealthPointType.DATA_POINT_STEP Step count per minute (unit: step).
Distance HiHealthPointType.DATA_POINT_DISTANCE_SUM Distance (unit: meter). For the current day, the value is updated in real time. For each of the previous days, the value is the total distance of that day.
Calories burned HiHealthPointType.DATA_POINT_CALORIES_SUM Calories burned (unit: kcal). For the current day, the value is updated in real time. For each of the previous days, the value is the total calories burned of that day.
Medium- and high-intensity activities HiHealthPointType.DATA_POINT_EXERCISE_INTENSITY Intensity (unit: minute). For the current day, the value is updated in real time. For each of the previous days, the value is the total intensity of that day.

Querying Workout Records

The following is an example of querying workout records in the last 30 days:

  • Call the execQuery method of the HiHealthDataStore object to query user's workout records.
  • Obtain the query result through ResultCallback.
int timeout = 0;
 long endTime = System.currentTimeMillis();
// The time range for the query is the past 30 days.
 long startTime = endTime - 1000 * 60 * 60 * 24 * 30L;
// Query the running data.
 HiHealthDataQuery hiHealthDataQuery = new HiHealthDataQuery(HiHealthSetType.DATA_SET_RUN_METADATA, startTime,
         endTime, new HiHealthDataQueryOption());
 HiHealthDataStore.execQuery(context, hiHealthDataQuery, timeout, new ResultCallback() {
     @Override
     public void onResult(int resultCode, Object data) {
if (resultCode == HiHealthError.SUCCESS && data instanceof List){ 
            List dataList = (List) data;
            for (Object obj : dataList) {
                HiHealthSetData hiHealthData = (HiHealthSetData) obj;
                Map map = hiHealthData.getMap();
                Log.i(TAG, "start time : " + hiHealthData.getStartTime());
                Log.i(TAG, "total_time : " +  map.get(HiHealthKitConstant.BUNDLE_KEY_TOTAL_TIME));
                Log.i(TAG, "total_distance : " + map.get(HiHealthKitConstant.BUNDLE_KEY_TOTAL_DISTANCE));
                Log.i(TAG, "total_calories : " + map.get(HiHealthKitConstant.BUNDLE_KEY_TOTAL_CALORIES));
                Log.i(TAG, "step : " + map.get(HiHealthKitConstant.BUNDLE_KEY_STEP));
                Log.i(TAG, "average_pace : " + map.get(HiHealthKitConstant.BUNDLE_KEY_AVERAGEPACE));
                Log.i(TAG, "average_speed : " + map.get(HiHealthKitConstant.BUNDLE_KEY_AVERAGE_SPEED));
                Log.i(TAG, "average_step_rate : " + map.get(HiHealthKitConstant.BUNDLE_KEY_AVERAGE_STEP_RATE));
                Log.i(TAG, "step_distance : " + map.get(HiHealthKitConstant.BUNDLE_KEY_STEP_DISTANCE));
                Log.i(TAG, "average_heart_rate : " + map.get(HiHealthKitConstant.BUNDLE_KEY_AVERAGE_HEART_RATE));
                Log.i(TAG, "total_altitude : " + map.get(HiHealthKitConstant.BUNDLE_KEY_TOTAL_ALTITUDE));
                Log.i(TAG, "total_descent : " + map.get(HiHealthKitConstant.BUNDLE_KEY_TOTALDESCENT));
                Log.i(TAG, "data source : " + map.get(HiHealthKitConstant.BUNDLE_KEY_DATA_SOURCE));
            }
        }
     }
 });
Enter fullscreen mode Exit fullscreen mode

Top comments (0)