3

There are various fitness activities in Google Fit API such as Aerobics, Badminton, Boxing, Weight Lifting, etc. How do I get the readings of the steps counted and the calories burnt for each of these activities using Google Fit API? Any sort of suggestions are most welcome. Thanks in advance.

  • there is option for data source request type – curiousMind Apr 27 '18 at 11:11
  • @curiousMind, I understand that, but I am not getting a proper documentation which says which of these fitness activities uses which datatype. – Partha Chakraborty Apr 27 '18 at 11:16
  • please refer this https://developers.google.com/fit/android/data-types – curiousMind Apr 27 '18 at 11:22
  • @curiousMind, suppose the user wants to do weightlifting. I am using the datatype as`TYPE_WORKOUT_EXERCISE`. Also for getting its value, I am writing the following: `DataPoint firstLiftEffort = liftDataSet.createDataPoint().setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS); firstLiftEffort.getValue(Field.FIELD_EXERCISE).setInt(weightliftingMps);` The app crashes because the field value is mismatching. This keeps happening with other fitness activities as well. – Partha Chakraborty Apr 27 '18 at 11:34
  • Did you check the [How to Record a Workout](https://developers.google.com/fit/rest/v1/workout)?? – ReyAnthonyRenacia May 02 '18 at 09:35
  • Yes, I have followed the documentation, but I want to know how to get the values of Fitness Activities such as Aerobics, Badminton, Boxing, Weight Lifting, etc. In the documentation, it's only showing the step count scenario. @noogui – Partha Chakraborty May 03 '18 at 09:41

1 Answers1

3

I'm not sure if this result is what you need. You can use bucketByActivitySegement under DataReadRequest.Builder to split each activity segement.

    DataReadRequest readRequest = new DataReadRequest.Builder()
            .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
            .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
            .bucketByActivitySegment( 1, TimeUnit.MINUTES) // just segement time over 1 minute will be list 
            .setTimeRange(startTimeLong, endTimeLong, TimeUnit.MILLISECONDS)
            .enableServerQueries()
            .build();

    Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context))
           .readData(readRequest)
           .addOnSuccessListener()
           .addOnFailureListener();

The result you will get several bucket, each bucket is one activity segment. An bucket contain two DataSets. One is step value, another one is calories value. Just like the following:

Bucket 0: activity: still, 05/09 00:00~08:03
-DataSet 0:  
--DataPoint 0: 05/09 08:02~09:03
---Field name: steps, value: 55
-DataSet 1: 
--DataPoint 0: 05/09 00:00~08:03
---Field name: calories, value: 459.41046

Bucket 1: acitvity: walking, 05/09 08:03~08:09
-DataSet 0:
--DataPoint 0: 05/09 08:03~08:04
---Field name: steps, value: 181
-DataSet: 1
--DataPoint 0: 05/09 08:03~08:09
---Field name: calories, value: 20.808548

Bucket 2: activity: in_vehicle, 05/09 08:09~08:48
-DataSet 0:
--DataPoint 0: 05/09 08:33~08:38
---Field name: steps, value: 156
-DataSet 1:
--DataPoint 0: 05/09 08:09~08:48
---Field name: calories, value: 36.633526

Bucket 3: activity: walking, 05/09 08:48~09:12
...
...
...

If the result you need if the aggregate value for each type during a duration, you can use bucketByActivityType.

    DataReadRequest readRequest = new DataReadRequest.Builder()
            .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
            .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
            .bucketByActivityType( 1, TimeUnit.MINUTES)
            .setTimeRange(startTimeLong, endTimeLong, TimeUnit.MILLISECONDS)
            .enableServerQueries()
            .build();

It will return the total value for each type during your TimeRange.

Bucket 0: activity: still, 05/09 00:00 ~ 05/16 18:42
-DataSet 0:  
--DataPoint 0: 05/09 00:00 ~ 05/16 18:42
---Field name: calories, value: 9984.753
-DataSet 1: 
--DataPoint 0: 05/09 08:02 ~ 05/16 17:24
---Field name: steps, value: 6499

Bucket 1: acitvity: walking, 05/09 08:03 ~ 05/16 13:28
-DataSet 0:
--DataPoint 0: 05/09 08:03 ~ 05/16 13:28
---Field name: calories, value: 1214.7212
-DataSet: 1
--DataPoint 0: 05/09 08:03 ~ 05/16 13:20
---Field name: steps, value: 12750

Bucket 2: activity: in_vehicle, 05/09 08:09 ~ 05/09 08:48
-DataSet 0:
--DataPoint 0: 05/09 08:09 ~ 05/09 08:48
---Field name: calories, value: 36.633526
-DataSet 1:
--DataPoint 0: 05/09 08:33 ~ 05/09 08:38
---Field name: steps, value: 156

Bucket 3: activity: aerobics, 05/11 18:00 ~ 05/11 18:59
...
...
...

Hope this helps you.


--- 2018/05/30 update ---

