forked from upstream-mirrors/OpenTracks
@@ -287,11 +287,6 @@ public class TrackPoint {
|
||||
this.speed = speed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isMoving() {
|
||||
return hasSpeed() && getSpeed().isMoving();
|
||||
}
|
||||
|
||||
public boolean hasBearing() {
|
||||
return bearing != null;
|
||||
}
|
||||
@@ -352,9 +347,8 @@ public class TrackPoint {
|
||||
return hasHorizontalAccuracy() && horizontalAccuracy.lessThan(thresholdHorizontalAccuracy);
|
||||
}
|
||||
|
||||
//TODO Bearing requires a location; what do we do if we don't have any?
|
||||
public float bearingTo(@NonNull TrackPoint dest) {
|
||||
return getLocation().bearingTo(dest.getLocation());
|
||||
return bearingTo(dest.getLocation());
|
||||
}
|
||||
|
||||
//TODO Bearing requires a location; what do we do if we don't have any?
|
||||
|
||||
@@ -315,6 +315,10 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
|
||||
if (i < sensorSpeedList.size() && sensorSpeedList.get(i) != null) {
|
||||
trackPoint.setSpeed(Speed.of(sensorSpeedList.get(i)));
|
||||
|
||||
if (TrackPoint.IDLE_SPEED.greaterOrEqualThan(trackPoint.getSpeed())) {
|
||||
trackPoint.setType(TrackPoint.Type.IDLE);
|
||||
}
|
||||
}
|
||||
if (i < sensorDistanceList.size() && sensorDistanceList.get(i) != null) {
|
||||
trackPoint.setSensorDistance(Distance.of(sensorDistanceList.get(i)));
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -32,11 +33,17 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
|
||||
|
||||
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;
|
||||
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
private final Context context;
|
||||
|
||||
private final Handler handler;
|
||||
|
||||
private final TrackPointCreator trackPointCreator;
|
||||
|
||||
private Distance recordingDistanceInterval;
|
||||
@@ -52,9 +59,10 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
|
||||
private TrackPoint lastStoredTrackPoint;
|
||||
private TrackPoint lastStoredTrackPointWithLocation;
|
||||
|
||||
TrackRecordingManager(Context context, TrackPointCreator trackPointCreator) {
|
||||
TrackRecordingManager(Context context, TrackPointCreator trackPointCreator, Handler handler) {
|
||||
this.context = context;
|
||||
this.trackPointCreator = trackPointCreator;
|
||||
this.handler = handler;
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
}
|
||||
|
||||
@@ -154,16 +162,27 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
|
||||
return new Marker.Id(ContentUris.parseId(uri));
|
||||
}
|
||||
|
||||
void onIdle() {
|
||||
Log.d(TAG, "Becoming idle");
|
||||
onNewTrackPoint(trackPointCreator.createIdle());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TrackPoint was stored?
|
||||
*/
|
||||
boolean onNewTrackPoint(@NonNull TrackPoint trackPoint) {
|
||||
synchronized boolean onNewTrackPoint(@NonNull TrackPoint trackPoint) {
|
||||
if (trackPoint.hasSpeed()) {
|
||||
lastTrackPointUIWithSpeed = trackPoint;
|
||||
}
|
||||
if (trackPoint.hasAltitude()) {
|
||||
lastTrackPointUIWithAltitude = trackPoint;
|
||||
}
|
||||
|
||||
if (trackPoint.getType() == TrackPoint.Type.IDLE) {
|
||||
insertTrackPoint(trackPoint, true);
|
||||
handler.removeCallbacks(ON_IDLE);
|
||||
return true;
|
||||
}
|
||||
//Storing trackPoint
|
||||
|
||||
// Always insert the first segment location
|
||||
@@ -184,10 +203,10 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
|
||||
if (!shouldStore) {
|
||||
Log.d(TAG, "Ignoring TrackPoint as it has no distance (and sensor data is not new enough).");
|
||||
return false;
|
||||
} else {
|
||||
insertTrackPoint(trackPoint, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
insertTrackPoint(trackPoint, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
Distance distanceToLastStoredTrackPoint;
|
||||
@@ -200,18 +219,17 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
|
||||
if (distanceToLastStoredTrackPoint.greaterThan(maxRecordingDistance)) {
|
||||
trackPoint.setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
||||
insertTrackPoint(trackPoint, true);
|
||||
|
||||
handler.removeCallbacks(ON_IDLE);
|
||||
handler.postDelayed(ON_IDLE, IDLE_TIMEOUT.toMillis());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (distanceToLastStoredTrackPoint.greaterOrEqualThan(recordingDistanceInterval)
|
||||
&& trackPoint.isMoving()) {
|
||||
if (distanceToLastStoredTrackPoint.greaterOrEqualThan(recordingDistanceInterval)) {
|
||||
insertTrackPoint(trackPoint, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (trackPoint.isMoving() != lastStoredTrackPoint.isMoving()) {
|
||||
// Moving from non-moving to moving or vice versa; required to compute moving time correctly.
|
||||
insertTrackPoint(trackPoint, true);
|
||||
handler.removeCallbacks(ON_IDLE);
|
||||
handler.postDelayed(ON_IDLE, IDLE_TIMEOUT.toMillis());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
gpsStatusObservable = new MutableLiveData<>(STATUS_GPS_DEFAULT);
|
||||
recordingDataObservable = new MutableLiveData<>(NOT_RECORDING);
|
||||
|
||||
trackPointCreator = new TrackPointCreator(this, this, handler);
|
||||
trackRecordingManager = new TrackRecordingManager(this, trackPointCreator);
|
||||
trackPointCreator = new TrackPointCreator(this);
|
||||
trackRecordingManager = new TrackRecordingManager(this, trackPointCreator, handler);
|
||||
|
||||
voiceAnnouncementManager = new VoiceAnnouncementManager(this);
|
||||
notificationManager = new TrackRecordingServiceNotificationManager(this);
|
||||
|
||||
@@ -36,16 +36,11 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
private Clock clock = new MonotonicClock();
|
||||
private SensorManager sensorManager;
|
||||
|
||||
public TrackPointCreator(Callback service, Context context, Handler handler) {
|
||||
public TrackPointCreator(Callback service) {
|
||||
this.service = service;
|
||||
this.sensorManager = new SensorManager(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TrackPointCreator(Callback service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public synchronized void start(@NonNull Context context, @NonNull Handler handler) {
|
||||
this.context = context;
|
||||
|
||||
@@ -106,6 +101,13 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
return segmentEnd;
|
||||
}
|
||||
|
||||
public synchronized TrackPoint createIdle() {
|
||||
TrackPoint idle = new TrackPoint(TrackPoint.Type.IDLE, createNow());
|
||||
addSensorData(idle);
|
||||
reset();
|
||||
return idle;
|
||||
}
|
||||
|
||||
public Pair<TrackPoint, SensorDataSet> createCurrentTrackPoint(@Nullable TrackPoint lastTrackPointUISpeed, @Nullable TrackPoint lastTrackPointUIAltitude, @Nullable TrackPoint lastStoredTrackPointWithLocation) {
|
||||
TrackPoint currentTrackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, createNow());
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ public class TrackStatisticsUpdater {
|
||||
// Current segment's last trackPoint
|
||||
private TrackPoint lastTrackPoint;
|
||||
|
||||
private boolean idle;
|
||||
|
||||
public TrackStatisticsUpdater() {
|
||||
this(new TrackStatistics());
|
||||
}
|
||||
@@ -77,6 +79,7 @@ public class TrackStatisticsUpdater {
|
||||
this.trackStatistics = new TrackStatistics(toCopy.trackStatistics);
|
||||
|
||||
this.lastTrackPoint = toCopy.lastTrackPoint;
|
||||
this.idle = idle;
|
||||
resetAverageHeartRate();
|
||||
}
|
||||
|
||||
@@ -132,26 +135,35 @@ public class TrackStatisticsUpdater {
|
||||
currentSegment.setAverageHeartRate(HeartRate.of(averageHeartRateBPM));
|
||||
}
|
||||
|
||||
// Update total distance
|
||||
if (trackPoint.hasSensorDistance()) {
|
||||
// Sensor-based distance/speed
|
||||
currentSegment.addTotalDistance(trackPoint.getSensorDistance());
|
||||
} else if (lastTrackPoint != null
|
||||
&& lastTrackPoint.hasLocation()
|
||||
&& trackPoint.hasLocation() && trackPoint.isMoving()) {
|
||||
// GPS-based distance/speed
|
||||
// Assumption: we ignore TrackPoints that are not moving as those are likely imprecise GPS measurements
|
||||
Distance movingDistance = trackPoint.distanceToPrevious(lastTrackPoint);
|
||||
currentSegment.addTotalDistance(movingDistance);
|
||||
}
|
||||
{
|
||||
// Update total distance
|
||||
Distance movingDistance = null;
|
||||
if (trackPoint.hasSensorDistance()) {
|
||||
movingDistance = trackPoint.getSensorDistance();
|
||||
} else if (lastTrackPoint != null
|
||||
&& lastTrackPoint.hasLocation()
|
||||
&& trackPoint.hasLocation()) {
|
||||
// GPS-based distance/speed
|
||||
movingDistance = trackPoint.distanceToPrevious(lastTrackPoint);
|
||||
}
|
||||
if (movingDistance != null) {
|
||||
idle = false;
|
||||
currentSegment.addTotalDistance(movingDistance);
|
||||
}
|
||||
|
||||
if (!idle && !trackPoint.isSegmentManualStart()) {
|
||||
if (lastTrackPoint != null) {
|
||||
currentSegment.addMovingTime(trackPoint, lastTrackPoint);
|
||||
}
|
||||
}
|
||||
|
||||
// Update moving time
|
||||
if (trackPoint.isMoving() && lastTrackPoint != null && lastTrackPoint.isMoving()) {
|
||||
currentSegment.addMovingTime(trackPoint, lastTrackPoint);
|
||||
if (trackPoint.getType() == TrackPoint.Type.IDLE) {
|
||||
idle = true;
|
||||
}
|
||||
|
||||
// Update max speed
|
||||
updateSpeed(trackPoint, lastTrackPoint);
|
||||
if (trackPoint.hasSpeed()) {
|
||||
updateSpeed(trackPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (trackPoint.isSegmentManualEnd()) {
|
||||
|
||||
Reference in New Issue
Block a user