diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardGoalsWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardGoalsWidget.java index 886bd19ef..f0fc3ea06 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardGoalsWidget.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardGoalsWidget.java @@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.os.AsyncTask; import android.os.Bundle; import android.text.Spannable; import android.text.SpannableString; @@ -43,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.HealthUtils; */ public class DashboardGoalsWidget extends AbstractDashboardWidget { private static final Logger LOG = LoggerFactory.getLogger(DashboardGoalsWidget.class); + private View goalsView; private ImageView goalsChart; public DashboardGoalsWidget() { @@ -68,11 +70,11 @@ public class DashboardGoalsWidget extends AbstractDashboardWidget { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View todayView = inflater.inflate(R.layout.dashboard_widget_goals, container, false); - goalsChart = todayView.findViewById(R.id.dashboard_goals_chart); + goalsView = inflater.inflate(R.layout.dashboard_widget_goals, container, false); + goalsChart = goalsView.findViewById(R.id.dashboard_goals_chart); // Initialize legend - TextView legend = todayView.findViewById(R.id.dashboard_goals_legend); + TextView legend = goalsView.findViewById(R.id.dashboard_goals_legend); SpannableString l_steps = new SpannableString("■ " + getString(R.string.steps)); l_steps.setSpan(new ForegroundColorSpan(color_activity), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableString l_distance = new SpannableString("■ " + getString(R.string.distance)); @@ -86,7 +88,7 @@ public class DashboardGoalsWidget extends AbstractDashboardWidget { fillData(); - return todayView; + return goalsView; } @Override @@ -96,34 +98,54 @@ public class DashboardGoalsWidget extends AbstractDashboardWidget { } protected void fillData() { - int width = 230; - int height = 230; - int barWidth = 10; - int barMargin = (int) Math.ceil(barWidth / 2f); + goalsView.post(new Runnable() { + @Override + public void run() { + FillDataAsyncTask myAsyncTask = new FillDataAsyncTask(); + myAsyncTask.execute(); + } + }); + } - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeCap(Paint.Cap.ROUND); - paint.setStrokeWidth(barWidth); + private class FillDataAsyncTask extends AsyncTask { + private Bitmap goalsBitmap; - paint.setColor(color_activity); - canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getStepsGoalFactor(timeTo), false, paint); + @Override + protected Void doInBackground(Void... params) { + int width = 500; + int height = 500; + int barWidth = 20; + int barMargin = (int) Math.ceil(barWidth / 2f); - barMargin += barWidth * 1.5; - paint.setColor(color_distance); - canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getDistanceGoalFactor(timeTo), false, paint); + goalsBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(goalsBitmap); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeWidth(barWidth); - barMargin += barWidth * 1.5; - paint.setColor(color_active_time); - canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getActiveMinutesGoalFactor(timeFrom, timeTo), false, paint); + paint.setColor(color_activity); + canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getStepsGoalFactor(timeTo), false, paint); - barMargin += barWidth * 1.5; - paint.setColor(color_light_sleep); - canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getSleepMinutesGoalFactor(timeTo), false, paint); + barMargin += barWidth * 1.5; + paint.setColor(color_distance); + canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getDistanceGoalFactor(timeTo), false, paint); - goalsChart.setImageBitmap(bitmap); + barMargin += barWidth * 1.5; + paint.setColor(color_active_time); + canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getActiveMinutesGoalFactor(timeFrom, timeTo), false, paint); + + barMargin += barWidth * 1.5; + paint.setColor(color_light_sleep); + canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * HealthUtils.getSleepMinutesGoalFactor(timeTo), false, paint); + return null; + } + + @Override + protected void onPostExecute(Void unused) { + super.onPostExecute(unused); + goalsChart.setImageBitmap(goalsBitmap); + } } } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardTodayWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardTodayWidget.java index bbbd7e080..f59415c9e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardTodayWidget.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/dashboard/DashboardTodayWidget.java @@ -17,6 +17,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard; import android.graphics.Color; +import android.os.AsyncTask; import android.os.Bundle; import android.text.Spannable; import android.text.SpannableString; @@ -59,6 +60,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class DashboardTodayWidget extends AbstractDashboardWidget { private static final Logger LOG = LoggerFactory.getLogger(DashboardTodayWidget.class); + private View todayView; + private boolean mode_24h; private PieChart chart_0_12; @@ -87,7 +90,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View todayView = inflater.inflate(R.layout.dashboard_widget_today, container, false); + todayView = inflater.inflate(R.layout.dashboard_widget_today, container, false); // Determine whether to draw a single or a double chart. In case 24h mode is selected, // use just the outer chart (chart_12_24) for all data. @@ -187,144 +190,158 @@ public class DashboardTodayWidget extends AbstractDashboardWidget { } protected void fillData() { - // Retrieve activity data - List devices = GBApplication.app().getDeviceManager().getDevices(); - List allActivitySamples = new ArrayList<>(); - List stepSessions = new ArrayList<>(); - try (DBHandler dbHandler = GBApplication.acquireDB()) { - for (GBDevice dev : devices) { - if (dev.getDeviceCoordinator().supportsActivityTracking()) { - List activitySamples = HealthUtils.getAllSamples(dbHandler, dev, timeFrom, timeTo); - allActivitySamples.addAll(activitySamples); - StepAnalysis stepAnalysis = new StepAnalysis(); - stepSessions.addAll(stepAnalysis.calculateStepSessions(activitySamples)); - } + todayView.post(new Runnable() { + @Override + public void run() { + FillDataAsyncTask myAsyncTask = new FillDataAsyncTask(); + myAsyncTask.execute(); } - } catch (Exception e) { - LOG.warn("Could not retrieve activity amounts: ", e); - } + }); + } - // Integrate and chronologically order various data from multiple devices - List generalizedActivities = new ArrayList<>(); - long midDaySecond = timeFrom + (12 * 60 * 60); - for (ActivitySample sample : allActivitySamples) { - // Handle only TYPE_NOT_WORN and TYPE_SLEEP (including variants) here - if (sample.getKind() != ActivityKind.TYPE_NOT_WORN && (sample.getKind() == ActivityKind.TYPE_NOT_MEASURED || (sample.getKind() & ActivityKind.TYPE_SLEEP) == 0)) - continue; - if (generalizedActivities.size() > 0) { - GeneralizedActivity previous = generalizedActivities.get(generalizedActivities.size() - 1); - // Merge samples if the type is the same, and they are within a minute of each other - if (previous.activityKind == sample.getKind() && previous.timeTo > sample.getTimestamp() - 60) { - // But only if the resulting activity doesn't cross the midday boundary in 12h mode - if (mode_24h || sample.getTimestamp() + 60 < midDaySecond || previous.timeFrom > midDaySecond) { - generalizedActivities.get(generalizedActivities.size() - 1).timeTo = sample.getTimestamp() + 60; - continue; + private class FillDataAsyncTask extends AsyncTask { + @Override + protected Void doInBackground(Void... params) { + // Retrieve activity data + List devices = GBApplication.app().getDeviceManager().getDevices(); + List allActivitySamples = new ArrayList<>(); + List stepSessions = new ArrayList<>(); + try (DBHandler dbHandler = GBApplication.acquireDB()) { + for (GBDevice dev : devices) { + if (dev.getDeviceCoordinator().supportsActivityTracking()) { + List activitySamples = HealthUtils.getAllSamples(dbHandler, dev, timeFrom, timeTo); + allActivitySamples.addAll(activitySamples); + StepAnalysis stepAnalysis = new StepAnalysis(); + stepSessions.addAll(stepAnalysis.calculateStepSessions(activitySamples)); } } + } catch (Exception e) { + LOG.warn("Could not retrieve activity amounts: ", e); } - generalizedActivities.add(new GeneralizedActivity( - sample.getKind(), - sample.getTimestamp(), - sample.getTimestamp() + 60 - )); - } - for (ActivitySession session : stepSessions) { - if (!mode_24h && session.getStartTime().getTime() / 1000 < midDaySecond && session.getEndTime().getTime() / 1000 > midDaySecond) { - generalizedActivities.add(new GeneralizedActivity( - session.getActivityKind(), - session.getStartTime().getTime() / 1000, - midDaySecond - )); - generalizedActivities.add(new GeneralizedActivity( - session.getActivityKind(), - midDaySecond, - session.getEndTime().getTime() / 1000 - )); - } else { - generalizedActivities.add(new GeneralizedActivity( - session.getActivityKind(), - session.getStartTime().getTime() / 1000, - session.getEndTime().getTime() / 1000 - )); - } - } - Collections.sort(generalizedActivities, (o1, o2) -> (int) (o1.timeFrom - o2.timeFrom)); - // Add pie slice entries - ArrayList entries_0_12 = new ArrayList<>(); - ArrayList colors_0_12 = new ArrayList<>(); - ArrayList entries_12_24 = new ArrayList<>(); - ArrayList colors_12_24 = new ArrayList<>(); - long secondIndex = timeFrom; - for (GeneralizedActivity activity : generalizedActivities) { - // FIXME: correctly merge parallel activities from multiple devices - // Skip earlier sessions - if (activity.timeFrom < secondIndex) continue; - // Use correct entries list for this part of the day - ArrayList entries = entries_0_12; - ArrayList colors = colors_0_12; - if (mode_24h || activity.timeFrom >= midDaySecond) { - entries = entries_12_24; - colors = colors_12_24; + // Integrate and chronologically order various data from multiple devices + List generalizedActivities = new ArrayList<>(); + long midDaySecond = timeFrom + (12 * 60 * 60); + for (ActivitySample sample : allActivitySamples) { + // Handle only TYPE_NOT_WORN and TYPE_SLEEP (including variants) here + if (sample.getKind() != ActivityKind.TYPE_NOT_WORN && (sample.getKind() == ActivityKind.TYPE_NOT_MEASURED || (sample.getKind() & ActivityKind.TYPE_SLEEP) == 0)) + continue; + if (generalizedActivities.size() > 0) { + GeneralizedActivity previous = generalizedActivities.get(generalizedActivities.size() - 1); + // Merge samples if the type is the same, and they are within a minute of each other + if (previous.activityKind == sample.getKind() && previous.timeTo > sample.getTimestamp() - 60) { + // But only if the resulting activity doesn't cross the midday boundary in 12h mode + if (mode_24h || sample.getTimestamp() + 60 < midDaySecond || previous.timeFrom > midDaySecond) { + generalizedActivities.get(generalizedActivities.size() - 1).timeTo = sample.getTimestamp() + 60; + continue; + } + } + } + generalizedActivities.add(new GeneralizedActivity( + sample.getKind(), + sample.getTimestamp(), + sample.getTimestamp() + 60 + )); } - // Draw inactive slice - if (activity.timeFrom > secondIndex) { - entries.add(new PieEntry(activity.timeFrom - secondIndex, "Inactive")); - colors.add(color_worn); + for (ActivitySession session : stepSessions) { + if (!mode_24h && session.getStartTime().getTime() / 1000 < midDaySecond && session.getEndTime().getTime() / 1000 > midDaySecond) { + generalizedActivities.add(new GeneralizedActivity( + session.getActivityKind(), + session.getStartTime().getTime() / 1000, + midDaySecond + )); + generalizedActivities.add(new GeneralizedActivity( + session.getActivityKind(), + midDaySecond, + session.getEndTime().getTime() / 1000 + )); + } else { + generalizedActivities.add(new GeneralizedActivity( + session.getActivityKind(), + session.getStartTime().getTime() / 1000, + session.getEndTime().getTime() / 1000 + )); + } } - // Draw activity slices - if (activity.activityKind == ActivityKind.TYPE_NOT_WORN) { - entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Not worn")); - colors.add(color_not_worn); - secondIndex = activity.timeTo; - } else if (activity.activityKind == ActivityKind.TYPE_LIGHT_SLEEP || activity.activityKind == ActivityKind.TYPE_SLEEP) { - entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Light sleep")); - colors.add(color_light_sleep); - secondIndex = activity.timeTo; - } else if (activity.activityKind == ActivityKind.TYPE_DEEP_SLEEP) { - entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Deep sleep")); - colors.add(color_deep_sleep); - secondIndex = activity.timeTo; - } else { - entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Active")); - colors.add(color_activity); - secondIndex = activity.timeTo; - } - } - // Fill remaining time until midnight - long currentTime = Calendar.getInstance().getTimeInMillis() / 1000; - if (!mode_24h && currentTime > timeFrom && currentTime < midDaySecond) { - // Fill with unknown slice up until current time - entries_0_12.add(new PieEntry(currentTime - secondIndex, "Unknown")); - colors_0_12.add(color_worn); - // Draw transparent slice for remaining time until midday - entries_0_12.add(new PieEntry(midDaySecond - currentTime, "Empty")); - colors_0_12.add(Color.TRANSPARENT); - } - if ((mode_24h || currentTime >= midDaySecond) && currentTime < timeTo) { - // Fill with unknown slice up until current time - entries_12_24.add(new PieEntry(currentTime - secondIndex, "Unknown")); - colors_12_24.add(color_worn); - // Draw transparent slice for remaining time until midnight - entries_12_24.add(new PieEntry(timeTo - currentTime, "Empty")); - colors_12_24.add(Color.TRANSPARENT); - } + Collections.sort(generalizedActivities, (o1, o2) -> (int) (o1.timeFrom - o2.timeFrom)); - // Draw charts - if (!mode_24h) { - PieDataSet dataSet_0_12 = new PieDataSet(entries_0_12, "Today 0-12h"); - dataSet_0_12.setSliceSpace(0f); - dataSet_0_12.setDrawValues(false); - dataSet_0_12.setColors(colors_0_12); - chart_0_12.setData(new PieData(dataSet_0_12)); - chart_0_12.invalidate(); + // Add pie slice entries + ArrayList entries_0_12 = new ArrayList<>(); + ArrayList colors_0_12 = new ArrayList<>(); + ArrayList entries_12_24 = new ArrayList<>(); + ArrayList colors_12_24 = new ArrayList<>(); + long secondIndex = timeFrom; + for (GeneralizedActivity activity : generalizedActivities) { + // FIXME: correctly merge parallel activities from multiple devices + // Skip earlier sessions + if (activity.timeFrom < secondIndex) continue; + // Use correct entries list for this part of the day + ArrayList entries = entries_0_12; + ArrayList colors = colors_0_12; + if (mode_24h || activity.timeFrom >= midDaySecond) { + entries = entries_12_24; + colors = colors_12_24; + } + // Draw inactive slice + if (activity.timeFrom > secondIndex) { + entries.add(new PieEntry(activity.timeFrom - secondIndex, "Inactive")); + colors.add(color_worn); + } + // Draw activity slices + if (activity.activityKind == ActivityKind.TYPE_NOT_WORN) { + entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Not worn")); + colors.add(color_not_worn); + secondIndex = activity.timeTo; + } else if (activity.activityKind == ActivityKind.TYPE_LIGHT_SLEEP || activity.activityKind == ActivityKind.TYPE_SLEEP) { + entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Light sleep")); + colors.add(color_light_sleep); + secondIndex = activity.timeTo; + } else if (activity.activityKind == ActivityKind.TYPE_DEEP_SLEEP) { + entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Deep sleep")); + colors.add(color_deep_sleep); + secondIndex = activity.timeTo; + } else { + entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Active")); + colors.add(color_activity); + secondIndex = activity.timeTo; + } + } + // Fill remaining time until midnight + long currentTime = Calendar.getInstance().getTimeInMillis() / 1000; + if (!mode_24h && currentTime > timeFrom && currentTime < midDaySecond) { + // Fill with unknown slice up until current time + entries_0_12.add(new PieEntry(currentTime - secondIndex, "Unknown")); + colors_0_12.add(color_worn); + // Draw transparent slice for remaining time until midday + entries_0_12.add(new PieEntry(midDaySecond - currentTime, "Empty")); + colors_0_12.add(Color.TRANSPARENT); + } + if ((mode_24h || currentTime >= midDaySecond) && currentTime < timeTo) { + // Fill with unknown slice up until current time + entries_12_24.add(new PieEntry(currentTime - secondIndex, "Unknown")); + colors_12_24.add(color_worn); + // Draw transparent slice for remaining time until midnight + entries_12_24.add(new PieEntry(timeTo - currentTime, "Empty")); + colors_12_24.add(Color.TRANSPARENT); + } + + // Draw charts + if (!mode_24h) { + PieDataSet dataSet_0_12 = new PieDataSet(entries_0_12, "Today 0-12h"); + dataSet_0_12.setSliceSpace(0f); + dataSet_0_12.setDrawValues(false); + dataSet_0_12.setColors(colors_0_12); + chart_0_12.setData(new PieData(dataSet_0_12)); + chart_0_12.invalidate(); + } + PieDataSet dataSet_12_24 = new PieDataSet(entries_12_24, "Today 12-24h"); + dataSet_12_24.setSliceSpace(0f); + dataSet_12_24.setDrawValues(false); + dataSet_12_24.setColors(colors_12_24); + chart_12_24.setData(new PieData(dataSet_12_24)); + chart_12_24.invalidate(); + return null; } - PieDataSet dataSet_12_24 = new PieDataSet(entries_12_24, "Today 12-24h"); - dataSet_12_24.setSliceSpace(0f); - dataSet_12_24.setDrawValues(false); - dataSet_12_24.setColors(colors_12_24); - chart_12_24.setData(new PieData(dataSet_12_24)); - chart_12_24.invalidate(); } private class GeneralizedActivity {