0

I'm getting the Google Fit distance for my app, but I noticed it includes cycling and running. Is there a way to get only the walked distance?

That's a sample for my application: https://github.com/francislainy/fit

enter image description here

// ----------- Google Fit Daily DISTANCE -----------
public static void subscribeDailyDistance() {


    Log.d(LOG_TAG, "subscribeDailyDistance was called");

    if (client != null) {

        // To create a subscription, invoke the Recording API.
        // As soon as the subscription is active, fitness data will start recording
        Fitness.RecordingApi.subscribe(client, DataType.TYPE_DISTANCE_DELTA)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(@NonNull Status status) {

                        if (status.isSuccess()) {

                            if (status.getStatusCode() == FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
                                Log.d(LOG_TAG, "Existing subscription for activity detected.");

                            } else {
                                Log.d(LOG_TAG, "Successfully subscribed");

                            }

                            // :)
                            readDistanceToday();

                        } else {
                            Log.e(LOG_TAG, "There was a problem subscribing");
                        }

                    }
                });

    }

}


public static class VerifyDataTaskDistance extends AsyncTask<GoogleApiClient, Void, Void> {

    float total = 0;

    protected Void doInBackground(GoogleApiClient... clients) {

        PendingResult<DailyTotalResult> result = Fitness.HistoryApi.readDailyTotal(clients[0], DataType.TYPE_DISTANCE_DELTA);
        DailyTotalResult totalResult = result.await(30, TimeUnit.SECONDS);
        if (totalResult.getStatus().isSuccess()) {
            DataSet totalSet = totalResult.getTotal();
            total = totalSet.isEmpty()
                    ? 0
                    : totalSet.getDataPoints().get(0).getValue(Field.FIELD_DISTANCE).asFloat();
        } else {
            Log.e(LOG_TAG, "There was a problem getting the distance count");
        }

        Log.i(LOG_TAG, "Total distance: " + total);


        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {

        // UI
        updateDistanceGoogle(total, MainActivity.mainActivity.getSupportFragmentManager());

    }

}

That's similar to this other SO question which hasn't got an answer for:

google fit sdk running distance

Thanks for your help. :)

PS: Adding extra code as per ginnyhuang's suggestion to use bucket by segment

 private static DataReadRequest getDataDistanceReadRequest(int numberOfDaysPast) {

    Calendar cal = new GregorianCalendar();
    cal.setTime(new Date());
    cal.add(Calendar.DAY_OF_YEAR, -numberOfDaysPast);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    long endTime = cal.getTimeInMillis();

    cal.add(Calendar.DAY_OF_YEAR, -1);

    long startTime = cal.getTimeInMillis();

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

    return new DataReadRequest.Builder()
            .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_DISTANCE_DELTA)
            //.bucketByTime(1, TimeUnit.DAYS) //todo
            .bucketByActivitySegment(7, TimeUnit.DAYS)
            .aggregate(DataType.TYPE_ACTIVITY_SEGMENT, DataType.AGGREGATE_ACTIVITY_SUMMARY)
            .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
            .build();

}

And

protected Void doInBackground(Integer... params) {

        daysIndex = params[0];

        DataReadRequest dataReadRequest = getDataDistanceReadRequest(daysIndex);

        // Invoke the History API to fetch the data with the query and await the result of
        // the read request.
        DataReadResult dataReadResult =
                Fitness.HistoryApi.readData(client, dataReadRequest).await(1, TimeUnit.MINUTES);

        List<Bucket> bucketList = dataReadResult.getBuckets();

        for (Bucket bucket : bucketList) {

            if (bucket.getActivity().equals("walking")) {

                dataSet = (bucket.getDataSet(DataType.TYPE_DISTANCE_DELTA));
            }
        }

        return null;
    }
Francislainy Campos
  • 3,462
  • 4
  • 33
  • 81
  • What object holds the distance values response being displayed in your UI? – ReyAnthonyRenacia Jun 08 '18 at 13:24
  • Hi @noogui, thank you for your reply. Not sure if I understood your question correctly, but the value I display for the distance on my UI comes from this line: `totalSet.getDataPoints().get(0).getValue(Field.FIELD_DISTANCE).asFloat();`. For some reason I keep getting the aggregate value. – Francislainy Campos Jun 08 '18 at 20:40
  • Hi @noogui. I've created a sample project similar to my application in case that may help? Thanks again for looking into it. :) – Francislainy Campos Jun 14 '18 at 13:47

1 Answers1

0

bucketByActivitySegment is the key to get results sort by acticity. You can get buckets sort by different type of acitivity.

The premise is that the stored value contains activity segment.

Here is the similar answer I've posted.

DataReadRequest readRequest = new DataReadRequest.Builder()
        .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA)
        .bucketByActivitySegment( 1, TimeUnit.MINUTES) // just segement time over 1 minute will be list 
        .setTimeRange(startTimeLong, endTimeLong, TimeUnit.MILLISECONDS)
        .enableServerQueries()
        .build();

Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context))
       .readData(readRequest)
       .addOnSuccessListener()
       .addOnFailureListener();
ginnyhuang
  • 63
  • 6
  • Hi @ginnyhuang, thanks very much for your reply. I've tried to use the bucketbysegment as per your suggestion and added my code to the description of the issue, but my dataset is now null? I tried also to keep the bucket by time and get its activity but it keeps returning 'in_vehicle' even though I only either walked or cycled. – Francislainy Campos Jun 15 '18 at 20:45
  • Did you start the motion detect by Google Fit? If you start the detection by yourself, you might lose something to record. The login and permission asked of mine are such different from yours. I'm not sure if it will affect. I do it with the guide in here: https://developers.google.com/fit/android/get-started. In FitnessOptions I was asked read/write permission for DataType.TYPE_ACTIVITY_SEGMENT, DataType.TYPE_ACTIVITY_SAMPLES. If you need distance you might add TYPE_DISTANCE_DELTA, AGGREGATE_DISTANCE_DELTA. – ginnyhuang Jun 19 '18 at 03:52
  • Thank you @ginnyhuang. Yes, it seems there's many code variations and my code is a bit different to the official documentation. Unfortunately really can't make this part work. `DataReadRequest readRequest = new DataReadRequest.Builder()` `.aggregate(ESTIMATED_STEP_DELTAS,DataType.AGGREGATE_DISTANCE_DELTA)` `.bucketByActivitySegment(7, TimeUnit.DAYS)` `.aggregate(ACTIVITY_SEGMENT,DataType.AGGREGATE_ACTIVITY_SUMMARY)` `.setTimeRange(startTime, endTime,` `TimeUnit.MILLISECONDS)` `.build();` Will keep working on that though. Thanks. – Francislainy Campos Jun 20 '18 at 19:53
  • Hi, no, I was never able to figure out how to do this no, sorry. – Francislainy Campos Oct 24 '20 at 21:58