Google Fit API for Android

6,124

Use Google Fit Rest Api in Flutter.

Google manages the data through data sources. To see all the data sources:

https://www.googleapis.com/fitness/v1/users/me/dataSources

To get Number of Steps: https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate Request body:

{    
    "aggregateBy" : [{    
        "dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"    
    }],    
    "bucketByTime": { "durationMillis": 86400000 }, // This is 24 hours    
    "startTimeMillis": 1546210381932,   // Start time    
    "endTimeMillis": 1547210381932  // End Time    
} 

You can use fitKit which is Flutter plugin for reading health and fitness data. Wraps HealthKit on iOS and GoogleFit on Android.

    import 'package:fit_kit/fit_kit.dart';

void read() async {
  final results = await FitKit.read(
    DataType.HEART_RATE,
    dateFrom: DateTime.now().subtract(Duration(days: 5)),
    dateTo: DateTime.now(),
  );
}

void readLast() async {
  final result = await FitKit.readLast(DataType.HEIGHT);
}

void readAll() async {
  if (await FitKit.requestPermissions(DataType.values)) {
    for (DataType type in DataType.values) {
      final results = await FitKit.read(
        type,
        dateFrom: DateTime.now().subtract(Duration(days: 5)),
        dateTo: DateTime.now(),
      );
    }
  }
}

If you are writing custom platform-specific code

Before you can invoke methods from the Google Fit APIs, you must connect to one or more of the following API clients, which are part of Google Play services:

  1. Sensors Client : Client which exposes different sources of fitness data in local and connected devices, and delivers live events to listeners.
  2. Recording Client : Client which enables low-power, always-on background collection of sensor data into the Google Fit store.
  3. History Client : Client for inserting, deleting, and reading data in Google Fit.
  4. Sessions Client : Client for creating and managing sessions of user activity in Google Fit.
  5. Goals Client : Client for reading fitness Goals created by users in Google Fit. BLE Client
  6. Config Client : Client for accessing custom data types and settings in Google Fit.

You must connect one of above.

    DataReadRequest readRequest = new DataReadRequest.Builder()
                .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                .bucketByTime(1, TimeUnit.DAYS)
                .enableServerQueries()
                .build();
// History Client 
        Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
                .readData(readRequest)
                .addOnSuccessListener(new OnSuccessListener<DataReadResponse>() {
                    @Override
                    public void onSuccess(DataReadResponse dataReadResponse) {
                        Log.d(TAG, "onSuccess()");
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "onFailure()", e);
                    }
                })
                .addOnCompleteListener(new OnCompleteListener<DataReadResponse>() {
                    @Override
                    public void onComplete(@NonNull Task<DataReadResponse> task) {
                        Log.d(TAG, "onComplete()");
                    }
                });

Example for getting Heart Rate from History Client:

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.FitnessOptions;
import com.google.android.gms.fitness.data.Bucket;
import com.google.android.gms.fitness.data.DataPoint;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.request.DataReadRequest;
import com.google.android.gms.fitness.result.DataReadResponse;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;


import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class googleFitData extends AppCompatActivity {

    private static final String TAG = "googleFitData";
    private static final int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 2;
    private static final int PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION = 3;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_smart_wacth);


        String[] PERMISSIONS = {
                Manifest.permission.ACTIVITY_RECOGNITION
        };


        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION)
                    != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(this,
                        PERMISSIONS,
                        PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION);
            }
        } else {
            googleSignin();

        }


    }

    public void googleSignin() {
        FitnessOptions fitnessOptions = FitnessOptions.builder()
                .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
                .build();
        if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
            GoogleSignIn.requestPermissions(
                    this, // your activity
                    GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
                    GoogleSignIn.getLastSignedInAccount(this),
                    fitnessOptions);
        } else {
            accessGoogleFit();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (GOOGLE_FIT_PERMISSIONS_REQUEST_CODE == requestCode) {

                accessGoogleFit();
            }
            if (PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION == requestCode) {

                accessGoogleFit();
            }
        } else {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

        }

    }

    private void accessGoogleFit() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        long endTime = cal.getTimeInMillis();
        cal.add(Calendar.YEAR, -1);
        long startTime = cal.getTimeInMillis();


        DataReadRequest readRequest = new DataReadRequest.Builder()
                .read(DataType.TYPE_HEART_RATE_BPM)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                .bucketByTime(365, TimeUnit.DAYS)
                .build();


        Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
                .readData(readRequest)
                .addOnSuccessListener(new OnSuccessListener<DataReadResponse>() {
                    @Override
                    public void onSuccess(DataReadResponse dataReadResponse) {
                        Log.d(TAG, "onSuccess()");

                        for (Bucket bucket : dataReadResponse.getBuckets()) {
                            Log.e("History", "Data returned for Data type: " + bucket.getDataSets());

                            List<DataSet> dataSets = bucket.getDataSets();
                            for (DataSet dataSet : dataSets) {
                                showDataSet(dataSet);
                            }
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "onFailure()", e);
                    }
                })
                .addOnCompleteListener(new OnCompleteListener<DataReadResponse>() {
                    @Override
                    public void onComplete(@NonNull Task<DataReadResponse> task) {
                        Log.d(TAG, "onComplete()");
                    }
                });
    }

    private void showDataSet(DataSet dataSet) {
        DateFormat dateFormat = DateFormat.getDateInstance();
        DateFormat timeFormat = DateFormat.getTimeInstance();

        for (DataPoint dp : dataSet.getDataPoints()) {
            Log.e("History", "Data point:");
            Log.e("History", "\tType: " + dp.getDataType().getName());
            Log.e("History", "\tStart: " + dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)) + " " + timeFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
            Log.e("History", "\tEnd: " + dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS)) + " " + timeFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());


                for (Field field : dp.getDataType().getFields()) {

                    Log.e("History", "\tField: " + field.getName() +
                            " Value: " + dp.getValue(field));

                }




        }
    }


}
Share:
6,124
desancheztorres
Author by

desancheztorres

Updated on December 16, 2022

Comments

  • desancheztorres
    desancheztorres over 1 year

    Google Fit and Flutter

    I am following this documentation from Google: Google Fit

    I don't understand step 5. I am not an Android developer and I have no idea where to locate the code. Step 5

    For example, it says:

    Before you can invoke methods from the Google Fit APIs, you must connect to one or more of the following API clients, which are part of Google Play services:

    • Sensors Client
    • Recording Client
    • History Client
    • Sessions Client
    • Goals Client
    • BLE Client
    • Config Client

    Now, I try to connect the first one SensorsClient

    But I don't know where to locate the code, which file? I am a flutter developer and I need help in step 5.

    build.grandle

    dependencies {
        implementation 'com.google.android.gms:play-services-fitness:18.0.0'
        implementation 'com.google.android.gms:play-services-auth:17.0.0'
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    }
    
  • desancheztorres
    desancheztorres over 4 years
    Where is this code, which file? Android project? MainFile? DataReadRequest readRequest = new DataReadRequest.Builder() .... Tis is my problem where can I locate the code above? It's because I am not a Android Developer.
  • desancheztorres
    desancheztorres over 4 years
    I am working on Flutter, I have no idea about Android native, that's why I can't understand the step 5 on the doc.
  • Junaid
    Junaid over 4 years
    Check tha answer i have added example
  • Junaid
    Junaid over 4 years
  • grooot
    grooot over 3 years
    @John so in order to use "DataType.TYPE_HEART_RATE_BPM" do we need to get the app verified by google?
  • Junaid
    Junaid over 3 years
    No i used it without google app verification