Idle: TrackRecordingManager creates IDLE TrackPoints (configurable timeout).

Fixes of #1187.
This commit is contained in:
Dennis Guse
2023-07-31 21:55:55 +02:00
parent 00debe2eb5
commit 78d2a0722a
37 changed files with 41 additions and 99 deletions
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks.data.models;
import java.time.Duration;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
public record Speed(double speed_mps) {
@@ -56,10 +55,6 @@ public record Speed(double speed_mps) {
return Double.isNaN(speed_mps) || Double.isInfinite(speed_mps);
}
public boolean isMoving() {
return !isInvalid() && greaterThan(PreferencesUtils.getIdleSpeed());
}
public boolean lessThan(Speed speed) {
return !greaterThan(speed);
}
@@ -34,8 +34,6 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
private static final String TAG = TrackRecordingManager.class.getSimpleName();
private static final Duration IDLE_TIMEOUT = Duration.ofSeconds(30);
private static final AltitudeCorrectionManager ALTITUDE_CORRECTION_MANAGER = new AltitudeCorrectionManager();
private final Runnable ON_IDLE = this::onIdle;
@@ -49,6 +47,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
private Distance recordingDistanceInterval;
private Distance maxRecordingDistance;
private Duration idleDuration;
private Track.Id trackId;
private TrackStatisticsUpdater trackStatisticsUpdater;
@@ -69,7 +68,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
Track.Id startNewTrack() {
TrackPoint segmentStartTrackPoint = trackPointCreator.createSegmentStartManual();
// Create new track
ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime());
Track track = new Track(zoneOffset);
trackId = contentProviderUtils.insertTrack(track);
@@ -83,7 +82,6 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
track.setActivityTypeLocalized(activityTypeLocalized);
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
//TODO Pass TrackPoint
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
contentProviderUtils.updateTrack(track);
@@ -109,7 +107,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return true;
}
void end() {
void endCurrentTrack() {
TrackPoint segmentEnd = trackPointCreator.createSegmentEnd();
insertTrackPoint(segmentEnd, true);
@@ -223,7 +221,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
insertTrackPoint(trackPoint, true);
handler.removeCallbacks(ON_IDLE);
handler.postDelayed(ON_IDLE, IDLE_TIMEOUT.toMillis());
handler.postDelayed(ON_IDLE, idleDuration.toMillis());
return true;
}
@@ -231,7 +229,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
insertTrackPoint(trackPoint, false);
handler.removeCallbacks(ON_IDLE);
handler.postDelayed(ON_IDLE, IDLE_TIMEOUT.toMillis());
handler.postDelayed(ON_IDLE, idleDuration.toMillis());
return true;
}
@@ -297,5 +295,8 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
if (PreferencesUtils.isKey(R.string.max_recording_distance_key, key)) {
maxRecordingDistance = PreferencesUtils.getMaxRecordingDistance();
}
if (PreferencesUtils.isKey(R.string.idle_duration_key, key)) {
idleDuration = PreferencesUtils.getIdleDurationTimeout();
}
}
}
@@ -214,7 +214,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
// Set recording status
updateRecordingStatus(STATUS_DEFAULT);
trackRecordingManager.end();
trackRecordingManager.endCurrentTrack();
stopUpdateRecordingData();
@@ -79,7 +79,7 @@ public class GpsSettingsFragment extends PreferenceFragmentCompat {
ListPreference recordingGpsAccuracy = findPreference(getString(R.string.recording_gps_accuracy_key));
recordingGpsAccuracy.setEntries(PreferencesUtils.getThresholdHorizontalAccuracyEntries());
ListPreference idleSpeed = findPreference(getString(R.string.idle_speed_key));
idleSpeed.setEntries(PreferencesUtils.getIdleSpeedEntries());
ListPreference idleDuration = findPreference(getString(R.string.idle_duration_key));
idleDuration.setEntries(PreferencesUtils.getIdleDurationEntries());
}
}
@@ -45,7 +45,6 @@ import de.dennisguse.opentracks.data.models.Distance;
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.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
@@ -530,11 +529,12 @@ public class PreferencesUtils {
static String[] getMinRecordingIntervalEntries() {
String[] entryValues = resources.getStringArray(R.array.min_recording_interval_values);
long recommended = PreferencesUtils.getMinRecordingIntervalDefault().getSeconds();
String[] entries = new String[entryValues.length];
for (int i = 0; i < entryValues.length; i++) {
int value = Integer.parseInt(entryValues[i]);
if (value == PreferencesUtils.getMinRecordingIntervalDefault().getSeconds()) {
if (value == recommended) {
entries[i] = resources.getString(R.string.value_smallest_recommended);
} else {
entries[i] = value < 60 ? resources.getString(R.string.value_integer_second, value) : resources.getString(R.string.value_integer_minute, value / 60);
@@ -598,49 +598,25 @@ public class PreferencesUtils {
return entries;
}
public static Speed getIdleSpeed() {
final float DEFAULT = Float.parseFloat(resources.getString(R.string.idle_speed_default));
float value = getFloat(R.string.idle_speed_key, DEFAULT);
return Speed.ofKMH(value);
public static Duration getIdleDurationTimeout() {
final int DEFAULT = Integer.parseInt(resources.getString(R.string.idle_duration_default));
int value = getInt(R.string.idle_duration_key, DEFAULT);
return Duration.ofSeconds(value);
}
static String[] getIdleSpeedEntries() {
String[] entryValues = resources.getStringArray(R.array.idle_speed_values);
static String[] getIdleDurationEntries() {
String[] entryValues = resources.getStringArray(R.array.idle_duration_values);
String[] entries = new String[entryValues.length];
final float idleSpeedDefault = Float.parseFloat(resources.getString(R.string.idle_speed_default));
UnitSystem unitSystem = getUnitSystem();
final int idleDurationDefault = Integer.parseInt(resources.getString(R.string.idle_duration_default));
for (int i = 0; i < entryValues.length; i++) {
float value = Float.parseFloat(entryValues[i]);
int value = Integer.parseInt(entryValues[i]);
switch (unitSystem) {
case METRIC -> {
if (value == idleSpeedDefault) {
entries[i] = resources.getString(R.string.value_float_kilometer_hour_recommended, value);
} else {
entries[i] = resources.getString(R.string.value_float_kilometer_hour, value);
}
}
case IMPERIAL_FEET, IMPERIAL_METER -> {
double valueMPH = Speed.ofKMH(value).toMPH();
if (value == idleSpeedDefault) {
entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH);
} else {
entries[i] = resources.getString(R.string.value_float_mile_hour, valueMPH);
}
}
case NAUTICAL_IMPERIAL -> {
double valueKnots = Speed.ofKMH(value).toKnots();
if (value == idleSpeedDefault) {
entries[i] = resources.getString(R.string.value_float_knots_recommended, valueKnots);
} else {
entries[i] = resources.getString(R.string.value_float_knots, valueKnots);
}
}
default -> throw new RuntimeException("Not implemented");
if (value == idleDurationDefault) {
entries[i] = resources.getString(R.string.value_int_seconds, value);
} else {
entries[i] = value < 60 ? resources.getString(R.string.value_integer_second, value) : resources.getString(R.string.value_integer_minute, value / 60);
}
}