TrackPoint has Location as delegate instead of inheritance.

This commit is contained in:
Dennis Guse
2020-03-29 12:30:16 +02:00
parent 901cffee97
commit 194379295d
25 changed files with 288 additions and 184 deletions
@@ -16,6 +16,8 @@
package de.dennisguse.opentracks; package de.dennisguse.opentracks;
import android.location.Location;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorDataSet;
@@ -68,16 +70,15 @@ public class TrackStubUtils {
* @return a SensorDataSetLocation stub. * @return a SensorDataSetLocation stub.
*/ */
private static TrackPoint createSensorDataSetLocation(double latitude, double longitude, double altitude) { private static TrackPoint createSensorDataSetLocation(double latitude, double longitude, double altitude) {
TrackPoint trackPoint = new TrackPoint(LOCATION_PROVIDER); Location location = new Location(LOCATION_PROVIDER);
trackPoint.setLatitude(latitude); location.setLatitude(latitude);
trackPoint.setLongitude(longitude); location.setLongitude(longitude);
trackPoint.setAltitude(altitude); location.setAltitude(altitude);
trackPoint.setAccuracy(INITIAL_ACCURACY); location.setAccuracy(INITIAL_ACCURACY);
trackPoint.setSpeed(INITIAL_SPEED); location.setSpeed(INITIAL_SPEED);
trackPoint.setTime(INITIAL_TIME); location.setTime(INITIAL_TIME);
trackPoint.setBearing(INITIAL_BEARING); location.setBearing(INITIAL_BEARING);
trackPoint.setSensorDataSet(new SensorDataSet(Float.NaN, Float.NaN));
return trackPoint; return new TrackPoint(location, new SensorDataSet(Float.NaN, Float.NaN));
} }
} }
@@ -1,5 +1,7 @@
package de.dennisguse.opentracks.content.data; package de.dennisguse.opentracks.content.data;
import android.location.Location;
public class TestDataUtil { public class TestDataUtil {
public static final double INITIAL_LATITUDE = 37.0; public static final double INITIAL_LATITUDE = 37.0;
@@ -30,12 +32,12 @@ public class TestDataUtil {
* @return created location * @return created location
*/ */
public static TrackPoint createTrackPoint(int i) { public static TrackPoint createTrackPoint(int i) {
TrackPoint trackpoint = new TrackPoint("test"); Location location = new Location("test");
trackpoint.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0); location.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
trackpoint.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0); location.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
trackpoint.setAccuracy((float) i / 100.0f); location.setAccuracy((float) i / 100.0f);
trackpoint.setAltitude(i * ALTITUDE_INTERVAL); location.setAltitude(i * ALTITUDE_INTERVAL);
trackpoint.setTime(i + 1); location.setTime(i + 1);
return trackpoint; return new TrackPoint(location);
} }
} }
@@ -81,7 +81,7 @@ public class CustomContentProviderUtilsTest {
@Test @Test
public void testLocationIterator_customFactory() { public void testLocationIterator_customFactory() {
final TrackPoint location = new TrackPoint("test_location"); final TrackPoint location = new TrackPoint(new Location("test_location"));
final AtomicInteger counter = new AtomicInteger(); final AtomicInteger counter = new AtomicInteger();
testIterator(1, 15, 4, false, new TrackPointFactory() { testIterator(1, 15, 4, false, new TrackPointFactory() {
@Override @Override
@@ -161,12 +161,12 @@ public class CustomContentProviderUtilsTest {
TrackPoint[] trackPoints = new TrackPoint[numPoints]; TrackPoint[] trackPoints = new TrackPoint[numPoints];
for (int i = 0; i < numPoints; ++i) { for (int i = 0; i < numPoints; ++i) {
TrackPoint loc = new TrackPoint("test"); Location loc = new Location("test");
loc.setLatitude(37.0 + (double) i / 10000.0); loc.setLatitude(37.0 + (double) i / 10000.0);
loc.setLongitude(57.0 - (double) i / 10000.0); loc.setLongitude(57.0 - (double) i / 10000.0);
loc.setAccuracy((float) i / 100.0f); loc.setAccuracy((float) i / 100.0f);
loc.setAltitude(i * 2.5); loc.setAltitude(i * 2.5);
trackPoints[i] = loc; trackPoints[i] = new TrackPoint(loc);
} }
contentProviderUtils.bulkInsertTrackPoint(trackPoints, numPoints, id); contentProviderUtils.bulkInsertTrackPoint(trackPoints, numPoints, id);
@@ -646,7 +646,7 @@ public class CustomContentProviderUtilsTest {
insertTrackWithLocations(track); insertTrackWithLocations(track);
TrackPoint lastTrackPoint = contentProviderUtils.getLastValidTrackPoint(trackId); TrackPoint lastTrackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
checkLocation(9, lastTrackPoint); checkLocation(9, lastTrackPoint.getLocation());
} }
/** /**
@@ -709,7 +709,7 @@ public class CustomContentProviderUtilsTest {
Assert.assertTrue(trackPointIterator.hasNext()); Assert.assertTrue(trackPointIterator.hasNext());
TrackPoint trackPoint = trackPointIterator.next(); TrackPoint trackPoint = trackPointIterator.next();
Assert.assertEquals(startTrackPointId - i, trackPointIterator.getTrackPointId()); Assert.assertEquals(startTrackPointId - i, trackPointIterator.getTrackPointId());
checkLocation((trackpointIds.length - 1) - i, trackPoint); checkLocation((trackpointIds.length - 1) - i, trackPoint.getLocation());
} }
Assert.assertFalse(trackPointIterator.hasNext()); Assert.assertFalse(trackPointIterator.hasNext());
} }
@@ -734,10 +734,10 @@ public class CustomContentProviderUtilsTest {
TrackPointIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, startTrackPointId, false, TrackPointFactory.DEFAULT_LOCATION_FACTORY); TrackPointIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, startTrackPointId, false, TrackPointFactory.DEFAULT_LOCATION_FACTORY);
for (int i = 0; i < trackpointIds.length; i++) { for (int i = 0; i < trackpointIds.length; i++) {
Assert.assertTrue(locationIterator.hasNext()); Assert.assertTrue(locationIterator.hasNext());
Location location = locationIterator.next(); TrackPoint trackPoint = locationIterator.next();
Assert.assertEquals(startTrackPointId + i, locationIterator.getTrackPointId()); Assert.assertEquals(startTrackPointId + i, locationIterator.getTrackPointId());
checkLocation(i, location); checkLocation(i, trackPoint.getLocation());
} }
Assert.assertFalse(locationIterator.hasNext()); Assert.assertFalse(locationIterator.hasNext());
} }
@@ -18,6 +18,7 @@ package de.dennisguse.opentracks.io.file.importer;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.Context; import android.content.Context;
import android.location.Location;
import android.location.LocationManager; import android.location.LocationManager;
import android.net.Uri; import android.net.Uri;
@@ -84,12 +85,12 @@ public abstract class AbstractTestFileTrackImporter {
public ContentProviderUtils contentProviderUtils; public ContentProviderUtils contentProviderUtils;
TrackPoint createTrackPoint(int index, long time) { TrackPoint createTrackPoint(int index, long time) {
TrackPoint trackPoint = new TrackPoint(LocationManager.GPS_PROVIDER); Location trackPoint = new Location(LocationManager.GPS_PROVIDER);
trackPoint.setLatitude(TRACK_LATITUDE + index); trackPoint.setLatitude(TRACK_LATITUDE + index);
trackPoint.setLongitude(TRACK_LONGITUDE + index); trackPoint.setLongitude(TRACK_LONGITUDE + index);
trackPoint.setAltitude(TRACK_ELEVATION + index); trackPoint.setAltitude(TRACK_ELEVATION + index);
trackPoint.setTime(time); trackPoint.setTime(time);
return trackPoint; return new TrackPoint(trackPoint);
} }
/** /**
@@ -67,7 +67,7 @@ public class ExportImportTest {
waypoint.setIcon("the waypoing icon" + i); waypoint.setIcon("the waypoing icon" + i);
waypoint.setPhotoUrl("the photo url" + i); waypoint.setPhotoUrl("the photo url" + i);
waypoint.setTrackId(trackId); waypoint.setTrackId(trackId);
waypoint.setLocation(track.getTrackPoints().get(i)); waypoint.setLocation(track.getTrackPoints().get(i).getLocation());
contentProviderUtils.insertWaypoint(waypoint); contentProviderUtils.insertWaypoint(waypoint);
waypoints.add(waypoint); waypoints.add(waypoint);
@@ -43,10 +43,10 @@ public class TrackRecordingServiceNotificationManagerTest {
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder); TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
// when // when
subject.updateLocation(context, locationMock, 100); subject.updateTrackPoint(context, locationMock, 100);
subject.updateLocation(context, locationMock, 100); subject.updateTrackPoint(context, locationMock, 100);
subject.updateLocation(context, locationMock, 1000); subject.updateTrackPoint(context, locationMock, 1000);
subject.updateLocation(context, locationMock, 100); subject.updateTrackPoint(context, locationMock, 100);
// then // then
verify(notificationCompatBuilder, times(6)).setOnlyAlertOnce(true); verify(notificationCompatBuilder, times(6)).setOnlyAlertOnce(true);
@@ -19,6 +19,7 @@ import android.content.ContentProvider;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.location.Location;
import android.os.IBinder; import android.os.IBinder;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -42,7 +43,6 @@ import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.data.Waypoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.content.provider.CustomContentProvider; import de.dennisguse.opentracks.content.provider.CustomContentProvider;
@@ -210,15 +210,15 @@ public class TrackRecordingServiceTest {
/** /**
* Inserts a location and waits for 200ms. * Inserts a location and waits for 200ms.
*/ */
private void insertTrackPoint(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException { private void insertLocation(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException {
TrackPoint trackPoint = new TrackPoint("gps"); Location location = new Location("gps");
trackPoint.setLongitude(35.0f); location.setLongitude(35.0f);
trackPoint.setLatitude(45.0f); location.setLatitude(45.0f);
trackPoint.setAccuracy(5); location.setAccuracy(5);
trackPoint.setSpeed(10); location.setSpeed(10);
trackPoint.setTime(System.currentTimeMillis()); location.setTime(System.currentTimeMillis());
trackPoint.setBearing(3.0f); location.setBearing(3.0f);
trackRecordingService.insertTrackPoint(trackPoint); trackRecordingService.insertLocation(location);
Thread.sleep(200); Thread.sleep(200);
} }
@@ -239,7 +239,7 @@ public class TrackRecordingServiceTest {
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context))); TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
service.startNewTrack(); service.startNewTrack();
Assert.assertTrue(service.isRecording()); Assert.assertTrue(service.isRecording());
insertTrackPoint(service); insertLocation(service);
long trackId = service.getRecordingTrackId(); long trackId = service.getRecordingTrackId();
long waypointId = service.insertWaypoint(null, null, null, null); long waypointId = service.insertWaypoint(null, null, null, null);
@@ -3,6 +3,7 @@ package de.dennisguse.opentracks.services;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.location.Location;
import android.os.Looper; import android.os.Looper;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -25,7 +26,6 @@ import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.content.provider.CustomContentProvider; import de.dennisguse.opentracks.content.provider.CustomContentProvider;
import de.dennisguse.opentracks.stats.TripStatistics; import de.dennisguse.opentracks.stats.TripStatistics;
@@ -208,14 +208,14 @@ public class TrackRecordingServiceTestLooper {
// Insert a few points, markers and statistics. // Insert a few points, markers and statistics.
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
TrackPoint trackPoint = new TrackPoint("gps"); Location location = new Location("gps");
trackPoint.setLongitude(35.0f + i / 10.0f); location.setLongitude(35.0f + i / 10.0f);
trackPoint.setLatitude(45.0f - i / 5.0f); location.setLatitude(45.0f - i / 5.0f);
trackPoint.setAccuracy(5); location.setAccuracy(5);
trackPoint.setSpeed(10); location.setSpeed(10);
trackPoint.setTime(startTime + i * 10000); location.setTime(startTime + i * 10000);
trackPoint.setBearing(3.0f); location.setBearing(3.0f);
service.insertTrackPoint(trackPoint); service.insertLocation(location);
if (i % 7 == 0) { if (i % 7 == 0) {
service.insertWaypoint(null, null, null, null); service.insertWaypoint(null, null, null, null);
@@ -412,7 +412,7 @@ public class TrackDataHub implements DataSourceListener, SharedPreferences.OnSha
samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints); samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints);
} }
if (!LocationUtils.isValidLocation(trackPoint)) { //This can be split markers (not anymore supported feature) if (!LocationUtils.isValidLocation(trackPoint.getLocation())) { //This can be split markers (not anymore supported feature)
includeNextPoint = true; includeNextPoint = true;
} else { } else {
// Also include the last point if the selected track is not recording. // Also include the last point if the selected track is not recording.
@@ -18,6 +18,8 @@ package de.dennisguse.opentracks.content.data;
import android.location.Location; import android.location.Location;
import android.location.LocationManager; import android.location.LocationManager;
import androidx.annotation.NonNull;
import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorDataSet;
/** /**
@@ -25,34 +27,71 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet;
* *
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
//TODO Check if we can drop inheritance from Location and use attributes instead. public class TrackPoint {
public class TrackPoint extends Location {
public static TrackPoint createPause() { private Location location;
TrackPoint pause = new TrackPoint(LocationManager.GPS_PROVIDER);
pause.setLongitude(0); public TrackPoint() {
pause.setLatitude(TrackPointsColumns.PAUSE_LATITUDE); this.location = new Location("");
pause.setTime(System.currentTimeMillis());
return pause;
} }
public static TrackPoint createResume() { public TrackPoint(@NonNull Location location) {
TrackPoint resume = new TrackPoint(LocationManager.GPS_PROVIDER); this.location = location;
resume.setLongitude(0); }
resume.setLatitude(TrackPointsColumns.RESUME_LATITUDE);
resume.setTime(System.currentTimeMillis()); public TrackPoint(@NonNull Location location, SensorDataSet sensorDataSet) {
return resume; this.location = location;
this.sensorDataSet = sensorDataSet;
}
public TrackPoint(@NonNull TrackPoint trackPoint, SensorDataSet sensorDataSet) {
this.location = trackPoint.getLocation();
this.sensorDataSet = sensorDataSet;
} }
private SensorDataSet sensorDataSet = null; private SensorDataSet sensorDataSet = null;
public TrackPoint(Location location, SensorDataSet sensorDataSet) { public TrackPoint(double latitude, double longitude, Double altitude, long time) {
super(location); location = new Location(LocationManager.GPS_PROVIDER);
this.sensorDataSet = sensorDataSet; location.setLatitude(latitude);
location.setLongitude(longitude);
if (altitude != null) {
location.setAltitude(altitude);
}
location.setTime(time);
} }
public TrackPoint(String provider) { public static TrackPoint createPause() {
super(provider); return createPauseWithTime(System.currentTimeMillis());
}
public static TrackPoint createPauseWithTime(long time) {
Location pause = new Location(LocationManager.GPS_PROVIDER);
pause.setLongitude(0);
pause.setLatitude(TrackPointsColumns.PAUSE_LATITUDE);
pause.setTime(time);
return new TrackPoint(pause);
}
public static TrackPoint createResume() {
return createResumeWithTime(System.currentTimeMillis());
}
public static TrackPoint createResumeWithTime(long time) {
Location resume = new Location(LocationManager.GPS_PROVIDER);
resume.setLongitude(0);
resume.setLatitude(TrackPointsColumns.RESUME_LATITUDE);
resume.setTime(time);
return new TrackPoint(resume);
}
public @NonNull
Location getLocation() {
return location;
}
public void setLocation(@NonNull Location location) {
this.location = location;
} }
public SensorDataSet getSensorDataSet() { public SensorDataSet getSensorDataSet() {
@@ -63,8 +102,92 @@ public class TrackPoint extends Location {
this.sensorDataSet = sensorDataSet; this.sensorDataSet = sensorDataSet;
} }
public double getLatitude() {
return location.getLatitude();
}
public void setLatitude(double latitude) {
location.setLatitude(latitude);
}
public double getLongitude() {
return location.getLongitude();
}
public void setLongitude(double longitude) {
location.setLongitude(longitude);
}
public long getTime() {
return location.getTime();
}
public void setTime(long time) {
location.setTime(time);
}
public boolean hasAltitude() {
return location.hasAltitude();
}
public double getAltitude() {
return location.getAltitude();
}
public void setAltitude(double altitude) {
location.setAltitude(altitude);
}
public boolean hasSpeed() {
return location.hasSpeed();
}
public float getSpeed() {
return location.getSpeed();
}
public void setSpeed(float speed) {
location.setSpeed(speed);
}
public boolean hasBearing() {
return location.hasBearing();
}
public float getBearing() {
return location.getBearing();
}
public void setBearing(float bearing) {
location.setBearing(bearing);
}
public boolean hasAccuracy() {
return location.hasAccuracy();
}
public float getAccuracy() {
return location.getAccuracy();
}
public void setAccuracy(float horizontalAccuracy) {
location.setAccuracy(horizontalAccuracy);
}
public float distanceTo(@NonNull TrackPoint dest) {
return location.distanceTo(dest.getLocation());
}
public float bearingTo(@NonNull TrackPoint dest) {
return location.bearingTo(dest.getLocation());
}
public float bearingTo(@NonNull Location dest) {
return location.bearingTo(dest);
}
public void reset() { public void reset() {
super.reset(); location.reset();
sensorDataSet = null; sensorDataSet = null;
} }
} }
@@ -19,6 +19,8 @@ package de.dennisguse.opentracks.content.data;
import android.location.Location; import android.location.Location;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull;
/** /**
* A waypoint. * A waypoint.
* *
@@ -117,11 +119,12 @@ public final class Waypoint {
this.duration = duration; this.duration = duration;
} }
public Location getLocation() { public @NonNull
Location getLocation() {
return location; return location;
} }
public void setLocation(Location location) { public void setLocation(@NonNull Location location) {
this.location = location; this.location = location;
} }
@@ -755,7 +755,7 @@ public class ContentProviderUtils {
* @param cursor the cursor pointing to the location * @param cursor the cursor pointing to the location
*/ */
public TrackPoint createTrackPoint(Cursor cursor) { public TrackPoint createTrackPoint(Cursor cursor) {
TrackPoint location = new TrackPoint(""); TrackPoint location = new TrackPoint();
fillTrackPoint(cursor, new CachedTrackPointsIndexes(cursor), location); fillTrackPoint(cursor, new CachedTrackPointsIndexes(cursor), location);
return location; return location;
} }
@@ -1,5 +1,6 @@
package de.dennisguse.opentracks.content.provider; package de.dennisguse.opentracks.content.provider;
import android.location.Location;
import android.location.LocationManager; import android.location.LocationManager;
import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.data.TrackPoint;
@@ -16,6 +17,6 @@ public class TrackPointFactory {
public static final TrackPointFactory DEFAULT_LOCATION_FACTORY = new TrackPointFactory(); public static final TrackPointFactory DEFAULT_LOCATION_FACTORY = new TrackPointFactory();
public TrackPoint create() { public TrackPoint create() {
return new TrackPoint(LocationManager.GPS_PROVIDER); return new TrackPoint(new Location(LocationManager.GPS_PROVIDER));
} }
} }
@@ -18,7 +18,7 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
private final ContentProviderUtils contentProviderUtils; private final ContentProviderUtils contentProviderUtils;
private final long trackId; private final long trackId;
private final boolean descending; private final boolean descending;
private final TrackPointFactory trackPointFactory; private final TrackPointFactory trackPointFactory; //TODO Remove; seems to be an old performance optimization.
private final CachedTrackPointsIndexes indexes; private final CachedTrackPointsIndexes indexes;
private long lastTrackPointId = -1L; private long lastTrackPointId = -1L;
private Cursor cursor; private Cursor cursor;
@@ -358,7 +358,7 @@ public class StatsFragment extends Fragment implements TrackDataListener {
} }
if (lastTrackPoint != null) { if (lastTrackPoint != null) {
boolean hasFix = !LocationUtils.isLocationOld(lastTrackPoint); boolean hasFix = !LocationUtils.isLocationOld(lastTrackPoint.getLocation());
boolean hasGoodFix = lastTrackPoint.hasAccuracy() && lastTrackPoint.getAccuracy() < recordingGpsAccuracy; boolean hasGoodFix = lastTrackPoint.hasAccuracy() && lastTrackPoint.getAccuracy() < recordingGpsAccuracy;
if (!hasFix || !hasGoodFix) { if (!hasFix || !hasGoodFix) {
@@ -139,7 +139,7 @@ public class FileTrackExporter implements TrackExporter {
setLocationTime(trackPoint, offset); setLocationTime(trackPoint, offset);
locationNumber++; locationNumber++;
boolean isLocationValid = LocationUtils.isValidLocation(trackPoint); boolean isLocationValid = LocationUtils.isValidLocation(trackPoint.getLocation());
boolean isSegmentValid = isLocationValid && isLastLocationValid; boolean isSegmentValid = isLocationValid && isLastLocationValid;
if (!wroteTrack && isSegmentValid) { if (!wroteTrack && isSegmentValid) {
// Found the first two consecutive locations that are valid // Found the first two consecutive locations that are valid
@@ -193,7 +193,7 @@ public class FileTrackExporter implements TrackExporter {
* Sets a trackPoint time. * Sets a trackPoint time.
* *
* @param trackPoint the trackPoint * @param trackPoint the trackPoint
* @param offset the time offset * @param offset the time offset
*/ */
private void setLocationTime(TrackPoint trackPoint, long offset) { private void setLocationTime(TrackPoint trackPoint, long offset) {
if (trackPoint != null) { if (trackPoint != null) {
@@ -213,7 +213,7 @@ public class FileTrackExporter implements TrackExporter {
@Override @Override
public TrackPoint create() { public TrackPoint create() {
if (currentTrackPoint == null) { if (currentTrackPoint == null) {
currentTrackPoint = new TrackPoint(""); currentTrackPoint = new TrackPoint();
} }
return currentTrackPoint; return currentTrackPoint;
} }
@@ -170,7 +170,7 @@ public class GpxTrackWriter implements TrackWriter {
@Override @Override
public void writeTrackPoint(TrackPoint trackPoint) { public void writeTrackPoint(TrackPoint trackPoint) {
if (printWriter != null) { if (printWriter != null) {
printWriter.println("<trkpt " + formatLocation(trackPoint) + ">"); printWriter.println("<trkpt " + formatLocation(trackPoint.getLocation()) + ">");
if (trackPoint.hasAltitude()) { if (trackPoint.hasAltitude()) {
printWriter.println("<ele>" + ELEVATION_FORMAT.format(trackPoint.getAltitude()) + "</ele>"); printWriter.println("<ele>" + ELEVATION_FORMAT.format(trackPoint.getAltitude()) + "</ele>");
} }
@@ -192,7 +192,7 @@ public class KmlTrackWriter implements TrackWriter {
this.startTrackPoint = startTrackPoint; this.startTrackPoint = startTrackPoint;
if (printWriter != null) { if (printWriter != null) {
String name = context.getString(R.string.marker_label_start, track.getName()); String name = context.getString(R.string.marker_label_start, track.getName());
writePlacemark(name, "", "", START_STYLE, startTrackPoint); writePlacemark(name, "", "", START_STYLE, startTrackPoint.getLocation());
printWriter.println("<Placemark>"); printWriter.println("<Placemark>");
if (exportTrackDetail) { if (exportTrackDetail) {
@@ -218,7 +218,7 @@ public class KmlTrackWriter implements TrackWriter {
if (exportTrackDetail) { if (exportTrackDetail) {
String name = context.getString(R.string.marker_label_end, track.getName()); String name = context.getString(R.string.marker_label_end, track.getName());
String description = descriptionGenerator.generateTrackDescription(track, false); String description = descriptionGenerator.generateTrackDescription(track, false);
writePlacemark(name, "", description, END_STYLE, endTrackPoint); writePlacemark(name, "", description, END_STYLE, endTrackPoint.getLocation());
} }
} }
} }
@@ -259,10 +259,10 @@ public class KmlTrackWriter implements TrackWriter {
public void writeTrackPoint(TrackPoint trackPoint) { public void writeTrackPoint(TrackPoint trackPoint) {
if (printWriter != null) { if (printWriter != null) {
if (exportTrackDetail) { if (exportTrackDetail) {
printWriter.println("<when>" + getTime(trackPoint) + "</when>"); printWriter.println("<when>" + getTime(trackPoint.getLocation()) + "</when>");
} }
printWriter.println("<gx:coord>" + getCoordinates(trackPoint, " ") + "</gx:coord>"); printWriter.println("<gx:coord>" + getCoordinates(trackPoint.getLocation(), " ") + "</gx:coord>");
if (exportSensorData) { if (exportSensorData) {
SensorDataSet sensorDataSet = trackPoint.getSensorDataSet(); SensorDataSet sensorDataSet = trackPoint.getSensorDataSet();
@@ -386,7 +386,7 @@ public class KmlTrackWriter implements TrackWriter {
if (trackPointId == -1L) { if (trackPointId == -1L) {
return location.getBearing(); return location.getBearing();
} }
Location viewLocation; TrackPoint viewLocation;
try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackPointId, 10, true)) { try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackPointId, 10, true)) {
if (cursor == null || cursor.getCount() == 0) { if (cursor == null || cursor.getCount() == 0) {
return location.getBearing(); return location.getBearing();
@@ -17,8 +17,6 @@
package de.dennisguse.opentracks.io.file.importer; package de.dennisguse.opentracks.io.file.importer;
import android.content.Context; import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
@@ -40,7 +38,6 @@ import javax.xml.parsers.SAXParserFactory;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.data.Waypoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.content.provider.TrackPointFactory; import de.dennisguse.opentracks.content.provider.TrackPointFactory;
@@ -193,7 +190,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
waypoint = null; waypoint = null;
} else { } else {
// The waypoint trackPoint time matches the track point time // The waypoint trackPoint time matches the track point time
if (!LocationUtils.isValidLocation(trackPoint)) { if (!LocationUtils.isValidLocation(trackPoint.getLocation())) {
// Invalid trackPoint, load the next trackPoint // Invalid trackPoint, load the next trackPoint
trackPoint = null; trackPoint = null;
continue; continue;
@@ -207,7 +204,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
long duration = trackTripStatisticstrackUpdater.getTripStatistics().getTotalTime(); long duration = trackTripStatisticstrackUpdater.getTripStatistics().getTotalTime();
// Insert waypoint // Insert waypoint
Waypoint newWaypoint = new Waypoint(waypoint.getName(), waypointDescription, waypoint.getCategory(), icon, track.getId(), length, duration, trackPoint, waypoint.getPhotoUrl()); Waypoint newWaypoint = new Waypoint(waypoint.getName(), waypointDescription, waypoint.getCategory(), icon, track.getId(), length, duration, trackPoint.getLocation(), waypoint.getPhotoUrl());
contentProviderUtils.insertWaypoint(newWaypoint); contentProviderUtils.insertWaypoint(newWaypoint);
} }
@@ -274,7 +271,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
//If not the first segment, add a pause separator if there is at least one location in the last segment. //If not the first segment, add a pause separator if there is at least one location in the last segment.
if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment != null) { if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment != null) {
insertLocation(createTrackPoint(TrackPointsColumns.PAUSE_LATITUDE, 0.0, 0.0, trackData.lastLocationInCurrentSegment.getTime())); insertLocation(TrackPoint.createPauseWithTime(trackData.lastLocationInCurrentSegment.getTime()));
} }
trackData.lastLocationInCurrentSegment = null; trackData.lastLocationInCurrentSegment = null;
} }
@@ -289,12 +286,12 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
} }
Waypoint waypoint = new Waypoint(); Waypoint waypoint = new Waypoint();
TrackPoint location = createTrackPoint(); TrackPoint trackPoint = createTrackPoint();
if (!LocationUtils.isValidLocation(location)) { if (!LocationUtils.isValidLocation(trackPoint.getLocation())) {
throw new SAXException(createErrorMessage("Invalid location detected: " + location)); throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint));
} }
waypoint.setLocation(location); waypoint.setLocation(trackPoint.getLocation());
if (name != null) { if (name != null) {
waypoint.setName(name); waypoint.setName(name);
@@ -316,11 +313,11 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
* Gets a track point. * Gets a track point.
*/ */
protected TrackPoint getTrackPoint() throws SAXException { protected TrackPoint getTrackPoint() throws SAXException {
TrackPoint location = createTrackPoint(); TrackPoint trackPoint = createTrackPoint();
// Calculate derived attributes from the previous point // Calculate derived attributes from the previous point
if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) { if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) {
long timeDifference = location.getTime() - trackData.lastLocationInCurrentSegment.getTime(); long timeDifference = trackPoint.getTime() - trackData.lastLocationInCurrentSegment.getTime();
// Check for negative time change // Check for negative time change
if (timeDifference <= 0) { if (timeDifference <= 0) {
@@ -332,22 +329,22 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
* GPS points tend to have some inherent imprecision, speed and bearing will likely be off, so the statistics for things like max speed will also be off. * GPS points tend to have some inherent imprecision, speed and bearing will likely be off, so the statistics for things like max speed will also be off.
*/ */
double duration = timeDifference * UnitConversions.MS_TO_S; double duration = timeDifference * UnitConversions.MS_TO_S;
double speed = trackData.lastLocationInCurrentSegment.distanceTo(location) / duration; double speed = trackData.lastLocationInCurrentSegment.distanceTo(trackPoint) / duration;
location.setSpeed((float) speed); trackPoint.setSpeed((float) speed);
} }
location.setBearing(trackData.lastLocationInCurrentSegment.bearingTo(location)); trackPoint.setBearing(trackData.lastLocationInCurrentSegment.bearingTo(trackPoint));
} }
if (!LocationUtils.isValidLocation(location)) { if (!LocationUtils.isValidLocation(trackPoint.getLocation())) {
throw new SAXException(createErrorMessage("Invalid location detected: " + location)); throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint));
} }
if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment == null) { if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment == null) {
// If not the first segment, add a resume separator before adding the first location. // If not the first segment, add a resume separator before adding the first location.
insertLocation(createTrackPoint(TrackPointsColumns.RESUME_LATITUDE, 0.0, 0.0, location.getTime())); insertLocation(TrackPoint.createResumeWithTime(trackPoint.getTime()));
} }
trackData.lastLocationInCurrentSegment = location; trackData.lastLocationInCurrentSegment = trackPoint;
return location; return trackPoint;
} }
/** /**
@@ -416,31 +413,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e); throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e);
} }
} }
return createTrackPoint(latitudeValue, longitudeValue, altitudeValue, timeValue); return new TrackPoint(latitudeValue, longitudeValue, altitudeValue, timeValue);
}
/**
* Creates a location.
*
* @param latitudeValue the latitude value
* @param longitudeValue the longitude value
* @param altitudeValue the altitude value
* @param timeValue the time value
*/
private TrackPoint createTrackPoint(double latitudeValue, double longitudeValue, Double altitudeValue, long timeValue) {
TrackPoint location = new TrackPoint(LocationManager.GPS_PROVIDER);
location.setLatitude(latitudeValue);
location.setLongitude(longitudeValue);
if (altitudeValue != null) {
location.setAltitude(altitudeValue);
} else {
location.removeAltitude();
}
location.setTime(timeValue);
location.removeAccuracy();
location.removeBearing();
location.removeSpeed();
return location;
} }
/** /**
@@ -499,7 +472,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
int numberOfSegments = 0; int numberOfSegments = 0;
// The last location in the current segment; Null if the current segment doesn't have a last location // The last location in the current segment; Null if the current segment doesn't have a last location
Location lastLocationInCurrentSegment; TrackPoint lastLocationInCurrentSegment;
// The number of locations processed for the current track // The number of locations processed for the current track
int numberOfLocations = 0; int numberOfLocations = 0;
@@ -311,7 +311,7 @@ public class TrackRecordingService extends Service {
long duration = stats.getTotalTime(); long duration = stats.getTotalTime();
// Insert waypoint // Insert waypoint
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, length, duration, trackPoint, photoUrl); Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, length, duration, trackPoint.getLocation(), photoUrl);
Uri uri = contentProviderUtils.insertWaypoint(waypoint); Uri uri = contentProviderUtils.insertWaypoint(waypoint);
return ContentUris.parseId(uri); return ContentUris.parseId(uri);
} }
@@ -568,7 +568,8 @@ public class TrackRecordingService extends Service {
return; return;
} }
notificationManager.updateLocation(this, location, recordingGpsAccuracy); TrackPoint trackPoint = new TrackPoint(location, getSensorDataSet());
notificationManager.updateTrackPoint(this, trackPoint, recordingGpsAccuracy);
if (!location.hasAccuracy() || location.getAccuracy() >= recordingGpsAccuracy) { if (!location.hasAccuracy() || location.getAccuracy() >= recordingGpsAccuracy) {
Log.d(TAG, "Ignore onLocationChangedAsync. Poor accuracy."); Log.d(TAG, "Ignore onLocationChangedAsync. Poor accuracy.");
@@ -583,15 +584,14 @@ public class TrackRecordingService extends Service {
TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId()); TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId());
long idleTime = 0L; long idleTime = 0L;
if (lastValidTrackPoint != null && location.getTime() > lastValidTrackPoint.getTime()) { if (lastValidTrackPoint != null && location.getTime() > lastValidTrackPoint.getLocation().getTime()) {
idleTime = location.getTime() - lastValidTrackPoint.getTime(); idleTime = location.getTime() - lastValidTrackPoint.getLocation().getTime();
} }
locationListenerPolicy.updateIdleTime(idleTime); locationListenerPolicy.updateIdleTime(idleTime);
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) { if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
registerLocationListener(); registerLocationListener();
} }
TrackPoint trackPoint = new TrackPoint(location, getSensorDataSet());
// Always insert the first segment location // Always insert the first segment location
if (!currentSegmentHasLocation) { if (!currentSegmentHasLocation) {
@@ -601,14 +601,14 @@ public class TrackRecordingService extends Service {
return; return;
} }
if (!LocationUtils.isValidLocation(lastValidTrackPoint)) { if (!LocationUtils.isValidLocation(lastValidTrackPoint.getLocation())) {
// Should not happen. The current segment should have a location. Just insert the current location. // Should not happen. The current segment should have a location. Just insert the current location.
insertTrackPoint(track, trackPoint, null); insertTrackPoint(track, trackPoint, null);
lastTrackPoint = trackPoint; lastTrackPoint = trackPoint;
return; return;
} }
double distanceToLastTrackLocation = location.distanceTo(lastValidTrackPoint); double distanceToLastTrackLocation = location.distanceTo(lastValidTrackPoint.getLocation());
if (distanceToLastTrackLocation > maxRecordingDistance) { if (distanceToLastTrackLocation > maxRecordingDistance) {
insertTrackPoint(track, lastTrackPoint, lastValidTrackPoint); insertTrackPoint(track, lastTrackPoint, lastValidTrackPoint);
insertTrackPoint(track, TrackPoint.createPause(), null); insertTrackPoint(track, TrackPoint.createPause(), null);
@@ -637,10 +637,10 @@ public class TrackRecordingService extends Service {
* Inserts a trackPoint. * Inserts a trackPoint.
* *
* @param track the track * @param track the track
* @param trackPoint the trackPoint * @param trackPoint the trackPoint
* @param lastValidTrackPoint the last valid track point, can be null * @param lastValidTrackPoint the last valid track point, can be null
*/ */
private void insertTrackPoint(Track track, TrackPoint trackPoint, Location lastValidTrackPoint) { private void insertTrackPoint(Track track, TrackPoint trackPoint, TrackPoint lastValidTrackPoint) {
if (trackPoint == null) { if (trackPoint == null) {
Log.w(TAG, "Ignore insertLocation. trackPoint is null."); Log.w(TAG, "Ignore insertLocation. trackPoint is null.");
return; return;
@@ -1,8 +1,9 @@
package de.dennisguse.opentracks.services; package de.dennisguse.opentracks.services;
import android.location.Location;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorDataSet;
/** /**
@@ -82,8 +83,8 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
@VisibleForTesting @VisibleForTesting
@Override @Override
public void insertTrackPoint(TrackPoint trackPoint) { public void insertLocation(Location location) {
trackRecordingService.onLocationChangedAsync(trackPoint); trackRecordingService.onLocationChangedAsync(location);
} }
@Override @Override
@@ -15,9 +15,10 @@
*/ */
package de.dennisguse.opentracks.services; package de.dennisguse.opentracks.services;
import android.location.Location;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorDataSet;
/** /**
@@ -95,15 +96,15 @@ public interface TrackRecordingServiceInterface {
/** /**
* ONLY FOR TESTING * ONLY FOR TESTING
* *
* Inserts a track point in the current recording track. * Inserts a location in the current recording track.
* <p> * <p>
* When recording a track, GPS locations are automatically inserted. This is used for * When recording a track, GPS locations are automatically inserted.
* inserting special track points or for testing. * This is used for inserting special track points or for testing.
* *
* @param trackPoint the track point to be inserted * @param location the location to be inserted
*/ */
@VisibleForTesting @VisibleForTesting
void insertTrackPoint(TrackPoint trackPoint); void insertLocation(Location location);
/** /**
* Gets the current sensor data. Returns null if there is no data. * Gets the current sensor data. Returns null if there is no data.
@@ -5,13 +5,13 @@ import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.location.Location;
import android.os.Build; import android.os.Build;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
@@ -63,12 +63,12 @@ class TrackRecordingServiceNotificationManager {
updateNotification(); updateNotification();
} }
void updateLocation(Context context, Location location, int recordingGpsAccuracy) { void updateTrackPoint(Context context, TrackPoint trackPoint, int recordingGpsAccuracy) {
String formattedAccuracy = context.getString(R.string.value_none); String formattedAccuracy = context.getString(R.string.value_none);
if (location.hasAccuracy()) { if (trackPoint.hasAccuracy()) {
formattedAccuracy = StringUtils.formatDistance(context, location.getAccuracy(), PreferencesUtils.isMetricUnits(context)); formattedAccuracy = StringUtils.formatDistance(context, trackPoint.getAccuracy(), PreferencesUtils.isMetricUnits(context));
boolean currentLocationWasAccurate = location.getAccuracy() < recordingGpsAccuracy; boolean currentLocationWasAccurate = trackPoint.getAccuracy() < recordingGpsAccuracy;
boolean shouldAlert = !currentLocationWasAccurate && previousLocationWasAccurate; boolean shouldAlert = !currentLocationWasAccurate && previousLocationWasAccurate;
notificationBuilder.setOnlyAlertOnce(!shouldAlert); notificationBuilder.setOnlyAlertOnce(!shouldAlert);
previousLocationWasAccurate = currentLocationWasAccurate; previousLocationWasAccurate = currentLocationWasAccurate;
@@ -16,7 +16,6 @@
package de.dennisguse.opentracks.stats; package de.dennisguse.opentracks.stats;
import android.location.Location;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -82,10 +81,10 @@ public class TripStatisticsUpdater {
// The current segment's trip statistics // The current segment's trip statistics
private TripStatistics currentSegment; private TripStatistics currentSegment;
// Current segment's last location. // Current segment's last trackPoint
private Location lastLocation; private TrackPoint lastTrackPoint;
// Current segment's last moving location // Current segment's last moving trackPoint
private Location lastMovingLocation; private TrackPoint lastMovingTrackPoint;
/** /**
* Creates a new trip statistics updater. * Creates a new trip statistics updater.
@@ -131,18 +130,18 @@ public class TripStatisticsUpdater {
*/ */
public void addTrackPoint(TrackPoint trackPoint, int minRecordingDistance) { public void addTrackPoint(TrackPoint trackPoint, int minRecordingDistance) {
// Always update time // Always update time
updateTime(trackPoint.getTime()); updateTime(trackPoint.getLocation().getTime());
if (!LocationUtils.isValidLocation(trackPoint)) { if (!LocationUtils.isValidLocation(trackPoint.getLocation())) {
// Either pause or resume marker // Either pause or resume marker
if (trackPoint.getLatitude() == TrackPointsColumns.PAUSE_LATITUDE) { if (trackPoint.getLocation().getLatitude() == TrackPointsColumns.PAUSE_LATITUDE) {
if (lastLocation != null && lastMovingLocation != null && lastLocation != lastMovingLocation) { if (lastTrackPoint != null && lastMovingTrackPoint != null && lastTrackPoint != lastMovingTrackPoint) {
currentSegment.addTotalDistance(lastMovingLocation.distanceTo(lastLocation)); currentSegment.addTotalDistance(lastMovingTrackPoint.distanceTo(lastTrackPoint));
} }
tripStatistics.merge(currentSegment); tripStatistics.merge(currentSegment);
} }
currentSegment = init(trackPoint.getTime()); currentSegment = init(trackPoint.getLocation().getTime());
lastLocation = null; lastTrackPoint = null;
lastMovingLocation = null; lastMovingTrackPoint = null;
elevationBuffer.reset(); elevationBuffer.reset();
runBuffer.reset(); runBuffer.reset();
gradeBuffer.reset(); gradeBuffer.reset();
@@ -153,21 +152,21 @@ public class TripStatisticsUpdater {
//TODO Use Barometer to compute elevation gain. //TODO Use Barometer to compute elevation gain.
double elevationDifference = trackPoint.hasAltitude() ? updateElevation(trackPoint.getAltitude()) : 0.0; double elevationDifference = trackPoint.hasAltitude() ? updateElevation(trackPoint.getAltitude()) : 0.0;
if (lastLocation == null || lastMovingLocation == null) { if (lastTrackPoint == null || lastMovingTrackPoint == null) {
lastLocation = trackPoint; lastTrackPoint = trackPoint;
lastMovingLocation = trackPoint; lastMovingTrackPoint = trackPoint;
return; return;
} }
double movingDistance = lastMovingLocation.distanceTo(trackPoint); double movingDistance = lastMovingTrackPoint.distanceTo(trackPoint);
if (movingDistance < minRecordingDistance && (!trackPoint.hasSpeed() || trackPoint.getSpeed() < MAX_NO_MOVEMENT_SPEED)) { if (movingDistance < minRecordingDistance && (!trackPoint.hasSpeed() || trackPoint.getSpeed() < MAX_NO_MOVEMENT_SPEED)) {
speedBuffer.reset(); speedBuffer.reset();
lastLocation = trackPoint; lastTrackPoint = trackPoint;
return; return;
} }
long movingTime = trackPoint.getTime() - lastLocation.getTime(); long movingTime = trackPoint.getTime() - lastTrackPoint.getTime();
if (movingTime < 0) { if (movingTime < 0) {
lastLocation = trackPoint; lastTrackPoint = trackPoint;
return; return;
} }
@@ -178,16 +177,16 @@ public class TripStatisticsUpdater {
currentSegment.addMovingTime(movingTime); currentSegment.addMovingTime(movingTime);
// Update grade // Update grade
double run = lastLocation.distanceTo(trackPoint); double run = lastTrackPoint.distanceTo(trackPoint);
updateGrade(run, elevationDifference); updateGrade(run, elevationDifference);
// Update max speed // Update max speed
if (trackPoint.hasSpeed() && lastLocation.hasSpeed()) { if (trackPoint.hasSpeed() && lastTrackPoint.hasSpeed()) {
updateSpeed(trackPoint.getTime(), trackPoint.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed()); updateSpeed(trackPoint.getTime(), trackPoint.getSpeed(), lastTrackPoint.getTime(), lastTrackPoint.getSpeed());
} }
lastLocation = trackPoint; lastTrackPoint = trackPoint;
lastMovingLocation = trackPoint; lastMovingTrackPoint = trackPoint;
} }
public void addTrackPoint(TrackPointIterator iterator, int minRecordingDistance) { public void addTrackPoint(TrackPointIterator iterator, int minRecordingDistance) {
@@ -115,8 +115,7 @@ public class LocationUtils {
current = stack.pop(); current = stack.pop();
maxDist = 0; maxDist = 0;
for (idx = current[0] + 1; idx < current[1]; ++idx) { for (idx = current[0] + 1; idx < current[1]; ++idx) {
dist = LocationUtils.distance( dist = LocationUtils.distance(trackPoints.get(idx).getLocation(), trackPoints.get(current[0]).getLocation(), trackPoints.get(current[1]).getLocation());
trackPoints.get(idx), trackPoints.get(current[0]), trackPoints.get(current[1]));
if (dist > maxDist) { if (dist > maxDist) {
maxDist = dist; maxDist = dist;
maxIdx = idx; maxIdx = idx;
@@ -165,7 +164,7 @@ public class LocationUtils {
* @param location the location to test * @param location the location to test
* @return true if the location is a valid location. * @return true if the location is a valid location.
*/ */
//TODO Still needed? //TODO Move to TrackPoint
public static boolean isValidLocation(Location location) { public static boolean isValidLocation(Location location) {
return location != null return location != null
&& Math.abs(location.getLatitude()) <= 90 && Math.abs(location.getLatitude()) <= 90