androidandroid-studiogoogle-fitgoogle-fit-sdkgoogle-fit-api

Weekly Steps Retrieved through Google Fit Android API doesn't match with steps displayed in Google Fit Official App


I am trying to retreive user's weekly steps data from google fit API but I am getting different steps count result from official google fit App data. for example : steps retrieved through google fit api for thursday are 5244 while in official google fit app the count for thursday's step is 5134. Steps count for every day of the week is a little different but I want exact results. I am using google fit History API to retrieve weekly steps count and display in a bar chart. My code looks like this:

    fitnessOptions = FitnessOptions.builder()
            .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.TYPE_LOCATION_SAMPLE, FitnessOptions.ACCESS_READ)
            .build();

    @RequiresApi(api = Build.VERSION_CODES.O)
private void invokeHistoryApiForWeeklySteps() {


    // Read the data that's been collected throughout the past week.
    ZonedDateTime endTime = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        endTime = LocalDateTime.now().atZone(ZoneId.systemDefault());
    }
    ZonedDateTime startTime = endTime.minusWeeks(1);

    Log.i(TAG, "Range Start: $startTime");
    Log.i(TAG, "Range End: $endTime");

    DataSource ESTIMATED_STEP_DELTAS = new DataSource.Builder()
            .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
            .setType(DataSource.TYPE_DERIVED)
            .setStreamName("estimated_steps")
            .setAppPackageName("com.google.android.gms")
            .build();

    DataReadRequest readRequest = new DataReadRequest.Builder()
            .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_STEP_COUNT_DELTA)
            .bucketByTime(1, TimeUnit.DAYS)
            .setTimeRange(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
            .enableServerQueries()
            .build();


    Fitness.getHistoryClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
            .readData(readRequest)
            .addOnSuccessListener(response -> {


                // The aggregate query puts datasets into buckets, so convert to a
                // single list of datasets
                for (Bucket bucket : response.getBuckets()) {

                    //convert days in bucket to milliseconds
                    long days = bucket.getStartTime(TimeUnit.MILLISECONDS);
                    //convert milliseconds to date
                    Date stepsDate = new Date(days);
                    //convert date to day of the week eg: monday, tuesday etc
                    @SuppressLint("SimpleDateFormat")
                    DateFormat df = new SimpleDateFormat("EEE");
                    String weekday = df.format(stepsDate);

                    Log.i(TAG, stepsDate.toString());
                    theDates.add(weekday);

                    for (DataSet dataSet : bucket.getDataSets()) {
                        totalAvgSteps.add(dumpDataSet(dataSet));



                    }
                }
                Log.i(TAG, theDates.toString());
                Log.i(TAG, totalAvgSteps.toString());
                displayBarChart();
            })
            .addOnFailureListener(e ->
                    Log.w(TAG, "There was an error reading data from Google Fit", e));

}

    private int dumpDataSet(DataSet dataSet) {
    Log.i(TAG, "Data returned for Data type: ${dataSet.dataType.name}");
    int totalSteps = 0;
    for (DataPoint dp : dataSet.getDataPoints()) {
        Log.i(TAG, "Data point:");
        Log.i(TAG, "\tType: ${dp.dataType.name}");
        Log.i(TAG, "\tStart: ${dp.getStartTimeString()}");
        Log.i(TAG, "\tEnd: ${dp.getEndTimeString()}");


        for (Field field : dp.getDataType().getFields()) {
            String fieldName = field.getName();
            totalSteps += dp.getValue(field).asInt();

            Log.i(TAG, "\tfield: " + fieldName + "value: " + dp.getValue(field));

        }
    }
    return totalSteps;
}

Here is what I get in result by this code:

My Code Result:

enter image description here

And this is what data looks like in google Fit Official App

Steps Count In Google Fit App:

enter image description here

Steps Count in Google Fit App:

enter image description here


Solution

  • So I fixed the problem of steps count difference and thus sharing here if it can help someone else as well. The mistake I was doing is I wasn't calculating the data from yesterday's midnight 12:00 am to last week's midnight 12:00 am which caused the difference in the number of steps for every day. Here is the right date and time calculation:

      Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.set(Calendar.HOUR_OF_DAY,0);
        cal.set(Calendar.MINUTE,0);
        cal.set(Calendar.SECOND,0);
        long endTime = cal.getTimeInMillis();
    
        cal.add(Calendar.WEEK_OF_MONTH, -1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        long startTime = cal.getTimeInMillis();
        Log.i(TAG, String.valueOf(endTime));
        Log.i(TAG,String.valueOf(startTime) );
    

    and We need to change the data request a little bit where I was requesting it in seconds now I am requesting that in milliseconds which is giving me the exact data as google fit official app.

     DataReadRequest readRequest = new DataReadRequest.Builder()
                .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_STEP_COUNT_DELTA)
                .bucketByTime(1, TimeUnit.DAYS)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                .build();
    

    The rest of the code is as it is as I posted it in the question.