diff --git a/doc/opentracks-schema-1.0.xsd b/doc/opentracks-schema-1.0.xsd
index 9b9ed8e36f..89b187fb14 100644
--- a/doc/opentracks-schema-1.0.xsd
+++ b/doc/opentracks-schema-1.0.xsd
@@ -51,4 +51,13 @@
+
+
+
+ User-defined translation of GPX's ]]>.
+ Only used in GPX.
+
+
+
\ No newline at end of file
diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java
index 59464b9afc..7065be17d1 100644
--- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java
+++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java
@@ -309,10 +309,10 @@ public void kmz_with_trackdetail_and_sensordata() throws TimeoutException, IOExc
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
+ assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName());
- assertEquals(track.getActivityType(), importedTrack.getActivityType());
// 2. trackpoints
TrackPointAssert a = new TrackPointAssert();
@@ -380,13 +380,11 @@ public void gpx() throws TimeoutException, IOException {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
+ assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName());
- //TODO exporting and importing a track icon is not yet supported by GpxTrackWriter.
- //assertEquals(track.getIcon(), importedTrack.getIcon());
-
// 2. trackpoints
// The GPX exporter does not support exporting TrackPoints without lat/lng.
// Therefore, the track segmentation is changes.
diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporterTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporterTest.java
index df1624d2f9..6d7fcc15d0 100644
--- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporterTest.java
+++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporterTest.java
@@ -80,6 +80,7 @@ public void gpx_with_pause_resume() throws IOException {
// 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
+ assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("the category", importedTrack.getActivityTypeLocalized());
assertEquals("the description", importedTrack.getDescription());
assertEquals("2021-01-07 22:51", importedTrack.getName());
diff --git a/src/androidTest/res/raw/gpx_timezone.gpx b/src/androidTest/res/raw/gpx_timezone.gpx
index 23d7548435..a9946060f6 100644
--- a/src/androidTest/res/raw/gpx_timezone.gpx
+++ b/src/androidTest/res/raw/gpx_timezone.gpx
@@ -21,10 +21,11 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/
-
+
c0c0c0
7002101e-4198-4613-8c24-544e01ca3981
+
0.0
0
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java
index 7a7362a051..535d144862 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java
@@ -261,7 +261,7 @@ public void writeMarker(ZoneOffset zoneOffset, Marker marker) {
printWriter.println("");
printWriter.println("" + StringUtils.formatCData(marker.getName()) + "");
printWriter.println("" + StringUtils.formatCData(marker.getDescription()) + "");
- printWriter.println("" + StringUtils.formatCData(marker.getCategory()) + "");
+ printWriter.println("" + StringUtils.formatCData(marker.getCategory()) + ""); //TODO This is localized; may be better to export in English only. See #1608
printWriter.println("");
}
@@ -269,12 +269,16 @@ public void writeBeginTrack(Track track) {
printWriter.println("");
printWriter.println("" + StringUtils.formatCData(track.getName()) + "");
printWriter.println("" + StringUtils.formatCData(track.getDescription()) + "");
- printWriter.println("" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "");
+ printWriter.println("" + StringUtils.formatCData(track.getActivityType().getId()) + "");
printWriter.println("");
printWriter.println("c0c0c0");
printWriter.println("" + track.getUuid() + "");
+ if (track.getActivityTypeLocalized() != null || !track.getActivityTypeLocalized().isBlank()) {
+ printWriter.println("" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "");
+ }
+
TrackStatistics trackStatistics = track.getTrackStatistics();
printWriter.println("");
printWriter.println("" + trackStatistics.getTotalDistance().toM() + "");
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java
index b9264ee623..b76dd33052 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java
@@ -37,6 +37,7 @@
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackPointIterator;
+import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -59,7 +60,8 @@ public class KMLTrackExporter implements TrackExporter {
private static final String TRACK_STYLE = "track";
private static final String SCHEMA_ID = "schema";
- public static final String EXTENDED_DATA_TYPE_ACTIVITYTYPE = "type";
+ public static final String EXTENDED_DATA_TYPE_LOCALIZED = "type";
+ public static final String EXTENDED_DATA_ACTIVITY_TYPE = "activityType";
public static final String EXTENDED_DATA_TYPE_TRACKPOINT = "trackpoint_type";
public static final String EXTENDED_DATA_TYPE_SPEED = "speed";
@@ -298,13 +300,13 @@ private void writeBeginTrack(Track track) {
printWriter.println("" + track.getUuid() + "");
printWriter.println("#" + TRACK_STYLE + "");
- writeActivityType(track.getActivityTypeLocalized());
+ writeActivityType(track.getActivityType());
+ writeTypeLocalized(track.getActivityTypeLocalized());
printWriter.println("");
printWriter.println("absolute");
printWriter.println("1");
}
-
private void writeEndTrack() {
printWriter.println("");
printWriter.println("");
@@ -416,7 +418,7 @@ private void writePlacemark(String name, String activityType, String description
printWriter.println("" + StringUtils.formatCData(description) + "");
printWriter.println("" + getTime(zoneOffset, location) + "");
printWriter.println("#" + KMLTrackExporter.MARKER_STYLE + "");
- writeActivityType(activityType);
+ writeTypeLocalized(activityType);
printWriter.println("");
printWriter.println("" + getCoordinates(location, ",") + "");
printWriter.println("");
@@ -437,7 +439,7 @@ private void writePhotoOverlay(Marker marker, float heading, ZoneOffset zoneOffs
printWriter.println("");
printWriter.println("" + getTime(zoneOffset, marker.getLocation()) + "");
printWriter.println("#" + MARKER_STYLE + "");
- writeActivityType(marker.getCategory());
+ writeTypeLocalized(marker.getCategory());
if (exportPhotos) {
printWriter.println("" + KmzTrackExporter.buildKmzImageFilePath(marker) + "");
@@ -492,12 +494,21 @@ private static String getCoordinates(Location location, String separator) {
return result;
}
- private void writeActivityType(String activityTypeLocalized) {
- if (activityTypeLocalized == null || "".equals(activityTypeLocalized)) {
+ private void writeTypeLocalized(String localizedValue) {
+ if (localizedValue == null || localizedValue.equals("")) {
+ return;
+ }
+ printWriter.println("");
+ printWriter.println("" + StringUtils.formatCData(localizedValue) + "");
+ printWriter.println("");
+ }
+
+ private void writeActivityType(ActivityType value) {
+ if (value == null) {
return;
}
printWriter.println("");
- printWriter.println("" + StringUtils.formatCData(activityTypeLocalized) + "");
+ printWriter.println("" + StringUtils.formatCData(value.getId()) + "");
printWriter.println("");
}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxTrackImporter.java
index 7d7cc5cd3b..91b8f6d33a 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxTrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxTrackImporter.java
@@ -55,7 +55,6 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG = GpxTrackImporter.class.getSimpleName();
private static final String TAG_DESCRIPTION = "desc";
- private static final String TAG_COMMENT = "cmt";
private static final String TAG_ALTITUDE = "ele";
private static final String TAG_GPX = "gpx";
private static final String TAG_NAME = "name";
@@ -64,6 +63,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_TRACK_POINT = "trkpt";
private static final String TAG_TRACK_SEGMENT = "trkseg";
private static final String TAG_TYPE = "type";
+ private static final String TAG_TYPE_LOCALIZED = "opentracks:typeTranslated";
private static final String TAG_MARKER = "wpt";
private static final String TAG_ID = "opentracks:trackid";
@@ -99,6 +99,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private String name;
private String description;
private String activityType;
+ private String activityTypeLocalized;
private String latitude;
private String longitude;
private String altitude;
@@ -159,7 +160,11 @@ public void endElement(String uri, String localName, String tag) {
case TAG_GPX -> onFileEnd();
case TAG_MARKER -> onMarkerEnd();
case TAG_TRACK -> {
- trackImporter.setTrack(context, name, uuid, description, activityType, null, zoneOffset);
+ if (activityTypeLocalized == null ) {
+ // Backward compatibility: up v4.9.1 as contained localized content.
+ activityTypeLocalized = activityType;
+ }
+ trackImporter.setTrack(context, name, uuid, description, activityTypeLocalized, activityType, zoneOffset);
zoneOffset = null;
}
case TAG_TRACK_SEGMENT -> onTrackSegmentEnd();
@@ -174,9 +179,16 @@ public void endElement(String uri, String localName, String tag) {
description = content.trim();
}
}
- case TAG_TYPE -> {
+ case TAG_TYPE -> { //Track or Marker/WPT
if (content != null) {
+ // In older version this might be localized content.
activityType = content.trim();
+ markerType = content.trim();
+ }
+ }
+ case TAG_TYPE_LOCALIZED -> {
+ if (content != null) {
+ activityTypeLocalized = content.trim();
}
}
case TAG_TIME -> {
@@ -189,11 +201,6 @@ public void endElement(String uri, String localName, String tag) {
altitude = content.trim();
}
}
- case TAG_COMMENT -> {
- if (content != null) {
- markerType = content.trim();
- }
- }
case TAG_EXTENSION_SPEED, TAG_EXTENSION_SPEED_COMPAT -> {
if (content != null) {
speed = content.trim();
@@ -385,7 +392,6 @@ private void onTrackPointStart(Attributes attributes) {
private void onMarkerStart(Attributes attributes) {
name = null;
description = null;
- activityType = null;
photoUrl = null;
latitude = attributes.getValue(ATTRIBUTE_LAT);
longitude = attributes.getValue(ATTRIBUTE_LON);
@@ -415,8 +421,8 @@ private void onMarkerEnd() {
if (description != null) {
marker.setDescription(description);
}
- if (activityType != null) {
- marker.setCategory(activityType);
+ if (markerType != null) {
+ marker.setCategory(markerType);
}
if (photoUrl != null) {
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlTrackImporter.java
index e6b097f4d4..1d278f1262 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlTrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlTrackImporter.java
@@ -53,7 +53,6 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_COORDINATES = "coordinates";
private static final String TAG_DESCRIPTION = "description";
- private static final String TAG_ICON = "icon";
private static final String TAG_COORD = "coord";
private static final String TAG_KML22_COORD = "gx:coord";
@@ -61,7 +60,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_MULTI_TRACK = "MultiTrack";
private static final String TAG_KML22_MULTI_TRACK = "gx:MultiTrack";
- private static final String TAG_DATA_ACTIVITYTYPE = "Data";
+ private static final String TAG_EXTENDED_DATA = "Data";
private static final String TAG_SIMPLE_ARRAY_DATA = "SimpleArrayData";
private static final String TAG_KML22_SIMPLE_ARRAY_DATA = "gx:SimpleArrayData";
@@ -94,7 +93,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private final ArrayList whenList = new ArrayList<>();
private final ArrayList locationList = new ArrayList<>();
- private String dataType; //Could be converted to an ENUM
+ private String dataType;
private final ArrayList trackpointTypeList = new ArrayList<>();
private final ArrayList sensorSpeedList = new ArrayList<>();
@@ -112,10 +111,10 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
// The current element content
private String content = "";
- private String icon;
private String name;
private String description;
private String activityType;
+ private String activityTypeLocalized;
private String latitude;
private String longitude;
private String altitude;
@@ -148,7 +147,7 @@ public void startElement(String uri, String localName, String tag, Attributes at
}
onTrackSegmentStart();
}
- case TAG_DATA_ACTIVITYTYPE, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA ->
+ case TAG_EXTENDED_DATA, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA ->
dataType = attributes.getValue(ATTRIBUTE_NAME);
}
}
@@ -167,18 +166,24 @@ public void endElement(String uri, String localName, String tag) throws SAXExcep
onMarkerEnd();
case TAG_COORDINATES -> onMarkerLocationEnd();
case TAG_MULTI_TRACK, TAG_KML22_MULTI_TRACK -> {
- trackImporter.setTrack(context, name, uuid, description, activityType, icon, zoneOffset);
+ trackImporter.setTrack(context, name, uuid, description, activityTypeLocalized, activityType, zoneOffset);
zoneOffset = null;
}
case TAG_TRACK, TAG_KML22_TRACK -> onTrackSegmentEnd();
case TAG_COORD, TAG_KML22_COORD -> onCoordEnded();
case TAG_VALUE, TAG_KML22_VALUE -> {
- if (KMLTrackExporter.EXTENDED_DATA_TYPE_ACTIVITYTYPE.equals(dataType)) {
- if (content != null) {
- activityType = content.trim();
+ switch (dataType) {
+ case KMLTrackExporter.EXTENDED_DATA_ACTIVITY_TYPE -> {
+ if (content != null) {
+ activityType = content.trim();
+ }
}
- } else {
- onExtendedDataValueEnd();
+ case KMLTrackExporter.EXTENDED_DATA_TYPE_LOCALIZED -> {
+ if (content != null) {
+ activityTypeLocalized = content.trim();
+ }
+ }
+ default -> onExtendedDataValueEnd();
}
}
case TAG_NAME -> {
@@ -196,11 +201,6 @@ public void endElement(String uri, String localName, String tag) throws SAXExcep
description = content.trim();
}
}
- case TAG_ICON -> {
- if (content != null) {
- icon = content.trim();
- }
- }
case TAG_WHEN -> {
if (content != null) {
try {
@@ -233,9 +233,8 @@ public void endElement(String uri, String localName, String tag) throws SAXExcep
private void onMarkerStart() {
// Reset all Placemark variables
name = null;
- icon = null;
description = null;
- activityType = null;
+ activityTypeLocalized = null;
photoUrl = null;
latitude = null;
longitude = null;
@@ -262,13 +261,13 @@ private void onMarkerEnd() {
Marker marker = new Marker(null, new TrackPoint(TrackPoint.Type.TRACKPOINT, location, whenList.get(0))); //TODO Creating marker without need
marker.setName(name != null ? name : "");
marker.setDescription(description != null ? description : "");
- marker.setCategory(activityType != null ? activityType : "");
+ marker.setCategory(activityTypeLocalized != null ? activityTypeLocalized : "");
marker.setPhotoUrl(photoUrl);
markers.add(marker);
name = null;
description = null;
- activityType = null;
+ activityTypeLocalized = null;
photoUrl = null;
whenList.clear();
}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
index ac6030594c..10145a96e6 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
@@ -105,7 +105,6 @@ void setTrack(Context context, String name, String uuid, String description, Str
if (activityTypeLocalized != null) {
track.setActivityTypeLocalized(activityTypeLocalized);
}
-
ActivityType activityType;
if (activityTypeId == null) {
activityType = ActivityType.findByLocalizedString(context, activityTypeLocalized);