1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 12:56:49 +01:00

ActivityDetail with steps

This commit is contained in:
vanous 2020-08-07 09:21:14 +02:00
parent 94afcba363
commit 7a46d39193
6 changed files with 307 additions and 11 deletions

View File

@ -419,6 +419,11 @@
android:parentActivityName=".activities.ControlCenterv2" android:parentActivityName=".activities.ControlCenterv2"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" /> android:windowSoftInputMode="stateHidden" />
<activity
android:name=".activities.ActivitySummaryDetail"
android:label="Activity Summary Detail"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
<activity <activity
android:name=".activities.DbManagementActivity" android:name=".activities.DbManagementActivity"

View File

@ -58,9 +58,13 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes; import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ActivitySummariesActivity extends AbstractListActivity<BaseActivitySummary> { public class ActivitySummariesActivity extends AbstractListActivity<BaseActivitySummary> {
private static final Logger LOG = LoggerFactory.getLogger(ActivitySummariesActivity.class);
private GBDevice mGBDevice; private GBDevice mGBDevice;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
@ -129,13 +133,12 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
Object item = parent.getItemAtPosition(position); Object item = parent.getItemAtPosition(position);
if (item != null) { if (item != null) {
ActivitySummary summary = (ActivitySummary) item; ActivitySummary summary = (ActivitySummary) item;
try {
String gpxTrack = summary.getGpxTrack(); showDetail(summary);
if (gpxTrack != null) { } catch (Exception e) {
showTrack(gpxTrack); GB.toast(getApplicationContext(), "Unable to display Activity Detail, maybe the activity is not available yet: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
} else {
GB.toast("This activity does not contain GPX tracks.", Toast.LENGTH_LONG, GB.INFO);
} }
} }
} }
}); });
@ -263,6 +266,13 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
refresh(); refresh();
} }
private void showDetail(ActivitySummary summary){
Intent ActivitySummaryDetailIntent = new Intent(this, ActivitySummaryDetail.class);
ActivitySummaryDetailIntent.putExtra("summary", summary);
ActivitySummaryDetailIntent.putExtra(GBDevice.EXTRA_DEVICE, mGBDevice);
startActivity(ActivitySummaryDetailIntent);
}
private void showTrack(String gpxTrack) { private void showTrack(String gpxTrack) {
try { try {
AndroidUtils.viewFile(gpxTrack, Intent.ACTION_VIEW, this); AndroidUtils.viewFile(gpxTrack, Intent.ACTION_VIEW, this);

View File

@ -0,0 +1,125 @@
/* Copyright (C) 2015-2020 abettenburg, Andreas Shimokawa, Carsten Pfeiffer,
Daniele Gobbetti, Lem Dulfo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ActivityAnalysis;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class ActivitySummaryDetail extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(ActivitySummaryDetail.class);
private GBDevice mGBDevice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_summary_details);
Intent intent = getIntent();
ActivitySummary summary = (ActivitySummary) intent.getSerializableExtra("summary");
GBDevice device = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
mGBDevice = device;
final String gpxTrack = summary.getGpxTrack();
Button show_track_btn = (Button) findViewById(R.id.showTrack);
show_track_btn.setVisibility(View.GONE);
if (gpxTrack != null) {
ActivityTrack activityTrack = new ActivityTrack();
show_track_btn.setVisibility(View.VISIBLE);
show_track_btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
AndroidUtils.viewFile(gpxTrack, Intent.ACTION_VIEW, getApplicationContext());
} catch (IOException e) {
GB.toast(getApplicationContext(), "Unable to display GPX track: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
}
}
});
}
String activitykind = ActivityKind.asString(summary.getActivityKind(), getApplicationContext());
String starttime = DateTimeUtils.formatDateTime(summary.getStartTime());
String endtime = DateTimeUtils.formatDateTime(summary.getEndTime());
Long startTs = summary.getStartTime().getTime() / 1000;
Long endTs = summary.getEndTime().getTime() / 1000;
Long durationms = (summary.getEndTime().getTime() - summary.getStartTime().getTime());
String durationhms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(durationms),
TimeUnit.MILLISECONDS.toMinutes(durationms) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(durationms) % TimeUnit.MINUTES.toSeconds(1));
int steps = getSteps(startTs.intValue(), endTs.intValue());
ImageView activity_icon = (ImageView) findViewById(R.id.item_image);
activity_icon.setImageResource(ActivityKind.getIconId(summary.getActivityKind()));
TextView activity_kind = (TextView) findViewById(R.id.activitykind);
activity_kind.setText(activitykind);
TextView start_time = (TextView) findViewById(R.id.starttime);
start_time.setText(starttime);
TextView end_time = (TextView) findViewById(R.id.endtime);
end_time.setText(endtime);
TextView activity_duration = (TextView) findViewById(R.id.duration);
activity_duration.setText(durationhms);
TextView activity_steps = (TextView) findViewById(R.id.steps);
activity_steps.setText(String.valueOf(steps));
}
private int getSteps(int tsStart, int tsEnd) {
try (DBHandler handler = GBApplication.acquireDB()) {
DailyTotals dt = new DailyTotals();
ActivityAnalysis analysis = new ActivityAnalysis();
ActivityAmounts amountsSteps;
amountsSteps = analysis.calculateActivityAmounts(dt.getSamples(handler, mGBDevice, tsStart, tsEnd));
return (int) dt.getTotalsStepsForActivityAmounts(amountsSteps);
} catch (Exception e) {
GB.toast("Error loading activity steps.", Toast.LENGTH_SHORT, GB.ERROR, e);
}
return 0;
}
}

View File

@ -21,6 +21,7 @@ import android.widget.Toast;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import de.greenrobot.dao.query.QueryBuilder; import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -60,21 +61,38 @@ public class ActivitySummariesAdapter extends AbstractItemAdapter<BaseActivitySu
@Override @Override
protected String getName(BaseActivitySummary item) { protected String getName(BaseActivitySummary item) {
String name = item.getName(); String name = item.getName();
if (name != null && name.length() > 0) { if (name != null && name.length() > 0) {
return name; return name;
} }
Date startTime = item.getStartTime(); Date startTime = item.getStartTime();
Long duration = (item.getEndTime().getTime() - item.getStartTime().getTime());
String durationhms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(duration),
TimeUnit.MILLISECONDS.toMinutes(duration) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(duration) % TimeUnit.MINUTES.toSeconds(1));
if (startTime != null) { if (startTime != null) {
return DateTimeUtils.formatDateTime(startTime); return DateTimeUtils.formatDateTime(startTime) + " (" + durationhms + ")";
} }
return "Unknown activity"; return "Unknown activity";
} }
@Override @Override
protected String getDetails(BaseActivitySummary item) { protected String getDetails(BaseActivitySummary item) {
return ActivityKind.asString(item.getActivityKind(), getContext()); String gpxTrack = item.getGpxTrack();
String hasGps = "";
if (gpxTrack != null) {
hasGps=" 🛰️";
}
return ActivityKind.asString(item.getActivityKind(), getContext())+ hasGps;
} }
@Override @Override

View File

@ -104,7 +104,7 @@ public class DailyTotals {
} }
private long getTotalsStepsForActivityAmounts(ActivityAmounts activityAmounts) { public long getTotalsStepsForActivityAmounts(ActivityAmounts activityAmounts) {
long totalSteps = 0; long totalSteps = 0;
for (ActivityAmount amount : activityAmounts.getAmounts()) { for (ActivityAmount amount : activityAmounts.getAmounts()) {
@ -131,7 +131,7 @@ public class DailyTotals {
} }
protected List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { public List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
return getAllSamples(db, device, tsFrom, tsTo); return getAllSamples(db, device, tsFrom, tsTo);
} }

View File

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:padding="8dp">
<ImageView
android:id="@+id/item_image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentStart="true"
android:contentDescription="activity image" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/item_image"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<TextView
android:id="@+id/activitykind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false" />
<LinearLayout
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/starttime_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:text="Start:" />
<TextView
android:id="@+id/starttime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end" />
</LinearLayout>
<LinearLayout
android:id="@+id/end"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/endtime_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:text="End:" />
<TextView
android:id="@+id/endtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end" />
</LinearLayout>
<LinearLayout
android:id="@+id/dur"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:text="Duration:" />
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end" />
</LinearLayout>
<LinearLayout
android:id="@+id/stps"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/steps_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:text="Steps:" />
<TextView
android:id="@+id/steps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end" />
</LinearLayout>
<Button
android:id="@+id/showTrack"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Show GPS Track" />
</LinearLayout>
</RelativeLayout>