mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 17:43:06 +02:00
@@ -15,6 +15,7 @@ class CachedTrackPointsIndexes {
|
||||
final int timeIndex;
|
||||
final int altitudeIndex;
|
||||
final int accuracyIndex;
|
||||
final int accuracyVerticalIndex;
|
||||
final int speedIndex;
|
||||
final int bearingIndex;
|
||||
final int sensorHeartRateIndex;
|
||||
@@ -32,6 +33,7 @@ class CachedTrackPointsIndexes {
|
||||
timeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.TIME);
|
||||
altitudeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ALTITUDE);
|
||||
accuracyIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.HORIZONTAL_ACCURACY);
|
||||
accuracyVerticalIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.VERTICAL_ACCURACY);
|
||||
speedIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED);
|
||||
bearingIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING);
|
||||
sensorHeartRateIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_HEARTRATE);
|
||||
|
||||
@@ -573,6 +573,9 @@ public class ContentProviderUtils {
|
||||
if (!cursor.isNull(indexes.accuracyIndex)) {
|
||||
trackPoint.setHorizontalAccuracy(Distance.of(cursor.getFloat(indexes.accuracyIndex)));
|
||||
}
|
||||
if (!cursor.isNull(indexes.accuracyVerticalIndex)) {
|
||||
trackPoint.setVerticalAccuracy(Distance.of(cursor.getFloat(indexes.accuracyVerticalIndex)));
|
||||
}
|
||||
if (!cursor.isNull(indexes.speedIndex)) {
|
||||
trackPoint.setSpeed(Speed.of(cursor.getFloat(indexes.speedIndex)));
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
|
||||
|
||||
private static final int DATABASE_VERSION = 33;
|
||||
private static final int DATABASE_VERSION = 34;
|
||||
|
||||
public CustomSQLiteOpenHelper(Context context) {
|
||||
this(context, ((Startup) context.getApplicationContext()).getDatabaseName());
|
||||
@@ -91,6 +91,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 33:
|
||||
upgradeFrom32to33(db);
|
||||
break;
|
||||
case 34:
|
||||
upgradeFrom33to34(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
||||
@@ -133,6 +136,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 32:
|
||||
downgradeFrom33to32(db);
|
||||
break;
|
||||
case 33:
|
||||
downgradeFrom34to33(db);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
||||
}
|
||||
@@ -206,7 +212,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("ALTER TABLE tracks ADD COLUMN uuid BLOB");
|
||||
try (Cursor cursor = db.query("tracks", new String[]{"_id"}, null, null, null, null, null)) {
|
||||
try (Cursor cursor = db.query("tracks", new String[]{"_id" }, null, null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
|
||||
do {
|
||||
@@ -396,7 +402,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.beginTransaction();
|
||||
|
||||
// TrackPoints
|
||||
//TODO That does not restore deleted trackpoints
|
||||
// Info: this does not restore deleted trackpoints
|
||||
db.execSQL("UPDATE trackpoints SET latitude = 200 * 1E6, longitude = NULL WHERE type = -2");
|
||||
db.execSQL("UPDATE trackpoints SET latitude = 100 * 1E6, longitude = NULL WHERE type = 1");
|
||||
|
||||
@@ -481,7 +487,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
ZoneRules zoneRules = ZoneOffset.systemDefault().getRules();
|
||||
|
||||
try (Cursor cursor = db.query("tracks", new String[]{"_id", "starttime"}, null, null, null, null, null)) {
|
||||
try (Cursor cursor = db.query("tracks", new String[]{"_id", "starttime" }, null, null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
|
||||
int startTimeIndex = cursor.getColumnIndexOrThrow("starttime");
|
||||
@@ -513,6 +519,33 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("CREATE UNIQUE INDEX tracks_uuid_index ON tracks(uuid)");
|
||||
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add accuracy_vertical
|
||||
*/
|
||||
private void upgradeFrom33to34(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("ALTER TABLE trackpoints ADD COLUMN accuracy_vertical FLOAT");
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
private void downgradeFrom34to33(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("ALTER TABLE trackpoints RENAME TO trackpoints_old");
|
||||
db.execSQL("CREATE TABLE trackpoints (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, longitude INTEGER, latitude INTEGER, time INTEGER, elevation FLOAT, accuracy FLOAT, speed FLOAT, bearing FLOAT, sensor_heartrate FLOAT, sensor_cadence FLOAT, sensor_power FLOAT, elevation_gain FLOAT, elevation_loss FLOAT, type TEXT CHECK(type IN (-2, -1, 0, 1)), sensor_distance FLOAT, FOREIGN KEY (trackid) REFERENCES tracks(_id) ON UPDATE CASCADE ON DELETE CASCADE)");
|
||||
db.execSQL("INSERT INTO trackpoints SELECT _id, trackid, longitude, latitude, time, elevation, accuracy, speed, bearing, sensor_heartrate, sensor_cadence, sensor_power, elevation_gain, elevation_gain, type, sensor_distance FROM trackpoints_old");
|
||||
db.execSQL("DROP TABLE trackpoints_old");
|
||||
|
||||
db.execSQL("CREATE INDEX trackpoints_trackid_index ON trackpoints(trackid)");
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package de.dennisguse.opentracks.data.models;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -44,6 +45,7 @@ public class TrackPoint {
|
||||
private Double latitude;
|
||||
private Double longitude;
|
||||
private Distance horizontalAccuracy;
|
||||
private Distance verticalAccuracy;
|
||||
private Altitude altitude;
|
||||
private Speed speed;
|
||||
private Float bearing;
|
||||
@@ -205,6 +207,9 @@ public class TrackPoint {
|
||||
this.altitude = location.hasAltitude() ? Altitude.WGS84.of(location.getAltitude()) : null;
|
||||
this.speed = location.hasSpeed() ? Speed.of(location.getSpeed()) : null;
|
||||
this.horizontalAccuracy = location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
this.verticalAccuracy = location.hasVerticalAccuracy() ? Distance.of(location.getVerticalAccuracyMeters()) : null;
|
||||
}
|
||||
|
||||
//TODO Should we copy the bearing?
|
||||
return this;
|
||||
@@ -309,6 +314,19 @@ public class TrackPoint {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasVerticalAccuracy() {
|
||||
return verticalAccuracy != null;
|
||||
}
|
||||
|
||||
public Distance getVerticalAccuracy() {
|
||||
return verticalAccuracy;
|
||||
}
|
||||
|
||||
public TrackPoint setVerticalAccuracy(Distance horizontalAccuracy) {
|
||||
this.verticalAccuracy = horizontalAccuracy;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Distance distanceToPrevious(@NonNull TrackPoint previous) {
|
||||
if (hasSensorDistance()) {
|
||||
|
||||
@@ -46,6 +46,7 @@ public interface TrackPointsColumns extends BaseColumns {
|
||||
String TIME = "time";
|
||||
String ALTITUDE = "elevation";
|
||||
String HORIZONTAL_ACCURACY = "accuracy";
|
||||
String VERTICAL_ACCURACY = "accuracy_vertical";
|
||||
String SPEED = "speed";
|
||||
String BEARING = "bearing";
|
||||
String SENSOR_HEARTRATE = "sensor_heartrate";
|
||||
@@ -79,6 +80,7 @@ public interface TrackPointsColumns extends BaseColumns {
|
||||
+ ALTITUDE_LOSS + " FLOAT, "
|
||||
+ TYPE + " TEXT CHECK(type IN (-2, -1, 0, 1, 2)), "
|
||||
+ SENSOR_DISTANCE + " FLOAT, "
|
||||
+ VERTICAL_ACCURACY + " FLOAT, "
|
||||
+ "FOREIGN KEY (" + TRACKID + ") REFERENCES " + TracksColumns.TABLE_NAME + "(" + TracksColumns._ID + ") ON UPDATE CASCADE ON DELETE CASCADE"
|
||||
+ ")";
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ public class CSVTrackExporter implements TrackExporter {
|
||||
new Column("longitude", t -> t.hasLocation() ? COORDINATE_FORMAT.format(t.getLatitude()) : ""),
|
||||
new Column("altitude", t -> t.hasAltitude() ? COORDINATE_FORMAT.format(t.getAltitude().toM()) : ""),
|
||||
new Column("accuracy_horizontal", t -> t.hasHorizontalAccuracy() ? DISTANCE_FORMAT.format(t.getHorizontalAccuracy().toM()) : ""),
|
||||
new Column("accuracy_vertical", t -> t.hasVerticalAccuracy() ? DISTANCE_FORMAT.format(t.getVerticalAccuracy().toM()) : ""),
|
||||
|
||||
new Column("speed", t -> t.hasSpeed() ? SPEED_FORMAT.format(t.getSpeed().toKMH()) : ""),
|
||||
new Column("altitude_gain", t -> t.hasAltitudeGain() ? DISTANCE_FORMAT.format(t.getAltitudeGain()) : ""),
|
||||
|
||||
@@ -361,6 +361,9 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
if (trackPoint.hasHorizontalAccuracy()) {
|
||||
trackPointExtensionContent += ("<opentracks:accuracy_horizontal>" + DISTANCE_FORMAT.format(trackPoint.getHorizontalAccuracy().toM()) + "</opentracks:accuracy_horizontal>");
|
||||
}
|
||||
if (trackPoint.hasVerticalAccuracy()) {
|
||||
trackPointExtensionContent += ("<opentracks:accuracy_vertical>" + DISTANCE_FORMAT.format(trackPoint.getVerticalAccuracy().toM()) + "</opentracks:accuracy_vertical>");
|
||||
}
|
||||
|
||||
cumulativeDistance = Distance.ofOrNull(cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasSensorDistance() ? tp.getSensorDistance().toM() : null));
|
||||
if (cumulativeDistance != null) {
|
||||
|
||||
@@ -66,6 +66,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
public static final String EXTENDED_DATA_TYPE_ALTITUDE_GAIN = "elevation_gain";
|
||||
public static final String EXTENDED_DATA_TYPE_ALTITUDE_LOSS = "elevation_loss";
|
||||
public static final String EXTENDED_DATA_TYPE_ACCURACY_HORIZONTAL = "accuracy_horizontal";
|
||||
public static final String EXTENDED_DATA_TYPE_ACCURACY_VERTICAL = "accuracy_vertical";
|
||||
|
||||
private static final String MARKER_ICON = "http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png";
|
||||
private static final String TRACK_ICON = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
|
||||
@@ -90,6 +91,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
private final List<Float> altitudeGainList = new ArrayList<>();
|
||||
private final List<Float> altitudeLossList = new ArrayList<>();
|
||||
private final List<Float> accuracyHorizontal = new ArrayList<>();
|
||||
private final List<Float> accuracyVertical = new ArrayList<>();
|
||||
|
||||
public KMLTrackExporter(Context context, boolean exportPhotos) {
|
||||
this.context = context;
|
||||
@@ -336,6 +338,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
altitudeGainList.clear();
|
||||
altitudeLossList.clear();
|
||||
accuracyHorizontal.clear();
|
||||
accuracyVertical.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +371,9 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
if (accuracyHorizontal.stream().anyMatch(Objects::nonNull)) {
|
||||
writeSimpleArrayData(accuracyHorizontal, EXTENDED_DATA_TYPE_ACCURACY_HORIZONTAL);
|
||||
}
|
||||
if (accuracyVertical.stream().anyMatch(Objects::nonNull)) {
|
||||
writeSimpleArrayData(accuracyVertical, EXTENDED_DATA_TYPE_ACCURACY_VERTICAL);
|
||||
}
|
||||
printWriter.println("</SchemaData>");
|
||||
printWriter.println("</ExtendedData>");
|
||||
printWriter.println("</gx:Track>");
|
||||
@@ -394,6 +400,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
altitudeGainList.add(trackPoint.hasAltitudeGain() ? trackPoint.getAltitudeGain() : null);
|
||||
altitudeLossList.add(trackPoint.hasAltitudeLoss() ? trackPoint.getAltitudeLoss() : null);
|
||||
accuracyHorizontal.add(trackPoint.hasHorizontalAccuracy() ? (float) trackPoint.getHorizontalAccuracy().toM() : null);
|
||||
accuracyVertical.add(trackPoint.hasVerticalAccuracy() ? (float) trackPoint.getVerticalAccuracy().toM() : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private static final String TAG_EXTENSION_LOSS = "opentracks:loss";
|
||||
private static final String TAG_EXTENSION_DISTANCE = "opentracks:distance";
|
||||
private static final String TAG_EXTENSION_ACCURACY_HORIZONTAL = "opentracks:accuracy_horizontal";
|
||||
|
||||
private static final String TAG_EXTENSION_ACCURACY_VERTICAL = "opentracks:accuracy_vertical";
|
||||
private Locator locator;
|
||||
|
||||
private final Context context;
|
||||
@@ -114,6 +114,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private String loss;
|
||||
private String sensorDistance;
|
||||
private String accuracyHorizontal;
|
||||
private String accuracyVertical;
|
||||
|
||||
private final LinkedList<TrackPoint> currentSegment = new LinkedList<>();
|
||||
|
||||
@@ -247,6 +248,11 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
accuracyHorizontal = content.trim();
|
||||
}
|
||||
break;
|
||||
case TAG_EXTENSION_ACCURACY_VERTICAL:
|
||||
if (content != null) {
|
||||
accuracyVertical = content.trim();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
content = "";
|
||||
@@ -356,6 +362,13 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_horizontal: %s", sensorDistance)), e);
|
||||
}
|
||||
}
|
||||
if (accuracyVertical != null) {
|
||||
try {
|
||||
trackPoint.setVerticalAccuracy(Distance.of(accuracyVertical));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_vertical: %s", sensorDistance)), e);
|
||||
}
|
||||
}
|
||||
|
||||
return trackPoint;
|
||||
}
|
||||
@@ -372,6 +385,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
|
||||
sensorDistance = null;
|
||||
accuracyHorizontal = null;
|
||||
accuracyVertical = null;
|
||||
power = null;
|
||||
heartrate = null;
|
||||
cadence = null;
|
||||
|
||||
@@ -90,6 +90,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private final ArrayList<Float> altitudeGainList = new ArrayList<>();
|
||||
private final ArrayList<Float> altitudeLossList = new ArrayList<>();
|
||||
private final ArrayList<Float> accuracyHorizontal = new ArrayList<>();
|
||||
private final ArrayList<Float> accuracyVertical = new ArrayList<>();
|
||||
|
||||
private final ArrayList<Marker> markers = new ArrayList<>();
|
||||
|
||||
@@ -296,6 +297,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
altitudeGainList.clear();
|
||||
altitudeLossList.clear();
|
||||
accuracyHorizontal.clear();
|
||||
accuracyVertical.clear();
|
||||
}
|
||||
|
||||
private void onTrackSegmentEnd() {
|
||||
@@ -338,6 +340,9 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
if (i < accuracyHorizontal.size() && accuracyHorizontal.get(i) != null) {
|
||||
trackPoint.setHorizontalAccuracy(Distance.of(accuracyHorizontal.get(i)));
|
||||
}
|
||||
if (i < accuracyVertical.size() && accuracyVertical.get(i) != null) {
|
||||
trackPoint.setVerticalAccuracy(Distance.of(accuracyVertical.get(i)));
|
||||
}
|
||||
|
||||
// Update TrackPoint type for START / STOP.
|
||||
TrackPoint.Type type = trackPoint.getType();
|
||||
@@ -438,6 +443,9 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_HORIZONTAL:
|
||||
accuracyHorizontal.add(value);
|
||||
break;
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_VERTICAL:
|
||||
accuracyVertical.add(value);
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "Data from extended data " + extendedDataType + " is not (yet) supported.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user