Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get step count from Google Fit REST API like Google Fit app?

I'm developing a PHP application which work with Google Fit APIs to collect daily user's step count.

I want to get my step count from "Jan 15 2015 00:00:00 GMT+0700" to "Jan 16 2015 00:00:00 GMT+0700". - First, I get all my datasources. - Then, with each datasource which have datatype equal to "com.google.step_count.delta", I get datasets between above timestamps and add return values together.

My code: https://gist.github.com/daitr-gu/472c4f18522172542cca
My result: https://gist.github.com/daitr-gu/1a7e11eb483a657bdc8b

I found that, there are many datasources and they returns different values. And the values are too different from what I see in Google Fit app on my phone.

Questions:
1. Which datasource the Google Fit app use to calculate step count?
2. Why there are different between datasources's value and Google Fit value?
3. How can I get the Google Fit value?

like image 779
Kahn Avatar asked Jan 17 '15 11:01

Kahn


2 Answers

  1. Which datasource the Google Fit app use to calculate step count?

Google Fit App uses the estimated_steps data source to calculate step counts. DataSourceId: derived:com.google.step_count.delta:com.google.android.gms:estimated_steps

  1. Why there are different between datasources's value and Google Fit value?

Each data source represents a different device/source. I see you have a Sony Smart Watch and a HTC Desire connected to Google Fit. Each of your devices reports values to Fit which are merged together. Merge_step_deltas gives you the merged stream of all your step counters. Estimated_steps also takes into account activity, and estimates steps when there are none.

  1. How can I get the Google Fit value?

REST API can only access data which has been synced to the backend. To get same values as Google Fit, read estimated_steps data source. It should be the same as what you see on https://fit.google.com/. The device could have latest values which are not yet synced to the server. We are working on making the syncs and the cross-platform experience more seamless.

-- Engineer on Google Fit Team.

like image 120
Gouri Joshi Avatar answered Oct 17 '22 04:10

Gouri Joshi


I think the difference you are seeing is the difference between how Google uses the History API and the Sensors API. If you are using PHP, you are querying the Google Fit Store via the available fitness API and this is then dependant on what the App has had the ability to save via the recording API. So you may not see all of the data the device has available.

Google Fit APIs

I think, but don't know for certain, that the Fit App uses the sensors api. Within the App you can use the sensors API as described in the Google Docs Sensors API and manipulate the returned data as you desire.

Below shows a simple way to get steps using TYPE_STEP_COUNT_CUMULATIVE and TYPE_RAW

Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
            // At least one datatype must be specified.
            .setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
                    // Can specify whether data type is raw or derived.
            .setDataSourceTypes(DataSource.TYPE_RAW)
            .build())
            .setResultCallback(new ResultCallback<DataSourcesResult>() {
                @Override
                public void onResult(DataSourcesResult dataSourcesResult) {
                    Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
                    for (DataSource dataSource : dataSourcesResult.getDataSources()) {
                        Log.i(TAG, "Data source found: " + dataSource.toString());
                        Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());

                        //Let's register a listener to receive Activity data!
                        if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE) && mListener == null) {
                            Log.i(TAG, "Data source for TYPE_STEP_COUNT_CUMULATIVE found!  Registering.");
                            registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
                        }
                    }
                }
            });

private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {

    mListener = new OnDataPointListener() {
        @Override
        public void onDataPoint(DataPoint dataPoint) {
            for (Field field : dataPoint.getDataType().getFields()) {
                Value val = dataPoint.getValue(field);
                Log.i(TAG, "Detected DataPoint field: " + field.getName());
                Log.i(TAG, "Detected DataPoint value: " + val);

                Log.i(TAG, "Difference in steps: " + (val.asInt()-previousValue));

                previousValue = val.asInt();
            }
        }
    };

    Fitness.SensorsApi.add(
            mClient,
            new SensorRequest.Builder()
                    .setDataSource(dataSource) // Optional but recommended for custom data sets.
                    .setDataType(dataType) // Can't be omitted.
                    .setSamplingRate(10, TimeUnit.SECONDS)
                    .build(),
            mListener)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        Log.i(TAG, "Listener registered!");
                    } else {
                        Log.i(TAG, "Listener not registered.");
                    }
                }
            });
}

You may find this gives you a closer value to that given by the Fit App. However this is obviously only available on the device, so you would then need to run a background service that updated an external database, which is what the Recording and History APIs give you.

As a point of note to ensure that data continues to be sent to the Fitness Store when your app is in background you need to use the Recording API, this may also change the values you are seeing.

UPDATE:

Having written the above I thought I ought to test it. This was from a mornings walking.

  • Apple iPhone 6 HealthKit: 6,762
  • Apple iPhone 6 My App: 6,762
  • Android Nexus 6 Fit: 6,920
  • Android Nexus 6 My App: 6,920 (Uses the HistoryAPI)
  • Android Rest API estimated_steps: 6,928
  • Android Rest API merge_step_deltas: 6,911

This is from a Google+ post you can find here

"merge_step_deltas gives you the merged stream of all your step counters. estimated_steps also takes into account activity, and estimates steps when there are none"

The one I haven't got to the bottom of yet is the sensors using what I show above, it only gives me 2,548 steps.

The other marginally curious thing is that a day later Fit shows me I did 6,668 steps, so closer to the Apple result, but a recalculation from what it initially showed me after the data had synced. My app still shows 6,920!

The time for it all to sync I didn't measure.

like image 5
Longmang Avatar answered Oct 17 '22 03:10

Longmang