mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 12:56:49 +01:00
ActivityDetail with steps
This commit is contained in:
parent
94afcba363
commit
7a46d39193
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
138
app/src/main/res/layout/activity_summary_details.xml
Normal file
138
app/src/main/res/layout/activity_summary_details.xml
Normal 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>
|
Loading…
Reference in New Issue
Block a user