Fetch active calories burned from Google Fit Android API

IMPORTANT : For Updated and Simplified code to fetch calories and steps for a particular date check this Article
Google Fit Continued
In the previous post we have seen how to fetch daily total calories and steps using the Google fit API. The daily total calories obtained is unfiltered and contains both active as well as inactive calories.
In this post we will see how to filter out active calories (calories consumed while Running and Walking) for a particular date.
Like the previous post, we will be using the History API to fetch active calories.
Create Google API Client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
// Create the Google API Client GoogleApiClient mClient1 = new GoogleApiClient.Builder(this) .addApi(Fitness.HISTORY_API) .addApi(Fitness.CONFIG_API) .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ)) .useDefaultAccount() .addConnectionCallbacks( new GoogleApiClient.ConnectionCallbacks() { @Override public void onConnected(Bundle bundle) { //fetch calories for a date fetchUserGoogleFitData(selecteddate); } @Override public void onConnectionSuspended(int i) { // If your connection to the sensor gets lost at some point, // you'll be able to determine the reason and react to it here. if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) { Log.i(TAG, "Connection lost. Cause: Network Lost."); } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) { Log.i(TAG, "Connection lost. Reason: Service Disconnected"); } } } ).addOnConnectionFailedListener( new GoogleApiClient.OnConnectionFailedListener() { // Called whenever the API client fails to connect. @Override public void onConnectionFailed(ConnectionResult result) { Log.i(TAG, "Connection failed. Cause: " + result.toString()); if (!result.hasResolution()) { // Show the localized error dialog GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), RevoBaseActivity.this, 0).show(); return; } // The failure has a resolution. Resolve it. // Called typically when the app is not yet authorized, and an // authorization dialog is displayed to the user. if (!authInProgress) { try { Log.i(TAG, "Attempting to resolve failed connection"); authInProgress = true; result.startResolutionForResult(RevoBaseActivity.this, REQUEST_OAUTH); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Exception while starting resolution activity", e); } } } } ).build(); mClient1.connect(); |
When API client is connected, we will call
1 2 3 4 5 6 |
//fetch calories for a date fetchUserGoogleFitData(selecteddate); |
The date is passed for which the burned calories is to be fetched.
1 2 3 4 5 6 7 |
c = Calendar.getInstance(); dateformat = new SimpleDateFormat("yyyy-MM-dd"); selecteddate = dateformat.format(c.getTime()); |
Below is the code for fetchUserGoogleFitData
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public void fetchUserGoogleFitData(String date) { if (mClient1 != null && mClient1.isConnected()) { Date d1 = null; try{ d1 = todaydateformat.parse(date); }catch (Exception e){ } Calendar calendar = Calendar.getInstance(); try{ calendar.setTime(d1); }catch (Exception e){ calendar.setTime(new Date()); } DataReadRequest readRequest = queryDateFitnessData(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)); new GetCaloriesAsyncTask(readRequest, mClient1).execute(); } } |
Build the DataReadRequest to query the fitness data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
private DataReadRequest queryDateFitnessData(int year, int month, int day_of_Month) { Calendar startCalendar = Calendar.getInstance(Locale.getDefault()); startCalendar.set(Calendar.YEAR, year); startCalendar.set(Calendar.MONTH, month); startCalendar.set(Calendar.DAY_OF_MONTH, day_of_Month); startCalendar.set(Calendar.HOUR_OF_DAY, 23); startCalendar.set(Calendar.MINUTE, 59); startCalendar.set(Calendar.SECOND, 59); startCalendar.set(Calendar.MILLISECOND, 999); long endTime = startCalendar.getTimeInMillis(); startCalendar.set(Calendar.HOUR_OF_DAY, 0); startCalendar.set(Calendar.MINUTE, 0); startCalendar.set(Calendar.SECOND, 0); startCalendar.set(Calendar.MILLISECOND, 0); long startTime = startCalendar.getTimeInMillis(); return new DataReadRequest.Builder() // The data request can specify multiple data types to return, effectively // combining multiple data queries into one call. // In this example, it's very unlikely that the request is for several hundred // datapoints each consisting of a few steps and a timestamp. The more likely // scenario is wanting to see how many steps were walked per day, for 7 days. //.aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA) //.aggregate(DataType.TYPE_CALORIES_EXPENDED,DataType.AGGREGATE_CALORIES_EXPENDED) .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED) // .read(DataType.TYPE_CALORIES_EXPENDED) // Analogous to a "Group By" in SQL, defines how data should be aggregated. // bucketByTime allows for a time span, whereas bucketBySession would allow // bucketing by "sessions", which would need to be defined in code. //.bucketByTime(1, TimeUnit.DAYS) .bucketByActivitySegment(1, TimeUnit.MILLISECONDS) .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS) .build(); } |
Pass the DataReadRequest object to AsyncTask GetCaloriesAsyncTask
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class GetCaloriesAsyncTask extends AsyncTask<Void, Void, DataReadResult> { DataReadRequest readRequest; String TAG = GetCaloriesAsyncTask.class.getName(); GoogleApiClient mClient = null; public GetCaloriesAsyncTask(DataReadRequest dataReadRequest_, GoogleApiClient googleApiClient) { this.readRequest = dataReadRequest_; this.mClient = googleApiClient; } @Override protected DataReadResult doInBackground(Void... params) { return HistoryApi.readData(mClient, readRequest).await(1, TimeUnit.MINUTES); } @Override protected void onPostExecute(DataReadResult dataReadResult) { super.onPostExecute(dataReadResult); printData(dataReadResult); } |
printData(dataReadResult) Here the Buckets are extracted from the Result. From Buckets we get DataSets from which the calories are fetched. Here we are filtering out buckets that contain Walking and Running Activities.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
private void printData(DataReadResult dataReadResult) { // [START parse_read_data_result] // If the DataReadRequest object specified aggregated data, dataReadResult will be returned // as buckets containing DataSets, instead of just DataSets. if (dataReadResult.getBuckets().size() > 0) { Log.e(TAG, "Number of returned buckets of DataSets is: "+ dataReadResult.getBuckets().size()); for (Bucket bucket : dataReadResult.getBuckets()) { String bucketActivity = bucket.getActivity(); if (bucketActivity.contains(FitnessActivities.WALKING) || bucketActivity.contains(FitnessActivities.RUNNING)) { Log.e(TAG, "bucket type->" + bucket.getActivity()); List<DataSet> dataSets = bucket.getDataSets(); for (DataSet dataSet : dataSets) { dumpDataSet(dataSet); } } } // expendedCalories => total active calories Log.e(TAG, "BurnedCalories->" + String.valueOf(expendedCalories)); } else if (dataReadResult.getDataSets().size() > 0) { Log.e(TAG, "Number of returned DataSets is: " + dataReadResult.getDataSets().size()); for (DataSet dataSet : dataReadResult.getDataSets()) { dumpDataSet(dataSet); } } // [END parse_read_data_result] } // [START parse_dataset] private void dumpDataSet(DataSet dataSet) { Log.e(TAG, "Data returned for Data type: " + dataSet.getDataType().getName()); for (DataPoint dp : dataSet.getDataPoints()) { if (dp.getEndTime(TimeUnit.MILLISECONDS) > dp.getStartTime(TimeUnit.MILLISECONDS)) { for (Field field : dp.getDataType().getFields()) { expendedCalories = expendedCalories + dp.getValue(field).asFloat(); } } } } } |
The Total Active calories can be get from expendedCalories
1 2 3 4 5 6 |
// expendedCalories => total active calories Log.e(TAG, "BurnedCalories->" + String.valueOf(expendedCalories)); |
Follow GadgetSaint on Facebook / Twitter for updates.
Hope you find this tutorial helpful. In case of Doubts please feel free to comment. Thanks 🙂
Wanna start your blog or site in 5 mins? Check out Official WordPress recommended web hosting Bluehost.
Do u have a git.hub link for the entire code? I am missing something because the selectedDate and expendedCalories are giving me an error *cannot resolve symbol*
Right now there is no Github link for this tutorial. I will add it soon.
how can i get week wise or month wise data from google fit ?
please guide me
Hey, this code is very helpful but it gives me the inactive + active calories. I want only the active calories using Google fit, how can i get it.
Calories received from API response and in G-fit app DO NOT MATCH.
when I debugged, I found that start date and end date remains same while fetching steps. However, it changes while fetching calories. I’m not setting any date. I’m just fetching date using : dp.getStartTime(TimeUnit.MILLISECONDS) & dp.getEndTime(TimeUnit.MILLISECONDS).
Any idea why??
how can I fix this??
Thanks so much for this. Saved my life