How to get step count from Google Fit REST API like Google Fit app?
Solution 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
- 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.
- 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.
Solution 2:
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.
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.