Skip to content

Commit

Permalink
ActivityType non-localized: import and export for GPX, KML, and KMZ.
Browse files Browse the repository at this point in the history
Fixes #1608.
  • Loading branch information
dennisguse committed Oct 8, 2023
1 parent 48ffcc6 commit 0d67b48
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 46 deletions.
9 changes: 9 additions & 0 deletions doc/opentracks-schema-1.0.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="typeTranslated"
type="xsd:string">
<xsd:annotation>
<xsd:documentation xml:lang="en">
User-defined translation of GPX's <![CDATA[<type>]]>.
Only used in GPX.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/androidTest/res/raw/gpx_timezone.gpx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/
<trk>
<name><![CDATA[2021-01-07 22:51]]></name>
<desc><![CDATA[the description]]></desc>
<type><![CDATA[the category]]></type>
<type><![CDATA[unknown]]></type>
<extensions>
<topografix:color>c0c0c0</topografix:color>
<opentracks:trackid>7002101e-4198-4613-8c24-544e01ca3981</opentracks:trackid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,20 +261,24 @@ public void writeMarker(ZoneOffset zoneOffset, Marker marker) {
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(marker.getTime(), zoneOffset) + "</time>");
printWriter.println("<name>" + StringUtils.formatCData(marker.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(marker.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(marker.getCategory()) + "</type>");
printWriter.println("<type>" + StringUtils.formatCData(marker.getCategory()) + "</type>"); //TODO This is localized; may be better to export in English only. See #1608
printWriter.println("</wpt>");
}

public void writeBeginTrack(Track track) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</type>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityType().getId()) + "</type>");

printWriter.println("<extensions>");
printWriter.println("<topografix:color>c0c0c0</topografix:color>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");

if (track.getActivityTypeLocalized() != null || !track.getActivityTypeLocalized().isBlank()) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>");
}

TrackStatistics trackStatistics = track.getTrackStatistics();
printWriter.println("<gpxtrkx:TrackStatsExtension>");
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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";
Expand Down Expand Up @@ -298,13 +300,13 @@ private void writeBeginTrack(Track track) {
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");

printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityTypeLocalized());
writeActivityType(track.getActivityType());
writeTypeLocalized(track.getActivityTypeLocalized());
printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>");
}


private void writeEndTrack() {
printWriter.println("</MultiTrack>");
printWriter.println("</Placemark>");
Expand Down Expand Up @@ -416,7 +418,7 @@ private void writePlacemark(String name, String activityType, String description
printWriter.println("<description>" + StringUtils.formatCData(description) + "</description>");
printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, location) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + KMLTrackExporter.MARKER_STYLE + "</styleUrl>");
writeActivityType(activityType);
writeTypeLocalized(activityType);
printWriter.println("<Point>");
printWriter.println("<coordinates>" + getCoordinates(location, ",") + "</coordinates>");
printWriter.println("</Point>");
Expand All @@ -437,7 +439,7 @@ private void writePhotoOverlay(Marker marker, float heading, ZoneOffset zoneOffs
printWriter.println("</Camera>");
printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, marker.getLocation()) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + MARKER_STYLE + "</styleUrl>");
writeActivityType(marker.getCategory());
writeTypeLocalized(marker.getCategory());

if (exportPhotos) {
printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(marker) + "</href></Icon>");
Expand Down Expand Up @@ -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("<ExtendedData>");
printWriter.println("<Data name=\"" + EXTENDED_DATA_TYPE_LOCALIZED + "\"><value>" + StringUtils.formatCData(localizedValue) + "</value></Data>");
printWriter.println("</ExtendedData>");
}

private void writeActivityType(ActivityType value) {
if (value == null) {
return;
}
printWriter.println("<ExtendedData>");
printWriter.println("<Data name=\"" + EXTENDED_DATA_TYPE_ACTIVITYTYPE + "\"><value>" + StringUtils.formatCData(activityTypeLocalized) + "</value></Data>");
printWriter.println("<Data name=\"" + EXTENDED_DATA_ACTIVITY_TYPE + "\"><value>" + StringUtils.formatCData(value.getId()) + "</value></Data>");
printWriter.println("</ExtendedData>");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -159,7 +160,7 @@ 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);
trackImporter.setTrack(context, name, uuid, description, activityTypeLocalized, activityType, zoneOffset);
zoneOffset = null;
}
case TAG_TRACK_SEGMENT -> onTrackSegmentEnd();
Expand All @@ -174,9 +175,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 -> {
Expand All @@ -189,11 +197,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();
Expand Down Expand Up @@ -385,7 +388,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);
Expand Down Expand Up @@ -415,8 +417,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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,14 @@ 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";

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";
Expand Down Expand Up @@ -94,7 +93,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private final ArrayList<Instant> whenList = new ArrayList<>();
private final ArrayList<Location> locationList = new ArrayList<>();

private String dataType; //Could be converted to an ENUM
private String dataType;

private final ArrayList<String> trackpointTypeList = new ArrayList<>();
private final ArrayList<Float> sensorSpeedList = new ArrayList<>();
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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 -> {
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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();
}
Expand Down

0 comments on commit 0d67b48

Please sign in to comment.