mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-03 09:53:06 +02:00
Introduced TrackPoint.Id.
This commit is contained in:
@@ -83,8 +83,8 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
|
||||
// Track points sampling state
|
||||
private int numLoadedPoints;
|
||||
private long firstSeenTrackPointId;
|
||||
private long lastSeenTrackPointId;
|
||||
private TrackPoint.Id firstSeenTrackPointId;
|
||||
private TrackPoint.Id lastSeenTrackPointId;
|
||||
|
||||
// Registered listeners
|
||||
private ContentObserver tracksTableObserver;
|
||||
@@ -351,36 +351,42 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
}
|
||||
|
||||
int localNumLoadedTrackPoints = updateSamplingState ? numLoadedPoints : 0;
|
||||
long localFirstSeenTrackPointId = updateSamplingState ? firstSeenTrackPointId : -1L;
|
||||
long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L;
|
||||
long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId;
|
||||
TrackPoint.Id localFirstSeenTrackPointId = updateSamplingState ? firstSeenTrackPointId : null;
|
||||
TrackPoint.Id localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : null;
|
||||
TrackPoint.Id maxPointId = updateSamplingState ? null : lastSeenTrackPointId;
|
||||
|
||||
if (selectedTrackId == null) {
|
||||
Log.w(TAG, "This should not happen, but it does"); //TODO
|
||||
return;
|
||||
}
|
||||
|
||||
long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId);
|
||||
TrackPoint.Id lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId);
|
||||
int samplingFrequency = -1;
|
||||
boolean includeNextPoint = false;
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, localLastSeenTrackPointIdId + 1)) {
|
||||
|
||||
TrackPoint.Id next;
|
||||
if (localLastSeenTrackPointIdId != null) {
|
||||
next = new TrackPoint.Id(localLastSeenTrackPointIdId.getId() + 1); //TODO startTrackPointId + 1 is an assumption assumption; should be derived from the DB.
|
||||
}
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, null)) {
|
||||
|
||||
while (trackPointIterator.hasNext()) {
|
||||
TrackPoint trackPoint = trackPointIterator.next();
|
||||
long trackPointId = trackPointIterator.getTrackPointId();
|
||||
TrackPoint.Id trackPointId = trackPoint.getId();
|
||||
|
||||
// Stop if past the last wanted point
|
||||
if (maxPointId != -1L && trackPointId > maxPointId) {
|
||||
if (maxPointId != null && trackPointId.getId() > maxPointId.getId()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (localFirstSeenTrackPointId == -1) {
|
||||
if (localFirstSeenTrackPointId == null) {
|
||||
localFirstSeenTrackPointId = trackPointId;
|
||||
}
|
||||
|
||||
if (samplingFrequency == -1) {
|
||||
long numTotalPoints = Math.max(0L, lastTrackPointId - localFirstSeenTrackPointId);
|
||||
long numTotalPoints = Math.max(0L, lastTrackPointId.getId() - localFirstSeenTrackPointId.getId()); //TODO That is an assumption; should be derived from the DB.
|
||||
samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints);
|
||||
}
|
||||
|
||||
@@ -421,8 +427,8 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
*/
|
||||
private void resetSamplingState() {
|
||||
numLoadedPoints = 0;
|
||||
firstSeenTrackPointId = -1L;
|
||||
lastSeenTrackPointId = -1L;
|
||||
firstSeenTrackPointId = null;
|
||||
lastSeenTrackPointId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,8 +82,8 @@ public final class Marker {
|
||||
/**
|
||||
* May be null if the it was not loaded from the database.
|
||||
*/
|
||||
public @Nullable
|
||||
Id getId() {
|
||||
@Nullable
|
||||
public Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@ public final class Marker {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
Track.Id getTrackId() {
|
||||
@NonNull
|
||||
public Track.Id getTrackId() {
|
||||
return trackId;
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ public final class Marker {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
Location getLocation() {
|
||||
@NonNull
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ public class Track {
|
||||
/**
|
||||
* May be null if the track was not loaded from the database.
|
||||
*/
|
||||
public @Nullable
|
||||
Id getId() {
|
||||
@Nullable
|
||||
public Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,16 +17,23 @@ package de.dennisguse.opentracks.content.data;
|
||||
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class extends the standard Android location with extra information.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
//TODO Merge constructors by use case; we have too many.
|
||||
public class TrackPoint {
|
||||
|
||||
private TrackPoint.Id id;
|
||||
|
||||
private final Location location;
|
||||
|
||||
private Float heartRate_bpm = null;
|
||||
@@ -92,8 +99,20 @@ public class TrackPoint {
|
||||
return new TrackPoint(resume);
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
Location getLocation() {
|
||||
/**
|
||||
* May be null if the track was not loaded from the database.
|
||||
*/
|
||||
@Nullable
|
||||
public TrackPoint.Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(TrackPoint.Id id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@@ -251,4 +270,41 @@ public class TrackPoint {
|
||||
public String toString() {
|
||||
return "time=" + getTime() + ": lat=" + getLatitude() + " lng=" + getLongitude() + " acc=" + getAccuracy();
|
||||
}
|
||||
|
||||
public static class Id {
|
||||
|
||||
private final long id;
|
||||
|
||||
public Id(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
protected Id(Parcel in) {
|
||||
id = in.readLong();
|
||||
}
|
||||
|
||||
//TOOD Limit visibility to TrackRecordingService / ContentProvider
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TrackPoint.Id id1 = (TrackPoint.Id) o;
|
||||
return id == id1.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,6 +545,9 @@ public class ContentProviderUtils {
|
||||
*/
|
||||
static TrackPoint fillTrackPoint(Cursor cursor, CachedTrackPointsIndexes indexes) {
|
||||
TrackPoint trackPoint = new TrackPoint();
|
||||
if (!cursor.isNull(indexes.longitudeIndex)) {
|
||||
trackPoint.setId(new TrackPoint.Id(cursor.getInt(indexes.idIndex)));
|
||||
}
|
||||
|
||||
if (!cursor.isNull(indexes.longitudeIndex)) {
|
||||
trackPoint.setLongitude(((double) cursor.getInt(indexes.longitudeIndex)) / 1E6);
|
||||
@@ -622,15 +625,15 @@ public class ContentProviderUtils {
|
||||
* @param trackId the track id
|
||||
*/
|
||||
@Deprecated
|
||||
public long getLastTrackPointId(@NonNull Track.Id trackId) {
|
||||
public TrackPoint.Id getLastTrackPointId(@NonNull Track.Id trackId) {
|
||||
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)";
|
||||
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
||||
return new TrackPoint.Id(cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)));
|
||||
}
|
||||
}
|
||||
return -1L;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -640,15 +643,15 @@ public class ContentProviderUtils {
|
||||
* @param location the location
|
||||
* @return trackPoint id if the location is in the track. -1L otherwise.
|
||||
*/
|
||||
public long getTrackPointId(Track.Id trackId, Location location) {
|
||||
public TrackPoint.Id getTrackPointId(Track.Id trackId, Location location) {
|
||||
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.TIME + "=?)";
|
||||
String[] selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(location.getTime())};
|
||||
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
||||
return new TrackPoint.Id(cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)));
|
||||
}
|
||||
}
|
||||
return -1L;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -667,12 +670,12 @@ public class ContentProviderUtils {
|
||||
* @param startTrackPointId the starting trackPoint id. `null` to ignore
|
||||
* @param maxLocations maximum number of locations to return. `null` for no limit
|
||||
*/
|
||||
public Cursor getTrackPointCursor(Track.Id trackId, Long startTrackPointId, Integer maxLocations) {
|
||||
public Cursor getTrackPointCursor(Track.Id trackId, TrackPoint.Id startTrackPointId, Integer maxLocations) {
|
||||
String selection;
|
||||
String[] selectionArgs;
|
||||
if (startTrackPointId != null) {
|
||||
selection = TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns._ID + ">=?";
|
||||
selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(startTrackPointId)};
|
||||
selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(startTrackPointId.getId())};
|
||||
} else {
|
||||
selection = TrackPointsColumns.TRACKID + "=?";
|
||||
selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||
@@ -765,7 +768,7 @@ public class ContentProviderUtils {
|
||||
* @param trackId the track id
|
||||
* @param startTrackPointId the starting trackPoint id. `null` to ignore
|
||||
*/
|
||||
public TrackPointIterator getTrackPointLocationIterator(final Track.Id trackId, final Long startTrackPointId) {
|
||||
public TrackPointIterator getTrackPointLocationIterator(final Track.Id trackId, final TrackPoint.Id startTrackPointId) {
|
||||
return new TrackPointIterator(this, trackId, startTrackPointId);
|
||||
}
|
||||
|
||||
@@ -794,7 +797,7 @@ public class ContentProviderUtils {
|
||||
public List<TrackPoint> getTrackPoints(Track.Id trackId) {
|
||||
List<TrackPoint> trackPoints = null;
|
||||
|
||||
try (Cursor trackPointCursor = getTrackPointCursor(trackId, -1L, -1)) {
|
||||
try (Cursor trackPointCursor = getTrackPointCursor(trackId, null, null)) {
|
||||
if (trackPointCursor != null) {
|
||||
trackPointCursor.moveToFirst();
|
||||
trackPoints = new ArrayList<>(trackPointCursor.getCount());
|
||||
|
||||
@@ -19,11 +19,11 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
private final Track.Id trackId;
|
||||
private final CachedTrackPointsIndexes indexes;
|
||||
private long lastTrackPointId = -1L;
|
||||
private TrackPoint.Id lastTrackPointId = null;
|
||||
private Cursor cursor;
|
||||
|
||||
|
||||
public TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, Long startTrackPointId) {
|
||||
public TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, TrackPoint.Id startTrackPointId) {
|
||||
this.contentProviderUtils = contentProviderUtils;
|
||||
this.trackId = trackId;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
*
|
||||
* @param trackPointId the starting track point id
|
||||
*/
|
||||
private Cursor getCursor(long trackPointId) {
|
||||
private Cursor getCursor(TrackPoint.Id trackPointId) {
|
||||
return contentProviderUtils.getTrackPointCursor(trackId, trackPointId, contentProviderUtils.getDefaultCursorBatchSize());
|
||||
}
|
||||
|
||||
@@ -45,17 +45,13 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
* Advances the cursor to the next batch. Returns true if successful.
|
||||
*/
|
||||
private boolean advanceCursorToNextBatch() {
|
||||
long trackPointId = lastTrackPointId == -1L ? -1L : lastTrackPointId + 1;
|
||||
TrackPoint.Id trackPointId = lastTrackPointId == null ? null : new TrackPoint.Id(lastTrackPointId.getId() + 1);
|
||||
Log.d(TAG, "Advancing track point id: " + trackPointId);
|
||||
cursor.close();
|
||||
cursor = getCursor(trackPointId);
|
||||
return cursor != null;
|
||||
}
|
||||
|
||||
public long getTrackPointId() {
|
||||
return lastTrackPointId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (cursor == null) {
|
||||
@@ -83,7 +79,7 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
lastTrackPointId = cursor.getLong(indexes.idIndex);
|
||||
lastTrackPointId = new TrackPoint.Id(cursor.getLong(indexes.idIndex));
|
||||
return ContentProviderUtils.fillTrackPoint(cursor, indexes);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ public class FileTrackExporter implements TrackExporter {
|
||||
boolean isLastLocationValid = false;
|
||||
TrackPoint lastTrackPoint = null;
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L)) {
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
|
||||
while (trackPointIterator.hasNext()) {
|
||||
if (Thread.interrupted()) {
|
||||
|
||||
@@ -398,8 +398,8 @@ public class KmlTrackWriter implements TrackWriter {
|
||||
* @param location the location
|
||||
*/
|
||||
private float getHeading(Track.Id trackId, Location location) {
|
||||
long trackPointId = contentProviderUtils.getTrackPointId(trackId, location);
|
||||
if (trackPointId == -1L) {
|
||||
TrackPoint.Id trackPointId = contentProviderUtils.getTrackPointId(trackId, location);
|
||||
if (trackPointId == null) {
|
||||
return location.getBearing();
|
||||
}
|
||||
TrackPoint viewLocation = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
// TODO Should not be necessary anymore?
|
||||
TrackStatisticsUpdater markerTrackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics().getStartTime_ms());
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L)) {
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
|
||||
while (true) {
|
||||
if (marker == null) {
|
||||
|
||||
@@ -352,7 +352,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
|
||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics().getStartTime_ms());
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L)) {
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
trackStatisticsUpdater.addTrackPoint(trackPointIterator, recordingDistanceInterval);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "RuntimeException", e);
|
||||
|
||||
Reference in New Issue
Block a user