Track is now a record.

This commit is contained in:
Dennis Guse
2025-11-27 19:35:05 +01:00
parent 6a262426a5
commit 990c91f978
51 changed files with 772 additions and 523 deletions
@@ -28,6 +28,7 @@ import java.time.ZoneOffset;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackEditBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.ui.ZoneOffsetAdapter;
@@ -46,7 +47,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
private static final String ICON_VALUE_KEY = "icon_value_key";
private ContentProviderUtils contentProviderUtils;
private Track track;
private TrackBuilder trackBuilder;
private ActivityType activityType;
private TrackEditBinding viewBinding;
@@ -63,16 +64,17 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
}
contentProviderUtils = new ContentProviderUtils(this);
track = contentProviderUtils.getTrack(trackId);
Track track = contentProviderUtils.getTrack(trackId);
if (track == null) {
Log.e(TAG, "No track for " + trackId.id());
finish();
return;
}
trackBuilder = new TrackBuilder(track);
viewBinding.trackEditName.setText(track.getName());
viewBinding.trackEditName.setText(trackBuilder.getName());
viewBinding.trackEditActivityTypeLocalized.setText(track.getActivityTypeLocalized());
viewBinding.trackEditActivityTypeLocalized.setText(trackBuilder.getActivityTypeLocalized());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this));
viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter);
viewBinding.trackEditActivityTypeLocalized.setOnItemClickListener((parent, view, position, id) -> {
@@ -91,25 +93,25 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
activityType = (ActivityType) bundle.getSerializable(ICON_VALUE_KEY);
}
if (activityType == null) {
activityType = track.getActivityType();
activityType = trackBuilder.getActivityType();
}
setActivityTypeIcon(activityType);
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityTypeLocalized.getText().toString()));
viewBinding.trackEditDescription.setText(track.getDescription());
viewBinding.trackEditDescription.setText(trackBuilder.getDescription());
final ArrayAdapter<ZoneOffset> zoneOffsetAdapter = new ZoneOffsetAdapter(this, android.R.layout.simple_dropdown_item_1line);
viewBinding.trackEditTimeOffset.setText(track.getZoneOffset().toString());
viewBinding.trackEditTimeOffset.setText(trackBuilder.getZoneOffset().toString());
viewBinding.trackEditTimeOffset.setAdapter(zoneOffsetAdapter);
viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> track.setZoneOffset(zoneOffsetAdapter.getItem(position)));
viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> trackBuilder.setZoneOffset(zoneOffsetAdapter.getItem(position)));
viewBinding.trackEditSave.setOnClickListener(v -> {
track.setName(viewBinding.trackEditName.getText().toString());
track.setDescription(viewBinding.trackEditDescription.getText().toString());
trackBuilder.setName(viewBinding.trackEditName.getText().toString());
trackBuilder.setDescription(viewBinding.trackEditDescription.getText().toString());
track.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityTypeLocalized.getText().toString());
trackBuilder.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityTypeLocalized.getText().toString());
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(trackBuilder.getTrack());
finish();
});
@@ -33,6 +33,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.TrackRecordingBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
@@ -324,11 +325,11 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
@Override
public void onChooseActivityTypeDone(ActivityType activityType) {
Track track = contentProviderUtils.getTrack(trackId);
TrackBuilder track = new TrackBuilder(contentProviderUtils.getTrack(trackId));
String activityTypeLocalized = getString(activityType.getLocalizedStringId());
track.setActivityTypeLocalizedAndUpdateActivityType(this, activityTypeLocalized);
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(track.getTrack());
}
private class CustomFragmentPagerAdapter extends FragmentStateAdapter {
@@ -14,6 +14,7 @@ import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.DistanceFormatter;
import de.dennisguse.opentracks.data.models.SpeedFormatter;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackStoppedBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.io.file.exporter.ExportUtils;
@@ -46,9 +47,9 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
Track track = contentProviderUtils.getTrack(trackId);
viewBinding.trackEditName.setText(track.getName());
viewBinding.trackEditName.setText(track.name());
viewBinding.trackEditActivityType.setText(track.getActivityTypeLocalized());
viewBinding.trackEditActivityType.setText(track.activityTypeLocalized());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this));
viewBinding.trackEditActivityType.setAdapter(adapter);
@@ -63,19 +64,19 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
}
});
setActivityTypeIcon(track.getActivityType());
setActivityTypeIcon(track.activityType());
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityType.getText().toString()));
viewBinding.trackEditDescription.setText(track.getDescription());
viewBinding.trackEditDescription.setText(track.description());
viewBinding.time.setText(StringUtils.formatElapsedTime(track.getStatistics().movingDuration()));
viewBinding.time.setText(StringUtils.formatElapsedTime(track.statistics().movingDuration()));
{
Pair<String, String> parts = SpeedFormatter.Builder()
.setUnit(PreferencesUtils.getUnitSystem())
.setReportSpeedOrPace(PreferencesUtils.isReportSpeed(track))
.build(this)
.getSpeedParts(track.getStatistics().getAverageMovingSpeed());
.getSpeedParts(track.statistics().getAverageMovingSpeed());
viewBinding.speed.setText(parts.first);
viewBinding.speedUnit.setText(parts.second);
}
@@ -84,7 +85,7 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
Pair<String, String> parts = DistanceFormatter.Builder()
.setUnit(PreferencesUtils.getUnitSystem())
.build(this)
.getDistanceParts(track.getStatistics().totalDistance());
.getDistanceParts(track.statistics().totalDistance());
viewBinding.distance.setText(parts.first);
viewBinding.distanceUnit.setText(parts.second);
}
@@ -104,11 +105,12 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
}
private void storeTrackMetaData(ContentProviderUtils contentProviderUtils, Track track) {
track.setName(viewBinding.trackEditName.getText().toString());
track.setDescription(viewBinding.trackEditDescription.getText().toString());
track.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString());
TrackBuilder trackBuilder = new TrackBuilder(track);
trackBuilder.setName(viewBinding.trackEditName.getText().toString());
trackBuilder.setDescription(viewBinding.trackEditDescription.getText().toString());
trackBuilder.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString());
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(trackBuilder.getTrack());
}
@NonNull
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.ChartBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -174,14 +175,14 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
}
@Override
public void onTrackUpdated(Track track) {
public void onTrackUpdated(@NonNull Track track) {
if (isResumed()) {
if (track == null) {
activityTypeLocalized = "";
return;
}
activityTypeLocalized = track.getActivityTypeLocalized();
activityTypeLocalized = track.activityTypeLocalized();
boolean reportSpeed = PreferencesUtils.isReportSpeed(activityTypeLocalized);
if (reportSpeed != viewBinding.chartView.getReportSpeed()) {
viewBinding.chartView.setReportSpeed(reportSpeed);
@@ -50,6 +50,7 @@ import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -93,11 +94,6 @@ public class ContentProviderUtils {
this.contentResolver = contentResolver;
}
/**
* Creates a {@link Track} from a cursor.
*
* @param cursor the cursor pointing to the track
*/
public static Track createTrack(Cursor cursor) {
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
@@ -133,7 +129,7 @@ public class ContentProviderUtils {
null
);
Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics);
TrackBuilder track = new TrackBuilder(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics);
track.setId(new Track.Id(cursor.getLong(idIndex)));
track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex)));
if (!cursor.isNull(nameIndex)) {
@@ -149,7 +145,7 @@ public class ContentProviderUtils {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
}
return track;
return track.getTrack();
}
@VisibleForTesting
@@ -273,23 +269,23 @@ public class ContentProviderUtils {
* @param track the track
*/
public void updateTrack(Track track) {
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId().id())});
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.id().id())});
}
private ContentValues createContentValues(Track track) {
ContentValues values = new ContentValues();
if (track.getId() != null) {
values.put(TracksColumns._ID, track.getId().id());
if (track.id() != null) {
values.put(TracksColumns._ID, track.id().id());
}
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
values.put(TracksColumns.NAME, track.getName());
values.put(TracksColumns.DESCRIPTION, track.getDescription());
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.uuid()));
values.put(TracksColumns.NAME, track.name());
values.put(TracksColumns.DESCRIPTION, track.description());
values.put(TracksColumns.ACTIVITY_TYPE, track.activityType() != null ? track.activityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.activityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.zoneOffset().getTotalSeconds());
values.putAll(createContentValues(track.getStatistics()));
values.putAll(createContentValues(track.statistics()));
return values;
}
@@ -9,7 +9,6 @@ import java.util.NoSuchElementException;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
class MarkerIterator extends AutoCloseableIterator<Marker> {
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.tables.TracksColumns;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
@@ -19,7 +19,6 @@ package de.dennisguse.opentracks.data;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
@@ -34,6 +33,7 @@ import java.util.Set;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -1,164 +1,46 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
public record Track(
// May be null if the track was not loaded from the database.
@NonNull
Id id,
// May be null if the track was not loaded from the database.
@NonNull
UUID uuid,
@NonNull
String name,
@NonNull
String description,
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class Track {
@NonNull
String activityTypeLocalized,
@NonNull
ActivityType activityType,
@NonNull
ZoneOffset zoneOffset,
@NonNull
Statistics statistics
) {
private Track.Id id;
private UUID uuid = UUID.randomUUID();
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@VisibleForTesting
public Track(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
public Track(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
public OffsetDateTime getStartTime() {
return trackStatistics
public OffsetDateTime startTime() {
return statistics
.startTime().atOffset(zoneOffset);
}
public OffsetDateTime getStopTime() {
return trackStatistics
public OffsetDateTime stopTime() {
return statistics
.stopTime().atOffset(zoneOffset);
}
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
public record Id(long id) implements Parcelable {
@Override
@@ -0,0 +1,193 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class TrackBuilder {
private Track.Id id;
private UUID uuid = UUID.randomUUID();
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@Deprecated
@VisibleForTesting
public TrackBuilder(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
@Deprecated
public TrackBuilder(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
public TrackBuilder(Track track) {
this.id = track.id();
this.uuid = track.uuid();
this.name = track.name();
this.description = track.description();
this.activityTypeLocalized = track.activityTypeLocalized();
this.activityType = track.activityType();
this.zoneOffset = track.zoneOffset();
this.trackStatistics = track.statistics();
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
@Deprecated
public Track.Id getId() {
return id;
}
public void setId(Track.Id id) {
this.id = id;
}
@Deprecated
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
@Deprecated
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Deprecated
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Deprecated
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
@Deprecated
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
@Deprecated
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
@Deprecated
public OffsetDateTime getStartTime() {
return trackStatistics
.startTime().atOffset(zoneOffset);
}
@Deprecated
public OffsetDateTime getStopTime() {
return trackStatistics
.stopTime().atOffset(zoneOffset);
}
@Deprecated
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
public Track getTrack() {
return new Track(
id,
uuid,
name,
description,
activityTypeLocalized,
activityType,
zoneOffset,
trackStatistics
);
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
}
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.models.DistanceFormatter;
import de.dennisguse.opentracks.data.models.SpeedFormatter;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
@@ -42,7 +43,7 @@ import de.dennisguse.opentracks.stats.SensorStatistics;
import de.dennisguse.opentracks.util.StringUtils;
/**
* A fragment to display track statistics to the user for a recorded {@link Track}.
* A fragment to display track statistics to the user for a recorded {@link TrackBuilder}.
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
@@ -147,7 +148,7 @@ public class StatisticsRecordedFragment extends Fragment {
sensorStatistics = contentProviderUtils.getSensorStats(trackId);
boolean prefsChanged = this.track == null || (!this.track.getActivityTypeLocalized().equals(track.getActivityTypeLocalized()));
boolean prefsChanged = this.track == null || (!this.track.activityTypeLocalized().equals(track.activityTypeLocalized()));
this.track = track;
if (prefsChanged) {
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, getString(R.string.stats_rate_key));
@@ -162,13 +163,13 @@ public class StatisticsRecordedFragment extends Fragment {
}
private void loadTrackDescription(@NonNull Track track) {
viewBinding.statsNameValue.setText(track.getName());
viewBinding.statsDescriptionValue.setText(track.getDescription());
viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.getStartTime()));
viewBinding.statsNameValue.setText(track.name());
viewBinding.statsDescriptionValue.setText(track.description());
viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.startTime()));
}
private void updateUI() {
Statistics trackStatistics = track.getStatistics();
Statistics trackStatistics = track.statistics();
// Set total distance
{
Pair<String, String> parts = DistanceFormatter.Builder()
@@ -180,7 +181,7 @@ public class StatisticsRecordedFragment extends Fragment {
}
// Set activity type
viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), track.getActivityType().getIconDrawableId()));
viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), track.activityType().getIconDrawableId()));
// Set time and start datetime
{
@@ -15,11 +15,11 @@ import androidx.gridlayout.widget.GridLayout;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
@@ -31,7 +31,7 @@ import de.dennisguse.opentracks.viewmodels.Mapping;
import de.dennisguse.opentracks.viewmodels.StatisticViewHolder;
/**
* A fragment to display track statistics to the user for a currently recording {@link Track}.
* A fragment to display track statistics to the user for a currently recording {@link TrackBuilder}.
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
@@ -167,9 +167,9 @@ public class StatisticsRecordingFragment extends Fragment {
private void onRecordingDataChanged(RecordingData recordingData) {
Track oldTrack = this.recordingData.track();
String oldActivityType = oldTrack != null ? oldTrack.getActivityTypeLocalized() : "";
String oldActivityType = oldTrack != null ? oldTrack.activityTypeLocalized() : "";
Track newTrack = recordingData.track();
String newActivityType = newTrack != null ? newTrack.getActivityTypeLocalized() : "";
String newActivityType = newTrack != null ? newTrack.activityTypeLocalized() : "";
this.recordingData = recordingData;
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks.io.file;
import androidx.annotation.NonNull;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
@@ -12,8 +11,10 @@ import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.util.FileUtils;
public class TrackFilenameGenerator {
@@ -41,11 +42,11 @@ public class TrackFilenameGenerator {
public String format(@NonNull Track track, @NonNull TrackFileFormat trackFileFormat) {
Map<String, String> values = new HashMap<>();
values.put(UUID_KEY, track.getUuid().toString().substring(0, 8));
values.put(TRACKNAME_KEY, track.getName());
values.put(ACTIVITY_TYPE_KEY, track.getActivityTypeLocalized());
values.put(STARTTIME_TIME_KEY, track.getStartTime().toLocalTime().toString());
values.put(STARTTIME_DATE_KEY, track.getStartTime().toLocalDate().toString());
values.put(UUID_KEY, track.uuid().toString().substring(0, 8));
values.put(TRACKNAME_KEY, track.name());
values.put(ACTIVITY_TYPE_KEY, track.activityTypeLocalized());
values.put(STARTTIME_TIME_KEY, track.startTime().toLocalTime().toString());
values.put(STARTTIME_DATE_KEY, track.stopTime().toLocalDate().toString());
return format(format(template, values), trackFileFormat);
}
@@ -90,9 +91,16 @@ public class TrackFilenameGenerator {
}
public String getExample() {
Track track = new Track(ZoneOffset.UTC, Statistics.DEFAULT);
track.setName("Berlin");
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"));
Track track = new Track(
null,
UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
"Berlin",
"",
"",
ActivityType.CYCLING,
ZoneOffset.UTC,
Statistics.DEFAULT
);
return format(track, TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES);
}
@@ -111,7 +111,7 @@ public class CSVTrackExporter implements TrackExporter {
boolean headerWritten = false;
for (Track track : tracks) {
columns.get(0).extractor = t -> quote(StringUtils.formatDateTimeIso8601(t.getTime(), track.getZoneOffset()));
columns.get(0).extractor = t -> quote(StringUtils.formatDateTimeIso8601(t.getTime(), track.zoneOffset()));
if (!headerWritten) {
writeHeader(columns);
@@ -131,7 +131,7 @@ public class CSVTrackExporter implements TrackExporter {
}
private void writeTrackPoints(List<Column> columns, Track track) throws InterruptedException {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -40,6 +40,7 @@ import de.dennisguse.opentracks.AbstractActivity;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.ExportActivityBinding;
import de.dennisguse.opentracks.io.file.ErrorListDialog;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
@@ -222,9 +223,9 @@ public class ExportActivity extends AbstractActivity {
exportTasks = new ArrayList<>();
if (allInOneFile) {
String filename = "OpenTracks-Backup";
exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).toList()));
exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::id).toList()));
} else {
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).toList());
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.id()))).toList());
}
trackExportTotalCount = exportTasks.size();
}
@@ -362,7 +363,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) {
name = exportTask.getFilename();
} else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName();
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).name();
}
Log.e(TAG, "Error exporting " + name + ": " + errorMessage);
trackErrors.add(name);
@@ -402,7 +403,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) {
name = exportTask.getFilename();
} else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName();
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).name();
}
viewBinding.exportProgressAlertMsg.setText(getString(R.string.export_track_already_exists_msg, name));
setConflictVisibility(View.VISIBLE);
@@ -25,6 +25,7 @@ import java.util.List;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.io.file.exporter;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -128,7 +129,7 @@ public class GPXTrackExporter implements TrackExporter {
LinkedList<TrackPoint> sensorPoints = new LinkedList<>();
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -152,7 +153,7 @@ public class GPXTrackExporter implements TrackExporter {
writeOpenSegment();
wroteSegment = true;
if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear();
} else {
sensorPoints.add(trackPoint);
@@ -165,7 +166,7 @@ public class GPXTrackExporter implements TrackExporter {
wroteSegment = true;
}
if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear();
} else {
sensorPoints.add(trackPoint);
@@ -238,12 +239,12 @@ public class GPXTrackExporter implements TrackExporter {
}
private void writeMarkers(Track track) throws InterruptedException {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
writeMarker(track.getZoneOffset(), markerIterator.next());
writeMarker(track.zoneOffset(), markerIterator.next());
}
}
}
@@ -262,19 +263,19 @@ public class GPXTrackExporter implements TrackExporter {
private void writeBeginTrack(Track track) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityType().getId()) + "</type>");
printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.description()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.activityType().getId()) + "</type>");
printWriter.println("<extensions>");
printWriter.println("<topografix:color>c0c0c0</topografix:color>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
printWriter.println("<opentracks:trackid>" + track.uuid() + "</opentracks:trackid>");
if (track.getActivityTypeLocalized() != null || !track.getActivityTypeLocalized().isBlank()) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>");
if (!TextUtils.isEmpty(track.activityTypeLocalized())) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.activityTypeLocalized()) + "</opentracks:typeTranslated>");
}
Statistics trackStatistics = track.getStatistics();
Statistics trackStatistics = track.statistics();
printWriter.println("<gpxtrkx:TrackStatsExtension>");
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.totalDistance().toM() + "</gpxtrkx:Distance>");
printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.totalDuration().getSeconds() + "</gpxtrkx:TimerTime>");
@@ -136,7 +136,7 @@ public class KMLTrackExporter implements TrackExporter {
private void writeMarkers(Track track) throws InterruptedException {
boolean hasMarkers = false;
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -145,7 +145,7 @@ public class KMLTrackExporter implements TrackExporter {
hasMarkers = true;
}
writeMarker(markerIterator.next(), track.getZoneOffset());
writeMarker(markerIterator.next(), track.zoneOffset());
}
}
if (hasMarkers) {
@@ -157,7 +157,7 @@ public class KMLTrackExporter implements TrackExporter {
boolean wroteTrack = false;
boolean wroteSegment = false;
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -171,12 +171,12 @@ public class KMLTrackExporter implements TrackExporter {
case SEGMENT_START_MANUAL, SEGMENT_START_AUTOMATIC -> {
if (wroteSegment) writeCloseSegment();
writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
wroteSegment = true;
}
case SEGMENT_END_MANUAL -> {
if (!wroteSegment) writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
writeCloseSegment();
wroteSegment = false;
}
@@ -187,7 +187,7 @@ public class KMLTrackExporter implements TrackExporter {
wroteSegment = true;
}
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
}
default ->
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.getType());
@@ -239,7 +239,7 @@ public class KMLTrackExporter implements TrackExporter {
printWriter.println("<visibility>1</visibility>");
Track track = tracks.get(0);
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<atom:generator>" + StringUtils.formatCData(context.getString(R.string.app_name)) + "</atom:generator>");
writeTrackStyle();
@@ -261,7 +261,7 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginMarkers(Track track) {
printWriter.println("<Folder>");
printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.getName())) + "</name>");
printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.name())) + "</name>");
printWriter.println("<open>1</open>");
}
@@ -291,13 +291,13 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginTrack(Track track) {
printWriter.println("<Placemark>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.description()) + "</description>");
printWriter.println("<opentracks:trackid>" + track.uuid() + "</opentracks:trackid>");
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityType());
writeTypeLocalized(track.getActivityTypeLocalized());
writeActivityType(track.activityType());
writeTypeLocalized(track.activityTypeLocalized());
printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>");
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
@@ -35,6 +34,7 @@ import java.util.zip.ZipOutputStream;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
import de.dennisguse.opentracks.util.FileUtils;
@@ -90,14 +90,14 @@ public class KMZTrackExporter implements TrackExporter {
private void addImages(Context context, List<Track> tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException {
for (Track track : tracks) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
Marker marker = markerIterator.next();
if (marker.hasPhoto()) {
Uri uriPhoto = marker.getPhotoUrl();
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null;
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.id(), uriPhoto) != null;
if (existsPhoto) {
addImage(context, zipOutputStream, uriPhoto, marker);
}
@@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.List;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
/**
* Track exporting for exporting track to an {@link OutputStream}.
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.importer;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
@@ -31,7 +30,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -25,6 +25,7 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
@@ -146,12 +147,16 @@ public class TrackImporter {
adjustTrackPoints();
TrackStatisticsUpdater updater = new TrackStatisticsUpdater(trackPoints);
Track track = new Track(trackData.zoneOffset, updater.getTrackStatistics());
track.setName(trackData.name);
track.setUuid(trackData.uuid);
track.setDescription(trackData.description);
track.setActivityType(trackData.activityType);
track.setActivityTypeLocalized(trackData.activityTypeLocalized);
Track track = new Track(
null,
trackData.uuid,
trackData.name,
trackData.description,
trackData.activityTypeLocalized,
trackData.activityType,
trackData.zoneOffset,
updater.getTrackStatistics()
);
Track.Id trackId = contentProviderUtils.insertTrack(track);
@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.IntentDashboardUtils;
@@ -39,14 +40,14 @@ public class StartRecording extends AbstractAPIActivity {
private void updateTrackMetadata(@NonNull Track.Id trackId, @NonNull Bundle bundle) {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
Track track = contentProviderUtils.getTrack(trackId);
TrackBuilder track = new TrackBuilder(contentProviderUtils.getTrack(trackId));
track.setName(bundle.getString(EXTRA_TRACK_NAME, ""));
track.setDescription(bundle.getString(EXTRA_TRACK_DESCRIPTION, ""));
track.setActivityType(ActivityType.findBy(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_ID, null)));
track.setActivityTypeLocalized(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_LOCALIZED, ""));
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(track.getTrack());
}
private void startDashboardAPI(@NonNull Track.Id trackId, @NonNull Bundle bundle) {
@@ -11,7 +11,7 @@ public class StopRecording extends AbstractAPIActivity {
RecordingData recordingData = service.getRecordingDataObservable().getValue();
Track.Id trackId = null;
if (recordingData != null && recordingData.track() != null) {
trackId = recordingData.track().getId();
trackId = recordingData.track().id();
}
service.endCurrentTrack();
@@ -1,14 +1,12 @@
package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
/**
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
* {@link TrackPoint} must be immutable (i.e., their content does not change).
*/
public record RecordingData(
Track track,
@@ -19,6 +17,6 @@ public record RecordingData(
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null, null);
public Statistics trackStatistics() {
return track.getStatistics();
return track.statistics();
}
}
@@ -19,6 +19,7 @@ import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager;
@@ -71,14 +72,14 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime());
trackStatisticsUpdater = new TrackStatisticsUpdater(segmentStartTrackPoint);
Track track = new Track(zoneOffset, trackStatisticsUpdater.getTrackStatistics());
TrackBuilder track = new TrackBuilder(zoneOffset, trackStatisticsUpdater.getTrackStatistics());
String activityTypeLocalized = PreferencesUtils.getDefaultActivityTypeLocalized();
track.setActivityTypeLocalized(activityTypeLocalized);
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
trackId = contentProviderUtils.insertTrack(track);
trackId = contentProviderUtils.insertTrack(track.getTrack());
onNewTrackPoint(segmentStartTrackPoint);
@@ -96,7 +97,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return false;
}
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getStatistics());
trackStatisticsUpdater = new TrackStatisticsUpdater(track.statistics());
onNewTrackPoint(trackPointCreator.createSegmentStartManual());
reset();
@@ -127,9 +128,10 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return null;
}
track.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
TrackBuilder trackBuilder = new TrackBuilder(track);
trackBuilder.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
return new RecordingData(track, current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
return new RecordingData(trackBuilder.getTrack(), current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
}
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@@ -149,12 +149,12 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
}
//TODO Avoid reloading (some) TrackPoints just to announce the last interval.
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().getId(), startTrackPointId)) {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().id(), startTrackPointId)) {
startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
Statistics lastInterval = intervalStatistics.getLastInterval();
SensorStatistics sensorStatistics = null;
if (data.track().getId() != null) {
sensorStatistics = contentProviderUtils.getSensorStats(data.track().getId());
if (data.track().id() != null) {
sensorStatistics = contentProviderUtils.getSensorStats(data.track().id());
}
return VoiceAnnouncementUtils.createStatistics(context, data.track(), data.sensorDataSet(), PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(data.track()), lastInterval, sensorStatistics);
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.stats.SensorStatistics;
@@ -51,12 +52,12 @@ class VoiceAnnouncementUtils {
}
static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable Statistics currentInterval, @Nullable SensorStatistics sensorStatistics) {
Statistics trackStatistics = track.getStatistics();
Statistics trackStatistics = track.statistics();
SpannableStringBuilder builder = new SpannableStringBuilder();
if (shouldVoiceAnnounceTime()) {
appendTime(builder, track.getStopTime());
appendTime(builder, track.stopTime());
}
Distance totalDistance = trackStatistics.totalDistance();
@@ -48,6 +48,7 @@ import de.dennisguse.opentracks.data.models.DistanceFormatter;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.HeartRateZones;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
import de.dennisguse.opentracks.sensors.SensorType;
@@ -252,7 +253,7 @@ public class PreferencesUtils {
}
public static boolean isReportSpeed(Track track) {
return isReportSpeed(track.getActivityTypeLocalized());
return isReportSpeed(track.activityTypeLocalized());
}
private static String getBluetoothSensorAddressNone() {
@@ -15,6 +15,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.ShareContentProvider;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -31,6 +31,7 @@ import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.SpeedFormatter;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.util.StringUtils;
@@ -62,10 +63,10 @@ public class TrackShareSummaryGenerator {
builder.append(TEXT_LINE_BREAK);
builder.append(TEXT_LINE_BREAK);
writeString(track.getName(), builder, R.string.generic_name_line);
writeString(track.getActivityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.getDescription(), builder, R.string.generic_description_line);
builder.append(generateTrackStatisticsDescription(track.getStatistics()));
writeString(track.name(), builder, R.string.generic_name_line);
writeString(track.activityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.description(), builder, R.string.generic_description_line);
builder.append(generateTrackStatisticsDescription(track.statistics()));
return builder.toString();
}
@@ -30,11 +30,11 @@ import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
/**
* Statistical data about a {@link Track}.
* Statistical data about a {@link TrackBuilder}.
* The data in this class should be filled out by {@link TrackStatisticsUpdater}.
*
* @author Rodrigo Damazio
@@ -18,6 +18,7 @@ import java.util.Optional;
import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
@@ -25,6 +26,7 @@ import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.CustomStatsItemBinding;
import de.dennisguse.opentracks.services.RecordingData;
@@ -54,7 +56,16 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
null,
null
);
Track track = new Track(ZoneOffset.UTC, statistics);
Track track = new Track(
null,
null,
"",
"",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
statistics);
Position position = new Position(
Instant.ofEpochMilli(0),
@@ -23,6 +23,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.DistanceFormatter;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
@@ -192,7 +192,7 @@ public class MarkerListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
viewBinding.markerListItemName.setText(marker.getName());
{
ZoneOffset timeZone = new ContentProviderUtils(context).getTrack(marker.getTrackId()).getZoneOffset();
ZoneOffset timeZone = new ContentProviderUtils(context).getTrack(marker.getTrackId()).zoneOffset();
ListItemUtils.setDateAndTime(context, viewBinding.markerListItemDate, viewBinding.markerListItemTime, marker.getTime(), timeZone);
}