diff --git a/app/src/main/assets/activity_stacked.svg b/app/src/main/assets/activity_stacked.svg
new file mode 100644
index 000000000..882ecdd75
--- /dev/null
+++ b/app/src/main/assets/activity_stacked.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/app/src/main/assets/ic_intensity_hollow.svg b/app/src/main/assets/ic_intensity_hollow.svg
new file mode 100644
index 000000000..0fa7d66a1
--- /dev/null
+++ b/app/src/main/assets/ic_intensity_hollow.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/app/src/main/assets/ic_shoe_prints_many.svg b/app/src/main/assets/ic_shoe_prints_many.svg
new file mode 100644
index 000000000..3462b3820
--- /dev/null
+++ b/app/src/main/assets/ic_shoe_prints_many.svg
@@ -0,0 +1,70 @@
+
+
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingAdapter.java
index 70095e535..cac1e5e23 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingAdapter.java
@@ -1,59 +1,273 @@
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.github.mikephil.charting.charts.PieChart;
+import com.github.mikephil.charting.data.PieData;
+import com.github.mikephil.charting.data.PieDataSet;
+import com.github.mikephil.charting.data.PieEntry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;
+import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.AbstractActivityListingAdapter;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
-public class ActivityListingAdapter extends AbstractActivityListingAdapter {
+public class ActivityListingAdapter extends AbstractActivityListingAdapter {
+ public static final String ACTIVE_STEPS_CHART_COLOR = "#3498db";
+ public static final String DISTANCE_CHART_COLOR = "#f1c40f";
+ public static final String ACTIVE_TIME_CHART_COLOR = "#e74c3c";
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractWeekChartFragment.class);
+ private final int SESSION_SUMMARY = ActivitySession.SESSION_SUMMARY;
+ ActivityUser activityUser = new ActivityUser();
+ int stepsGoal = activityUser.getStepsGoal();
+ int distanceMeters = activityUser.getDistanceMeters();
+ long activeTimeMillis = activityUser.getActiveTimeMinutes() * 60 * 1000L;
+
public ActivityListingAdapter(Context context) {
super(context);
}
@Override
- protected String getDateLabel(StepAnalysis.StepSession item) {
+ protected View fill_dashboard(ActivitySession item, int position, View view, ViewGroup parent, Context context) {
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ view = inflater.inflate(R.layout.activity_list_dashboard_item, parent, false);
+
+ PieChart ActiveStepsChart;
+ PieChart DistanceChart;
+ PieChart ActiveTimeChart;
+
+ ActiveStepsChart = view.findViewById(R.id.activity_dashboard_piechart1);
+ setUpChart(ActiveStepsChart);
+ setStepsData(item, ActiveStepsChart, context);
+
+ DistanceChart = view.findViewById(R.id.activity_dashboard_piechart2);
+ setUpChart(DistanceChart);
+ setDistanceData(item, DistanceChart, context);
+
+ ActiveTimeChart = view.findViewById(R.id.activity_dashboard_piechart3);
+ setUpChart(ActiveTimeChart);
+ setDurationData(item, ActiveTimeChart, context);
+
+ TextView stepLabel = view.findViewById(R.id.line_layout_step_label);
+ TextView stepTotalLabel = view.findViewById(R.id.line_layout_total_step_label);
+
+ TextView distanceLabel = view.findViewById(R.id.line_layout_distance_label);
+
+ TextView hrLabel = view.findViewById(R.id.heartrate_widget_label);
+
+ TextView intensityLabel = view.findViewById(R.id.intensity_widget_label);
+ TextView intensity2Label = view.findViewById(R.id.line_layout_intensity2_label);
+
+
+ TextView durationLabel = view.findViewById(R.id.line_layout_duration_label);
+ TextView sessionCountLabel = view.findViewById(R.id.line_layout_count_label);
+
+ LinearLayout durationLayout = view.findViewById(R.id.line_layout_duration);
+ LinearLayout countLayout = view.findViewById(R.id.line_layout_count);
+
+
+ View hrLayout = view.findViewById(R.id.heartrate_widget_icon);
+ LinearLayout stepsLayout = view.findViewById(R.id.line_layout_step);
+ LinearLayout stepsTotalLayout = view.findViewById(R.id.line_layout_total_step);
+
+
+ LinearLayout distanceLayout = view.findViewById(R.id.line_layout_distance);
+ View intensityLayout = view.findViewById(R.id.intensity_widget_icon);
+ View intensity2Layout = view.findViewById(R.id.line_layout_intensity2);
+
+ stepLabel.setText(getStepLabel(item));
+ stepTotalLabel.setText(getStepTotalLabel(item));
+
+ distanceLabel.setText(getDistanceLabel(item));
+ hrLabel.setText(getHrLabel(item));
+ intensityLabel.setText(getIntensityLabel(item));
+ intensity2Label.setText(getIntensityLabel(item));
+ durationLabel.setText(getDurationLabel(item));
+ sessionCountLabel.setText(getSessionCountLabel(item));
+
+ if (!hasHR(item)) {
+ hrLayout.setVisibility(View.GONE);
+ hrLabel.setVisibility(View.GONE);
+ } else {
+ hrLayout.setVisibility(View.VISIBLE);
+ hrLabel.setVisibility(View.VISIBLE);
+ }
+
+ if (!hasIntensity(item)) {
+ intensityLayout.setVisibility(View.GONE);
+ intensity2Layout.setVisibility(View.GONE);
+ intensityLabel.setVisibility(View.GONE);
+ intensity2Label.setVisibility(View.GONE);
+ } else {
+ intensityLayout.setVisibility(View.VISIBLE);
+ intensity2Layout.setVisibility(View.VISIBLE);
+ intensityLabel.setVisibility(View.VISIBLE);
+ intensity2Label.setVisibility(View.VISIBLE);
+ }
+
+ if (!hasDistance(item)) {
+ distanceLayout.setVisibility(View.GONE);
+ } else {
+ distanceLayout.setVisibility(View.VISIBLE);
+ }
+
+ if (!hasSteps(item)) {
+ stepsLayout.setVisibility(View.GONE);
+ } else {
+ stepsLayout.setVisibility(View.VISIBLE);
+ }
+
+ if (!hasTotalSteps(item)) {
+ stepsTotalLayout.setVisibility(View.GONE);
+ countLayout.setVisibility(View.GONE);
+ durationLayout.setVisibility(View.GONE);
+ } else {
+ stepsTotalLayout.setVisibility(View.VISIBLE);
+ countLayout.setVisibility(View.VISIBLE);
+ durationLayout.setVisibility(View.VISIBLE);
+ }
+
+ return view;
+ }
+
+ private void setStepsData(ActivitySession item, PieChart DashboardChart, Context context) {
+ ArrayList entries = new ArrayList<>();
+ int steps = item.getActiveSteps();
+ entries.add(new PieEntry((float) steps));
+
+ if (steps < stepsGoal) {
+ entries.add(new PieEntry((float) (stepsGoal - steps)));
+ }
+
+ DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (steps * 100 / stepsGoal), context.getString(R.string.activity_list_summary_active_steps)));
+
+ PieDataSet dataSet = new PieDataSet(entries, "");
+ dataSet.setSliceSpace(0f);
+ dataSet.setSelectionShift(5f);
+
+ dataSet.setColors(Color.parseColor(ACTIVE_STEPS_CHART_COLOR), Color.LTGRAY);
+ PieData data = new PieData(dataSet);
+ data.setValueTextSize(0f);
+ data.setValueTextColor(Color.WHITE);
+ DashboardChart.setData(data);
+ DashboardChart.invalidate();
+ }
+
+ private void setDistanceData(ActivitySession item, PieChart DashboardChart, Context context) {
+ ArrayList entries = new ArrayList<>();
+ float distance = item.getDistance();
+ entries.add(new PieEntry(distance));
+
+ if (distance < distanceMeters) {
+ entries.add(new PieEntry((float) (distanceMeters - distance)));
+ }
+
+ DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (distance * 100 / distanceMeters), context.getString(R.string.distance)));
+ PieDataSet dataSet = new PieDataSet(entries, "");
+ dataSet.setSliceSpace(0f);
+ dataSet.setSelectionShift(5f);
+
+ dataSet.setColors(Color.parseColor(DISTANCE_CHART_COLOR), Color.LTGRAY);
+ PieData data = new PieData(dataSet);
+ data.setValueTextSize(0f);
+ data.setValueTextColor(Color.WHITE);
+ DashboardChart.setData(data);
+ DashboardChart.invalidate();
+ }
+
+ private void setDurationData(ActivitySession item, PieChart DashboardChart, Context context) {
+ ArrayList entries = new ArrayList<>();
+ long duration = item.getEndTime().getTime() - item.getStartTime().getTime();
+ entries.add(new PieEntry((float) duration));
+
+ if (duration < activeTimeMillis) {
+ entries.add(new PieEntry((float) (activeTimeMillis - duration)));
+ }
+
+ DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (duration * 100 / activeTimeMillis), context.getString(R.string.activity_list_summary_active_time)));
+ PieDataSet dataSet = new PieDataSet(entries, "");
+ dataSet.setSliceSpace(0f);
+ dataSet.setSelectionShift(5f);
+ dataSet.setColors(Color.parseColor(ACTIVE_TIME_CHART_COLOR), Color.LTGRAY);
+ PieData data = new PieData(dataSet);
+ data.setValueTextSize(0f);
+ data.setValueTextColor(Color.WHITE);
+ DashboardChart.setData(data);
+ DashboardChart.invalidate();
+ }
+
+ private void setUpChart(PieChart DashboardChart) {
+ DashboardChart.setNoDataText("");
+ DashboardChart.getLegend().setEnabled(false);
+ DashboardChart.setDrawHoleEnabled(true);
+ DashboardChart.setHoleColor(Color.WHITE);
+ DashboardChart.getDescription().setText("");
+ DashboardChart.setTransparentCircleColor(Color.WHITE);
+ DashboardChart.setTransparentCircleAlpha(110);
+ DashboardChart.setHoleRadius(70f);
+ DashboardChart.setTransparentCircleRadius(75f);
+ DashboardChart.setDrawCenterText(true);
+ DashboardChart.setRotationEnabled(true);
+ DashboardChart.setHighlightPerTapEnabled(true);
+ DashboardChart.setCenterTextOffset(0, 0);
+ }
+
+ @Override
+ protected String getDateLabel(ActivitySession item) {
return "";
}
@Override
- protected boolean hasGPS(StepAnalysis.StepSession item) {
+ protected boolean hasGPS(ActivitySession item) {
return false;
}
@Override
- protected boolean hasDate(StepAnalysis.StepSession item) {
+ protected boolean hasDate(ActivitySession item) {
return false;
}
@Override
- protected String getTimeFrom(StepAnalysis.StepSession item) {
+ protected String getTimeFrom(ActivitySession item) {
Date time = item.getStartTime();
return DateTimeUtils.formatTime(time.getHours(), time.getMinutes());
}
@Override
- protected String getTimeTo(StepAnalysis.StepSession item) {
+ protected String getTimeTo(ActivitySession item) {
Date time = item.getEndTime();
return DateTimeUtils.formatTime(time.getHours(), time.getMinutes());
}
@Override
- protected String getActivityName(StepAnalysis.StepSession item) {
+ protected String getActivityName(ActivitySession item) {
return ActivityKind.asString(item.getActivityKind(), getContext());
}
@Override
- protected String getStepLabel(StepAnalysis.StepSession item) {
- return String.valueOf(item.getSteps());
+ protected String getStepLabel(ActivitySession item) {
+ return String.valueOf(item.getActiveSteps());
}
@Override
- protected String getDistanceLabel(StepAnalysis.StepSession item) {
+ protected String getDistanceLabel(ActivitySession item) {
float distance = item.getDistance();
String unit = "###m";
if (distance > 2000) {
@@ -61,69 +275,74 @@ public class ActivityListingAdapter extends AbstractActivityListingAdapter 0) {
- return true;
- } else {
- return false;
- }
+ protected String getSessionCountLabel(ActivitySession item) {
+ return String.valueOf(item.getSessionCount());
}
@Override
- public boolean hasIntensity(StepAnalysis.StepSession item) {
- if (item.getIntensity() > 0) {
- return true;
- } else {
- return false;
- }
+ public boolean hasHR(ActivitySession item) {
+ return item.getHeartRateAverage() > 0;
}
@Override
- protected boolean hasDistance(StepAnalysis.StepSession item) {
- if (item.getDistance() > 0) {
- return true;
- } else {
- return false;
- }
+ public boolean hasIntensity(ActivitySession item) {
+ return item.getIntensity() > 0;
}
@Override
- protected boolean hasSteps(StepAnalysis.StepSession item) {
- if (item.getSteps() > 0) {
- return true;
- } else {
- return false;
- }
+ protected boolean hasDistance(ActivitySession item) {
+ return item.getDistance() > 0;
}
+ @Override
+ protected boolean hasSteps(ActivitySession item) {
+ return item.getActiveSteps() > 0;
+ }
@Override
- protected int getIcon(StepAnalysis.StepSession item) {
+ protected boolean hasTotalSteps(ActivitySession item) {
+ return item.getTotalDaySteps() > 0;
+ }
+
+ @Override
+ protected boolean isSummary(ActivitySession item) {
+ int sessionType = item.getSessionType();
+ return sessionType == SESSION_SUMMARY;
+ }
+
+ @Override
+ protected boolean isEmptySummary(ActivitySession item) {
+ return item.getIsEmptySummary();
+ }
+
+ @Override
+ protected String getStepTotalLabel(ActivitySession item) {
+ return String.valueOf(item.getTotalDaySteps());
+ }
+
+ @Override
+ protected int getIcon(ActivitySession item) {
return ActivityKind.getIconId(item.getActivityKind());
}
-
-
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingChartFragment.java
index 26b3ccacb..bc5add220 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingChartFragment.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityListingChartFragment.java
@@ -42,14 +42,14 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
-
public class ActivityListingChartFragment extends AbstractChartFragment {
protected static final Logger LOG = LoggerFactory.getLogger(ActivityListingChartFragment.class);
int tsDateFrom;
+
private View rootView;
- private List extends ActivitySample> activitySamples;
private ActivityListingAdapter stepListAdapter;
private TextView stepsDateView;
@@ -57,18 +57,16 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_steps_list, container, false);
-
+ getChartsHost().enableSwipeRefresh(false);
ListView stepsList = rootView.findViewById(R.id.itemListView);
- View headerView = inflater.inflate(R.layout.heartrate_average_widget,null, false);
- stepsList.addHeaderView(headerView);
stepListAdapter = new ActivityListingAdapter(getContext());
stepsList.setAdapter(stepListAdapter);
stepsDateView = rootView.findViewById(R.id.stepsDateView);
refresh();
-
return rootView;
}
+
@Override
public String getTitle() {
return "Steps list";
@@ -86,36 +84,40 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
}
}
-
@Override
protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
- //trying to fit found peg into square hole of the Gb Charts fragment system
- //get the data
+ List extends ActivitySample> activitySamples;
activitySamples = getSamples(db, device);
- return null;
+ List stepSessions = null;
+ StepAnalysis stepAnalysis = new StepAnalysis();
+ boolean isEmptySummary = false;
+
+ if (activitySamples != null) {
+ stepSessions = stepAnalysis.calculateStepSessions(activitySamples);
+ if (stepSessions.toArray().length == 0) {
+ isEmptySummary = true;
+ }
+ stepSessions = stepAnalysis.calculateSummary(stepSessions, isEmptySummary);
+ }
+ return new MyChartsData(stepSessions);
}
@Override
protected void updateChartsnUIThread(ChartsData chartsData) {
- //top displays selected date
- stepsDateView.setText(DateTimeUtils.formatDate(new Date(tsDateFrom * 1000L)));
- //calculate active sessions
- StepAnalysis stepAnalysis = new StepAnalysis();
- if (activitySamples != null) {
- List stepSessions = stepAnalysis.calculateStepSessions(activitySamples);
- if (stepSessions.toArray().length == 0) {
- stepSessions = create_empty_record();
- getChartsHost().enableSwipeRefresh(true); //try to enable pull to refresh, might be needed
- } else {
- getChartsHost().enableSwipeRefresh(false); //disable pull to refresh as it collides with swipable view
- }
- //push to the adapter
- stepListAdapter.setItems(stepSessions, true);
+ MyChartsData mcd = (MyChartsData) chartsData;
+ if (mcd.getStepSessions().toArray().length == 0) {
+ getChartsHost().enableSwipeRefresh(true); //try to enable pull to refresh, might be needed
+ } else {
+ getChartsHost().enableSwipeRefresh(false); //disable pull to refresh as it collides with swipable view
}
+
+ stepsDateView.setText(DateTimeUtils.formatDate(new Date(tsDateFrom * 1000L)));
+ stepListAdapter.setItems(mcd.getStepSessions(), true);
}
@Override
protected void renderCharts() {
+
}
@Override
@@ -135,16 +137,17 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
return getAllSamples(db, device, tsFrom, tsTo);
}
- private List create_empty_record() {
- //have an "Unknown Activity" in the list in case there are no active sessions
- List result = new ArrayList<>();
- int tsTo = tsDateFrom + 24 * 60 * 60 - 1;
- if (DateUtils.isToday(tsDateFrom * 1000L)) {
- Calendar day = Calendar.getInstance();
- day.set(Calendar.SECOND, 0);
- tsTo = (int) (day.getTimeInMillis() / 1000);
+ private static class MyChartsData extends ChartsData {
+ private final List stepSessions;
+
+ MyChartsData(List stepSessions) {
+ this.stepSessions = stepSessions;
+ }
+
+ public List getStepSessions() {
+ return stepSessions;
}
- result.add(new StepAnalysis.StepSession(new Date(tsDateFrom * 1000L), new Date(tsTo * 1000L), 0, 0, 0, 0, ActivityKind.TYPE_UNKNOWN));
- return result;
}
+
+
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepChartFragment.java
index 6d4601f4e..0ad73b27a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepChartFragment.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepChartFragment.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
-import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -244,7 +243,7 @@ public class SleepChartFragment extends AbstractChartFragment {
int min = Collections.min(heartRateValues);
int max = Collections.max(heartRateValues);
int count = heartRateValues.toArray().length;
- float sum = calculateHRSum(heartRateValues);
+ float sum = calculateSumOfInts(heartRateValues);
float average = sum / count;
return Triple.of(average, min, max);
}
@@ -257,7 +256,7 @@ public class SleepChartFragment extends AbstractChartFragment {
return result;
}
- private float calculateHRSum(List samples) {
+ private float calculateSumOfInts(List samples) {
float result = 0;
for (Integer sample : samples) {
result += sample;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepAnalysis.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepAnalysis.java
index a7049734b..9b8b1a9e1 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepAnalysis.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepAnalysis.java
@@ -28,12 +28,14 @@ import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
public class StepAnalysis {
protected static final Logger LOG = LoggerFactory.getLogger(StepAnalysis.class);
+ private int totalDailySteps = 0;
- public List calculateStepSessions(List extends ActivitySample> samples) {
- List result = new ArrayList<>();
+ public List calculateStepSessions(List extends ActivitySample> samples) {
+ List result = new ArrayList<>();
ActivityUser activityUser = new ActivityUser();
double STEP_LENGTH_M;
final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5);
@@ -41,6 +43,7 @@ public class StepAnalysis {
final int MIN_STEPS_PER_MINUTE = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute", 40);
int stepLengthCm = activityUser.getStepLengthCm();
int heightCm = activityUser.getHeightCm();
+ totalDailySteps = 0;
if (stepLengthCm == 0 && heightCm != 0) {
STEP_LENGTH_M = heightCm * 0.43 * 0.01;
@@ -68,6 +71,11 @@ public class StepAnalysis {
HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
for (ActivitySample sample : samples) {
+ int steps = sample.getSteps();
+ if (steps > 0) {
+ totalDailySteps += steps;
+ }
+
if (sample.getKind() != ActivityKind.TYPE_SLEEP //anything but sleep counts
&& !(sample instanceof TrailingActivitySample)) { //trailing samples have wrong date and make trailing activity have 0 duration
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
@@ -119,7 +127,7 @@ public class StepAnalysis {
float distance = (float) (activeSteps * STEP_LENGTH_M);
sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L);
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
- result.add(new StepSession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
+ result.add(new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
}
sessionStart = null;
}
@@ -139,12 +147,69 @@ public class StepAnalysis {
float distance = (float) (activeSteps * STEP_LENGTH_M);
sessionEnd = getDateFromSample(previousSample);
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
- result.add(new StepSession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
+ result.add(new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
}
}
return result;
}
+ public List calculateSummary(List sessions, boolean empty) {
+
+ HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
+ Date startTime = null;
+ Date endTime = null;
+ int stepsSum = 0;
+ int heartRateAverage = 0;
+ List heartRateSum = new ArrayList<>();
+ int distanceSum = 0;
+ float intensitySum = 0;
+ int sessionCount;
+ int durationSum = 0;
+
+ for (ActivitySession session : sessions) {
+ startTime = session.getStartTime();
+ endTime = session.getEndTime();
+ durationSum += endTime.getTime() - startTime.getTime();
+ stepsSum += session.getActiveSteps();
+ distanceSum += session.getDistance();
+ heartRateSum.add(session.getHeartRateAverage());
+ intensitySum += session.getIntensity();
+ }
+
+ sessionCount = sessions.toArray().length;
+ if (heartRateSum.toArray().length > 0) {
+ heartRateAverage = calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length;
+ }
+ if (!heartRateUtilsInstance.isValidHeartRateValue(heartRateAverage)) {
+ heartRateAverage = 0;
+ }
+ startTime = new Date(0);
+ endTime = new Date(durationSum);
+
+ ActivitySession stepSessionSummary = new ActivitySession(startTime, endTime,
+ stepsSum, heartRateAverage, intensitySum, distanceSum, 0);
+
+ stepSessionSummary.setSessionCount(sessionCount);
+ stepSessionSummary.setSessionType(ActivitySession.SESSION_SUMMARY);
+ stepSessionSummary.setEmptySummary(empty);
+
+
+ stepSessionSummary.setTotalDaySteps(totalDailySteps);
+
+ List newList = new ArrayList<>();
+ newList.add(stepSessionSummary);
+ newList.addAll(sessions);
+ return newList;
+ }
+
+ private int calculateSumOfInts(List samples) {
+ int result = 0;
+ for (Integer sample : samples) {
+ result += sample;
+ }
+ return result;
+ }
+
private int detect_activity_kind(int session_length, int activeSteps, int heartRateAverage, float intensity) {
final int MIN_STEPS_PER_MINUTE_FOR_RUN = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute_for_run", 120);
int spm = (int) (activeSteps / (session_length / 60));
@@ -160,61 +225,7 @@ public class StepAnalysis {
return ActivityKind.TYPE_ACTIVITY;
}
- private boolean isStep(ActivitySample sample) {
- return sample.getKind() == ActivityKind.TYPE_WALKING || sample.getKind() == ActivityKind.TYPE_RUNNING || sample.getKind() == ActivityKind.TYPE_ACTIVITY;
- }
-
private Date getDateFromSample(ActivitySample sample) {
return new Date(sample.getTimestamp() * 1000L);
}
-
- public static class StepSession {
- private final Date startTime;
- private final Date endTime;
- private final int steps;
- private final int heartRateAverage;
- private final float intensity;
- private final float distance;
- private final int activityKind;
-
- StepSession(Date startTime,
- Date endTime,
- int steps, int heartRateAverage, float intensity, float distance, int activityKind) {
- this.startTime = startTime;
- this.endTime = endTime;
- this.steps = steps;
- this.heartRateAverage = heartRateAverage;
- this.intensity = intensity;
- this.distance = distance;
- this.activityKind = activityKind;
- }
-
- public Date getStartTime() {
- return startTime;
- }
-
- public Date getEndTime() {
- return endTime;
- }
-
- public int getSteps() {
- return steps;
- }
-
- public int getHeartRateAverage() {
- return heartRateAverage;
- }
-
- public int getActivityKind() {
- return activityKind;
- }
-
- public float getIntensity() {
- return intensity;
- }
-
- public float getDistance() {
- return distance;
- }
- }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/AbstractActivityListingAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/AbstractActivityListingAdapter.java
index 59f203823..bdb36225f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/AbstractActivityListingAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/AbstractActivityListingAdapter.java
@@ -35,6 +35,8 @@ import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
/**
* Adapter for displaying generic ItemWithDetails instances.
@@ -43,6 +45,7 @@ public abstract class AbstractActivityListingAdapter extends ArrayAdapter
private final Context context;
private final List items;
+ private final int SESSION_SUMMARY = ActivitySession.SESSION_SUMMARY;
private int backgroundColor = 0;
private int alternateColor = 0;
private boolean zebraStripes = true;
@@ -67,15 +70,27 @@ public abstract class AbstractActivityListingAdapter extends ArrayAdapter
return typedValue.data;
}
+
@Override
public View getView(int position, View view, ViewGroup parent) {
T item = getItem(position);
- view = null; //this is ugly (probably we get no recycling), but it is required to keep the layout nice. We have only few items, so this should be OK.
- if (view == null) {
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- view = inflater.inflate(R.layout.activity_list_item, parent, false);
+
+ if (isSummary(item)) {
+ view = fill_dashboard(item, position, view, parent, context);
+ } else {
+ view = fill_item(item, position, view, parent);
}
+
+ return view;
+
+
+ }
+
+ private View fill_item(T item, int position, View view, ViewGroup parent) {
+ view = null;
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ view = inflater.inflate(R.layout.activity_list_item, parent, false);
TextView timeFrom = view.findViewById(R.id.line_layout_time_from);
TextView timeTo = view.findViewById(R.id.line_layout_time_to);
TextView activityName = view.findViewById(R.id.line_layout_activity_name);
@@ -160,6 +175,9 @@ public abstract class AbstractActivityListingAdapter extends ArrayAdapter
return view;
}
+
+ protected abstract View fill_dashboard(T item, int position, View view, ViewGroup parent, Context context);
+
protected abstract String getDateLabel(T item);
protected abstract boolean hasGPS(T item);
@@ -182,6 +200,8 @@ public abstract class AbstractActivityListingAdapter extends ArrayAdapter
protected abstract String getDurationLabel(T item);
+ protected abstract String getSessionCountLabel(T item);
+
protected abstract boolean hasHR(T item);
protected abstract boolean hasIntensity(T item);
@@ -190,6 +210,14 @@ public abstract class AbstractActivityListingAdapter extends ArrayAdapter
protected abstract boolean hasSteps(T item);
+ protected abstract boolean hasTotalSteps(T item);
+
+ protected abstract boolean isSummary(T item);
+
+ protected abstract boolean isEmptySummary(T item);
+
+ protected abstract String getStepTotalLabel(T item);
+
public void setZebraStripes(boolean enable) {
zebraStripes = enable;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/ActivitySummariesAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/ActivitySummariesAdapter.java
index 2562a95b5..ed37e98b1 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/ActivitySummariesAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/ActivitySummariesAdapter.java
@@ -18,6 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.content.Context;
import android.text.format.DateUtils;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.Toast;
import java.util.Calendar;
@@ -134,6 +136,11 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_filter_none.xml b/app/src/main/res/drawable/ic_filter_none.xml
new file mode 100644
index 000000000..050d129b3
--- /dev/null
+++ b/app/src/main/res/drawable/ic_filter_none.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_functions.xml b/app/src/main/res/drawable/ic_functions.xml
new file mode 100644
index 000000000..088ba5f2f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_functions.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_intensity.xml b/app/src/main/res/drawable/ic_intensity.xml
index 7063d2bc0..70449795f 100644
--- a/app/src/main/res/drawable/ic_intensity.xml
+++ b/app/src/main/res/drawable/ic_intensity.xml
@@ -1,15 +1,10 @@
-
+ android:fillColor="@android:color/white"
+ android:pathData="M11.57,13.16c-1.36,0.28 -2.17,1.16 -2.17,2.41 0,1.34 1.11,2.42 2.49,2.42 2.05,0 3.71,-1.66 3.71,-3.71 0,-1.07 -0.15,-2.12 -0.46,-3.12 -0.79,1.07 -2.2,1.72 -3.57,2zM13.5,0.67s0.74,2.65 0.74,4.8c0,2.06 -1.35,3.73 -3.41,3.73 -2.07,0 -3.63,-1.67 -3.63,-3.73l0.03,-0.36C5.21,7.51 4,10.62 4,14c0,4.42 3.58,8 8,8s8,-3.58 8,-8C20,8.61 17.41,3.8 13.5,0.67zM12,20c-3.31,0 -6,-2.69 -6,-6 0,-1.53 0.3,-3.04 0.86,-4.43 1.01,1.01 2.41,1.63 3.97,1.63 2.66,0 4.75,-1.83 5.28,-4.43C17.34,8.97 18,11.44 18,14c0,3.31 -2.69,6 -6,6z" />
diff --git a/app/src/main/res/drawable/ic_intensity_hollow.xml b/app/src/main/res/drawable/ic_intensity_hollow.xml
new file mode 100644
index 000000000..b39e3ceb2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_intensity_hollow.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_shoe_print.xml b/app/src/main/res/drawable/ic_shoe_print.xml
new file mode 100644
index 000000000..67ed513d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_shoe_print.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_shoe_prints_many.xml b/app/src/main/res/drawable/ic_shoe_prints_many.xml
new file mode 100644
index 000000000..b0b68a7bb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_shoe_prints_many.xml
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/app/src/main/res/layout/activity_list_dashboard_item.xml b/app/src/main/res/layout/activity_list_dashboard_item.xml
new file mode 100644
index 000000000..188a546f3
--- /dev/null
+++ b/app/src/main/res/layout/activity_list_dashboard_item.xml
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_list_item.xml b/app/src/main/res/layout/activity_list_item.xml
index 71c21b1f5..5ba85a6bc 100644
--- a/app/src/main/res/layout/activity_list_item.xml
+++ b/app/src/main/res/layout/activity_list_item.xml
@@ -134,7 +134,7 @@
android:layout_height="19dp"
android:layout_gravity="bottom|start"
android:contentDescription="@string/candidate_item_device_image"
- app:srcCompat="@drawable/ic_shoe" />
+ app:srcCompat="@drawable/ic_shoe_print" />
-
+
+
+
diff --git a/app/src/main/res/layout/intensity_total_widget.xml b/app/src/main/res/layout/intensity_total_widget.xml
index 9369d17ac..42ba95e05 100644
--- a/app/src/main/res/layout/intensity_total_widget.xml
+++ b/app/src/main/res/layout/intensity_total_widget.xml
@@ -14,14 +14,13 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:srcCompat="@drawable/ic_activity_unknown" />
+ app:srcCompat="@drawable/ic_intensity_hollow" />
Steps per week
Activity
Activity list
+ Active steps
+ Distance
+ Active time
+ Movement\nIntensity
+ Activities
Lack of sleep: %1$s
Overslept: %1$s