0

So I'm trying to find the calories burned for activities using Google Fit for a month and displaying the information but it's taking an extremely long time (about 45 seconds). What I'm doing is retrieving all the activities done by the user over that time period and creating another read request for calories expended during the time period for each activity. I know this is a pretty bad way to do it, but I can't think of any other way.

@Override
            protected ArrayList<DayActivities> doInBackground(Void... params)
            {
                Calendar cal = Calendar.getInstance();
                Date now = new Date();
                cal.setTime(now);
                cal.set(Calendar.DAY_OF_MONTH, 30);
                cal.add(Calendar.MONTH, -1);
                int currTime;
                ArrayList<CalorieActivity> activityList = new ArrayList<>();

                long endTime = cal.getTimeInMillis();
                SetCalendar.setLessOneMonth(cal);
                long startTime = cal.getTimeInMillis();

                DataReadRequest readRequest = ReadRequestFactory.getActivityReadRequest(startTime, endTime);
                DataReadResult dataReadResult = Fitness.HistoryApi.readData(mClient, readRequest).await(1, TimeUnit.MINUTES);

                if (dataReadResult.getBuckets().size() > 0)
                {
                    Log.i("MyApp", "Number of returned buckets of DataSets is: "
                            + dataReadResult.getBuckets().size());
                    for (Bucket bucket : dataReadResult.getBuckets())
                    {
                        List<DataSet> dataSets = bucket.getDataSets();
                        for (DataSet dataSet : dataSets)
                        {
                            Calendar startDate;
                            Calendar endDate;
                            DayActivities currActivity;
                            Date date;

                            for (DataPoint dp : dataSet.getDataPoints())
                            {
                                startDate = Calendar.getInstance();
                                endDate = Calendar.getInstance();
                                currActivity = new DayActivities();
                                CalorieActivity calorieActivity = new CalorieActivity();

                                startDate.setTime(new Date(dp.getStartTime(TimeUnit.MILLISECONDS)));
                                currActivity.setStartDate(startDate);
                                calorieActivity.setStartDate(startDate);
                                currTime = startDate.get(Calendar.DAY_OF_MONTH);
                                endDate.setTime(new Date(dp.getEndTime(TimeUnit.MILLISECONDS)));
                                currActivity.setEndDate(endDate);
                                calorieActivity.setEndDate(endDate);

                                for (Field field : dp.getDataType().getFields())
                                {
                                    if (field.getName().equals("activity"))
                                    {
                                        calorieActivity.setActivity(ActivityTypes.findActivity(Integer.parseInt(dp.getValue(field).toString())));
                                        calorieActivity.setActivityNumber(Integer.parseInt(dp.getValue(field).toString()));
                                    }
                                }

                                cal.setTime(calorieActivity.getStartDate().getTime());
                                startTime = cal.getTimeInMillis();
                                cal.setTime(calorieActivity.getEndDate().getTime());
                                endTime = cal.getTimeInMillis();

                                DataReadRequest readRequest2 = ReadRequestFactory.getCaloriesReadRequest(startTime, endTime);
                                DataReadResult dataReadResult2 = Fitness.HistoryApi.readData(mClient, readRequest2).await(1, TimeUnit.MINUTES);

                                for (Bucket bucket2 : dataReadResult2.getBuckets())
                                {
                                    List<DataSet> dataSets2 = bucket2.getDataSets();
                                    for (DataSet dataSet2 : dataSets2)
                                    {
                                        for (DataPoint dp2 : dataSet2.getDataPoints())
                                        {
                                            for (Field field2 : dp2.getDataType().getFields())
                                            {
                                                if (field2.getName().equals("calories"))
                                                {
                                                    calorieActivity.setCalorie((int) Double.parseDouble(dp2.getValue(field2).toString()));
                                                }
                                            }
                                        }
                                    }
                                }


                                boolean added = false;
                                for(int j=0; j<dayActivities.size(); j++)
                                {
                                    DayActivities currDay = dayActivities.get(j);
                                    if(currActivity.getStartDate().get(Calendar.DAY_OF_MONTH) == currDay.getStartDate().get(Calendar.DAY_OF_MONTH))
                                    {
                                        currDay.addActivity(calorieActivity);
                                        added = true;
                                    }
                                }
                                if(!added)
                                {
                                    DayActivities newDay = new DayActivities();
                                    Calendar start = Calendar.getInstance();
                                    start.setTime(currActivity.getStartDate().getTime());
                                    Calendar end = Calendar.getInstance();
                                    end.setTime(currActivity.getEndDate().getTime());
                                    SetCalendar.setStartTime(start);
                                    SetCalendar.setEndTime(end);
                                    newDay.setStartDate(start);
                                    newDay.setEndDate(end);
                                    newDay.addActivity(calorieActivity);
                                    dayActivities.add(newDay);
                                }
                            }
                        }
                    }
                }
                else
                {
                    Log.i("MyApp", "No data");
                }
                Log.i("MyApp", "We're done here");
                return dayActivities;
            }

As you can see there's an unreasonable number of for loops, this is because I have to find all the activities, which takes three for loops, then I need to find the calories burned for each activity, which (for each activity) takes another three for loops. It's ridiculous, but I can't find any other way of doing this.

user292277
  • 101
  • 2
  • 5
  • Try to check this following SO questions : [Google Fit API, getting calories burned per activity](http://stackoverflow.com/questions/37820404/google-fit-api-getting-calories-burned-per-activity) and [Calories expenditure using google fit api](http://stackoverflow.com/questions/32123898/calories-expenditure-using-google-fit-api). Hope this helps – Mr.Rebot Jul 06 '16 at 14:53
  • Two of those are mine, actually. I haven't been able to get a good answer since I've started working on this project. But thanks for trying anyway :( – user292277 Jul 07 '16 at 14:12

1 Answers1

0

Redoing my answer: I tried out myself getting aggregate calories expended for a month's worth of activities. First, here's the request I used:

new DataReadRequest.Builder()
        .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
        .bucketByActivitySegment(5, TimeUnit.MINUTES)
        .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
        .build();

It's pretty self-explanatory. I make a request for the aggregated calories expended per activity (aggregate and bucketByActivitySegment), setting the minimum time for an activity to 5 minutes. The time range is set for 1 month and it returned a lot of information very quickly (< 5 seconds, no worries about timeout).

So that will give you the calories expended per activity (defined by a minimum of 5 minutes) and you can get what type of activity it is by Bucket.getActivity() which returns a String.

Matthew Woo
  • 1,288
  • 15
  • 28