In addOnSuccessListener() you can add a Listener like this:

    new OnSuccessListener<DataReadResponse>() {
                @Override
                public void onSuccess(DataReadResponse dataReadResult) {
                    String returnValue = "";

                    if (dataReadResult.getBuckets().size() > 0) {
                        for (int i = 0; i < dataReadResult.getBuckets().size(); i++) {
                            returnValue += "\n\n" + i + " ---new bucket-- activity: " + dataReadResult.getBuckets().get(i).getActivity() + "\n"
                                    + getNoYearDateWithTimeFormat().format(dataReadResult.getBuckets().get(i).getStartTime(TimeUnit.MILLISECONDS)) + "~"
                                    + getNoYearDateWithTimeFormat().format(dataReadResult.getBuckets().get(i).getEndTime(TimeUnit.MILLISECONDS));

                            for (int j = 0; j < dataReadResult.getBuckets().get(i).getDataSets().size(); j++) {
                                returnValue += "\n-data set " + j + "-package: " + dataReadResult.getBuckets().get(i).getDataSets().get(j).getDataSource().getAppPackageName() + ", stream: " + dataReadResult.getBuckets().get(i).getDataSets().get(j).getDataSource().getStreamIdentifier();
                                returnValue += handleDailyRecordInDataSet(dataReadResult.getBuckets().get(i).getDataSets().get(j));
                            }
                        }
                    }


                    if (fitnessListener != null) {
                        fitnessListener.readActionDone(null, returnValue);
                    }
                }
            }

In each bucket you can get several DataSet per data type.

private String handleDailyRecordInDataSet(DataSet dataSet) {
    String returnValue = "";

    for (DataPoint dataPoint : dataSet.getDataPoints()) {
        long startTime = dataPoint.getStartTime(TimeUnit.MILLISECONDS);
        long endTime = dataPoint.getEndTime(TimeUnit.MILLISECONDS);
        String tempValue = "DataPoint start: " + getDateWithTimeFormat().format(new Date(startTime))
                + ", end=" + getDateWithTimeFormat().format(new Date(endTime))
                + ", type=" + dataPoint.getDataType().getName() + ",  package=" + dataPoint.getDataSource().getAppPackageName() + ", stream=" + dataPoint.getDataSource().getStreamIdentifier();
        if (dataPoint.getDataSource().getDevice() != null) {
            tempValue += "\nManufacturer=" + dataPoint.getDataSource().getDevice().getManufacturer() + ", model=" + dataPoint.getDataSource().getDevice().getModel()
                    + ", uid: " + dataPoint.getDataSource().getDevice().getUid() + ", type=" + dataPoint.getDataSource().getDevice().getType();
        }
        tempValue += "\norigin source: package=" + dataPoint.getOriginalDataSource().getAppPackageName() + ", stream=" + dataPoint.getOriginalDataSource().getStreamIdentifier();
        if (dataPoint.getOriginalDataSource().getDevice() != null) {
            tempValue += "\nManufacturer=" + dataPoint.getOriginalDataSource().getDevice().getManufacturer() + ", model=" + dataPoint.getOriginalDataSource().getDevice().getModel()
                    + ", uid: " + dataPoint.getOriginalDataSource().getDevice().getUid() + ", type=" + dataPoint.getOriginalDataSource().getDevice().getType();
        }

        returnValue += ("\n\n" + tempValue);
        for (Field field : dataPoint.getDataType().getFields()) {
            String fieldValue = "Field name: " + field.getName() + ", value: " + dataPoint.getValue(field);

            returnValue += ("\n" + fieldValue);
        }
    }

    return returnValue;
}
ginnyhuang
  • 63
  • 6
  • This is almost the full code. I'm not sure what information I did not mention you need. – ginnyhuang May 24 '18 at 09:55
  • You just need to handle Google Account Sign-in with permissions before these code. And than add Listener in addOnSuccessListener() to get the data you need. – ginnyhuang May 24 '18 at 09:56
  • I ain't getting bucket wise data unlike you. – Partha Chakraborty May 29 '18 at 10:39
  • Did you install Google Fit and start an account to use it? I think you can use Fitness api without install Google fit, but it will not record any info detect from mobile without Google Fit. – ginnyhuang May 30 '18 at 09:11
  • Yes, I have installed Google Fit and opened a Google account as well. Thanks for updating the code. I will check the same. – Partha Chakraborty May 31 '18 at 08:09
  • @ParthaChakraborty hi did you get running and other activity data from history api – Vishal Thakkar Mar 04 '19 at 12:07
  • @Vishal Thakkar I can read history data, it is easy to get, But i was trying to read the real time data but i can not get real time data. Here is my question if any one know please answer. https://stackoverflow.com/questions/58584957/fitness-getsensorsclient-can-not-read-type-activity-segment-real-time-data – Dinakar Prasad Maurya Nov 02 '19 at 11:53
  • @ginnyhuang what if I want the total for each activity, but bucketed by day? Is it possible to do that in a single query? Thanks. – Jumpa Oct 24 '20 at 07:31