Exporter: rather crash than hide lifecycle errors.

Part of #1187.
This commit is contained in:
Dennis Guse
2023-08-01 19:09:45 +02:00
parent f35eef4c57
commit 87bc7be530
3 changed files with 227 additions and 273 deletions
@@ -153,24 +153,18 @@ public class CSVTrackExporter implements TrackExporter {
} }
public void close() { public void close() {
if (printWriter != null) { printWriter.flush();
printWriter.flush(); printWriter = null;
printWriter = null;
}
} }
public void writeHeader(List<Column> columns) { public void writeHeader(List<Column> columns) {
if (printWriter != null) { String columnNames = columns.stream().map(c -> c.columnName).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined"));
String columnNames = columns.stream().map(c -> c.columnName).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined")); printWriter.println("#" + columnNames);
printWriter.println("#" + columnNames);
}
} }
public void writeTrackPoint(List<Column> columns, TrackPoint trackPoint) { public void writeTrackPoint(List<Column> columns, TrackPoint trackPoint) {
if (printWriter != null) { String columnNames = columns.stream().map(c -> c.extractor.apply(trackPoint)).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined"));
String columnNames = columns.stream().map(c -> c.extractor.apply(trackPoint)).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined")); printWriter.println(columnNames);
printWriter.println(columnNames);
}
} }
private static class Column { private static class Column {
@@ -199,42 +199,36 @@ public class GPXTrackExporter implements TrackExporter {
} }
public void close() { public void close() {
if (printWriter != null) { printWriter.flush();
printWriter.flush(); printWriter = null;
printWriter = null;
}
} }
public void writeHeader() { public void writeHeader() {
if (printWriter != null) { printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); printWriter.println("<gpx");
printWriter.println("<gpx"); printWriter.println("version=\"1.1\"");
printWriter.println("version=\"1.1\""); printWriter.println("creator=\"" + creator + "\"");
printWriter.println("creator=\"" + creator + "\""); printWriter.println("xmlns=\"http://www.topografix.com/GPX/1/1\"");
printWriter.println("xmlns=\"http://www.topografix.com/GPX/1/1\""); printWriter.println("xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\"");
printWriter.println("xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\""); printWriter.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
printWriter.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); printWriter.println("xmlns:opentracks=\"http://opentracksapp.com/xmlschemas/v1\"");
printWriter.println("xmlns:opentracks=\"http://opentracksapp.com/xmlschemas/v1\""); printWriter.println("xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v2\"");
printWriter.println("xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v2\""); printWriter.println("xmlns:gpxtrkx=\"http://www.garmin.com/xmlschemas/TrackStatsExtension/v1\"");
printWriter.println("xmlns:gpxtrkx=\"http://www.garmin.com/xmlschemas/TrackStatsExtension/v1\""); printWriter.println("xmlns:cluetrust=\"http://www.cluetrust.com/Schemas/\"");
printWriter.println("xmlns:cluetrust=\"http://www.cluetrust.com/Schemas/\""); printWriter.println("xmlns:pwr=\"http://www.garmin.com/xmlschemas/PowerExtension/v1\"");
printWriter.println("xmlns:pwr=\"http://www.garmin.com/xmlschemas/PowerExtension/v1\""); printWriter.println("xsi:schemaLocation=" +
printWriter.println("xsi:schemaLocation=" + "\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
"\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" + " http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd" + " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd"
+ " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd" + " http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd"
+ " http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd" + " http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
+ " http://www.garmin.com/xmlschemas/TrackStatsExtension/v1" + " http://www.cluetrust.com/Schemas http://www.cluetrust.com/Schemas/gpxdata10.xsd"
+ " http://www.cluetrust.com/Schemas http://www.cluetrust.com/Schemas/gpxdata10.xsd" + " http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd\">");
+ " http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd\">");
}
} }
public void writeFooter() { public void writeFooter() {
if (printWriter != null) { printWriter.println("</gpx>");
printWriter.println("</gpx>");
}
} }
private void writeMarkers(Track track) throws InterruptedException { private void writeMarkers(Track track) throws InterruptedException {
@@ -254,49 +248,43 @@ public class GPXTrackExporter implements TrackExporter {
} }
public void writeMarker(ZoneOffset zoneOffset, Marker marker) { public void writeMarker(ZoneOffset zoneOffset, Marker marker) {
if (printWriter != null) { printWriter.println("<wpt " + formatLocation(marker.getLatitude(), marker.getLongitude()) + ">");
printWriter.println("<wpt " + formatLocation(marker.getLatitude(), marker.getLongitude()) + ">"); if (marker.hasAltitude()) {
if (marker.hasAltitude()) { printWriter.println("<ele>" + ALTITUDE_FORMAT.format(marker.getAltitude().toM()) + "</ele>");
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(marker.getAltitude().toM()) + "</ele>");
}
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("</wpt>");
} }
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("</wpt>");
} }
public void writeBeginTrack(Track track) { public void writeBeginTrack(Track track) {
if (printWriter != null) { printWriter.println("<trk>");
printWriter.println("<trk>"); printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>"); printWriter.println("<type>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</type>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</type>");
printWriter.println("<extensions>"); printWriter.println("<extensions>");
printWriter.println("<topografix:color>c0c0c0</topografix:color>"); printWriter.println("<topografix:color>c0c0c0</topografix:color>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
TrackStatistics trackStatistics = track.getTrackStatistics(); TrackStatistics trackStatistics = track.getTrackStatistics();
printWriter.println("<gpxtrkx:TrackStatsExtension>"); printWriter.println("<gpxtrkx:TrackStatsExtension>");
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>"); printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>");
printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.getTotalTime().getSeconds() + "</gpxtrkx:TimerTime>"); printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.getTotalTime().getSeconds() + "</gpxtrkx:TimerTime>");
printWriter.println("<gpxtrkx:MovingTime>" + trackStatistics.getMovingTime().getSeconds() + "</gpxtrkx:MovingTime>"); printWriter.println("<gpxtrkx:MovingTime>" + trackStatistics.getMovingTime().getSeconds() + "</gpxtrkx:MovingTime>");
printWriter.println("<gpxtrkx:StoppedTime>" + trackStatistics.getStoppedTime().getSeconds() + "</gpxtrkx:StoppedTime>"); printWriter.println("<gpxtrkx:StoppedTime>" + trackStatistics.getStoppedTime().getSeconds() + "</gpxtrkx:StoppedTime>");
printWriter.println("<gpxtrkx:MaxSpeed>" + trackStatistics.getMaxSpeed().toMPS() + "</gpxtrkx:MaxSpeed>"); printWriter.println("<gpxtrkx:MaxSpeed>" + trackStatistics.getMaxSpeed().toMPS() + "</gpxtrkx:MaxSpeed>");
printWriter.println("<gpxtrkx:Ascent>" + trackStatistics.getTotalAltitudeGain() + "</gpxtrkx:Ascent>"); printWriter.println("<gpxtrkx:Ascent>" + trackStatistics.getTotalAltitudeGain() + "</gpxtrkx:Ascent>");
printWriter.println("<gpxtrkx:Descent>" + trackStatistics.getTotalAltitudeLoss() + "</gpxtrkx:Descent>"); printWriter.println("<gpxtrkx:Descent>" + trackStatistics.getTotalAltitudeLoss() + "</gpxtrkx:Descent>");
printWriter.println("</gpxtrkx:TrackStatsExtension>"); printWriter.println("</gpxtrkx:TrackStatsExtension>");
printWriter.println("</extensions>"); printWriter.println("</extensions>");
}
} }
public void writeEndTrack() { public void writeEndTrack() {
if (printWriter != null) { printWriter.println("</trk>");
printWriter.println("</trk>");
}
} }
public void writeOpenSegment() { public void writeOpenSegment() {
@@ -310,67 +298,65 @@ public class GPXTrackExporter implements TrackExporter {
public Distance writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint, List<TrackPoint> sensorPoints, Distance trackDistance) { public Distance writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint, List<TrackPoint> sensorPoints, Distance trackDistance) {
Distance cumulativeDistance = null; Distance cumulativeDistance = null;
if (printWriter != null) { printWriter.println("<trkpt " + formatLocation(trackPoint.getLatitude(), trackPoint.getLongitude()) + ">");
printWriter.println("<trkpt " + formatLocation(trackPoint.getLatitude(), trackPoint.getLongitude()) + ">"); if (trackPoint.hasAltitude()) {
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(trackPoint.getAltitude().toM()) + "</ele>");
if (trackPoint.hasAltitude()) {
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(trackPoint.getAltitude().toM()) + "</ele>");
}
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(trackPoint.getTime(), zoneOffset) + "</time>");
{
String trackPointExtensionContent = "";
if (trackPoint.hasSpeed()) {
trackPointExtensionContent += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.getSpeed().toMPS()) + "</gpxtpx:speed>\n";
}
if (trackPoint.hasHeartRate()) {
trackPointExtensionContent += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.getHeartRate().getBPM()) + "</gpxtpx:hr>\n";
}
if (trackPoint.hasCadence()) {
trackPointExtensionContent += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.getCadence().getRPM()) + "</gpxtpx:cad>\n";
}
if (trackPoint.hasPower()) {
trackPointExtensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
}
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGain() ? (double) tp.getAltitudeGain() : null);
if (cumulativeGain != null) {
trackPointExtensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
}
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeLoss() ? (double) tp.getAltitudeLoss() : null);
if (cumulativeLoss != null) {
trackPointExtensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
}
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) {
trackPointExtensionContent += ("<opentracks:distance>" + DISTANCE_FORMAT.format(cumulativeDistance.toM()) + "</opentracks:distance>\n");
trackPointExtensionContent += ("<cluetrust:distance>" + DISTANCE_FORMAT.format(trackDistance.plus(cumulativeDistance).toM()) + "</cluetrust:distance>\n");
}
if (!trackPointExtensionContent.isEmpty()) {
printWriter.println("<extensions><gpxtpx:TrackPointExtension>");
printWriter.print(trackPointExtensionContent);
printWriter.println("</gpxtpx:TrackPointExtension></extensions>");
}
}
printWriter.println("</trkpt>");
} }
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(trackPoint.getTime(), zoneOffset) + "</time>");
{
String trackPointExtensionContent = "";
if (trackPoint.hasSpeed()) {
trackPointExtensionContent += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.getSpeed().toMPS()) + "</gpxtpx:speed>\n";
}
if (trackPoint.hasHeartRate()) {
trackPointExtensionContent += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.getHeartRate().getBPM()) + "</gpxtpx:hr>\n";
}
if (trackPoint.hasCadence()) {
trackPointExtensionContent += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.getCadence().getRPM()) + "</gpxtpx:cad>\n";
}
if (trackPoint.hasPower()) {
trackPointExtensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
}
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGain() ? (double) tp.getAltitudeGain() : null);
if (cumulativeGain != null) {
trackPointExtensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
}
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeLoss() ? (double) tp.getAltitudeLoss() : null);
if (cumulativeLoss != null) {
trackPointExtensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
}
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) {
trackPointExtensionContent += ("<opentracks:distance>" + DISTANCE_FORMAT.format(cumulativeDistance.toM()) + "</opentracks:distance>\n");
trackPointExtensionContent += ("<cluetrust:distance>" + DISTANCE_FORMAT.format(trackDistance.plus(cumulativeDistance).toM()) + "</cluetrust:distance>\n");
}
if (!trackPointExtensionContent.isEmpty()) {
printWriter.println("<extensions><gpxtpx:TrackPointExtension>");
printWriter.print(trackPointExtensionContent);
printWriter.println("</gpxtpx:TrackPointExtension></extensions>");
}
}
printWriter.println("</trkpt>");
if (cumulativeDistance != null) { if (cumulativeDistance != null) {
return cumulativeDistance; return cumulativeDistance;
} }
@@ -212,196 +212,170 @@ public class KMLTrackExporter implements TrackExporter {
@VisibleForTesting @VisibleForTesting
void close() { void close() {
if (printWriter != null) { printWriter.flush();
printWriter.flush(); printWriter = null;
printWriter = null;
}
} }
private void writeHeader(List<Track> tracks) { private void writeHeader(List<Track> tracks) {
if (printWriter != null) { printWriter.println(
printWriter.println( """
""" <?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?> """);
"""); printWriter.println(
printWriter.println( """
""" <kml xmlns="http://www.opengis.net/kml/2.3"
<kml xmlns="http://www.opengis.net/kml/2.3" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:atom="http://www.w3.org/2005/Atom" xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1"
xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/kml/2.3 http://schemas.opengis.net/kml/2.3/ogckml23.xsd
xsi:schemaLocation="http://www.opengis.net/kml/2.3 http://schemas.opengis.net/kml/2.3/ogckml23.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd"> """); //TODO ADD xsi:schemaLocation for atom
"""); //TODO ADD xsi:schemaLocation for atom printWriter.println("<Document>");
printWriter.println("<Document>"); printWriter.println("<open>1</open>");
printWriter.println("<open>1</open>"); printWriter.println("<visibility>1</visibility>");
printWriter.println("<visibility>1</visibility>");
Track track = tracks.get(0); Track track = tracks.get(0);
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<atom:generator>" + StringUtils.formatCData(context.getString(R.string.app_name)) + "</atom:generator>"); printWriter.println("<atom:generator>" + StringUtils.formatCData(context.getString(R.string.app_name)) + "</atom:generator>");
writeTrackStyle(); writeTrackStyle();
writePlacemarkerStyle(); writePlacemarkerStyle();
printWriter.println("<Schema id=\"" + SCHEMA_ID + "\">"); printWriter.println("<Schema id=\"" + SCHEMA_ID + "\">");
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_SPEED, context.getString(R.string.description_speed_ms)); writeSimpleArrayStyle(EXTENDED_DATA_TYPE_SPEED, context.getString(R.string.description_speed_ms));
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_POWER, context.getString(R.string.description_sensor_power)); writeSimpleArrayStyle(EXTENDED_DATA_TYPE_POWER, context.getString(R.string.description_sensor_power));
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_CADENCE, context.getString(R.string.description_sensor_cadence)); writeSimpleArrayStyle(EXTENDED_DATA_TYPE_CADENCE, context.getString(R.string.description_sensor_cadence));
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_HEART_RATE, context.getString(R.string.description_sensor_heart_rate)); writeSimpleArrayStyle(EXTENDED_DATA_TYPE_HEART_RATE, context.getString(R.string.description_sensor_heart_rate));
printWriter.println("</Schema>"); printWriter.println("</Schema>");
}
} }
private void writeFooter() { private void writeFooter() {
if (printWriter != null) { printWriter.println("</Document>");
printWriter.println("</Document>"); printWriter.println("</kml>");
printWriter.println("</kml>");
}
} }
private void writeBeginMarkers(Track track) { private void writeBeginMarkers(Track track) {
if (printWriter != null) { printWriter.println("<Folder>");
printWriter.println("<Folder>"); printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.getName())) + "</name>");
printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.getName())) + "</name>"); printWriter.println("<open>1</open>");
printWriter.println("<open>1</open>");
}
} }
private void writeMarker(Marker marker, ZoneOffset zoneOffset) { private void writeMarker(Marker marker, ZoneOffset zoneOffset) {
if (printWriter != null) { boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null;
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null; if (marker.hasPhoto() && exportPhotos && existsPhoto) {
if (marker.hasPhoto() && exportPhotos && existsPhoto) { float heading = getHeading(marker.getTrackId(), marker.getLocation());
float heading = getHeading(marker.getTrackId(), marker.getLocation()); writePhotoOverlay(marker, heading, zoneOffset);
writePhotoOverlay(marker, heading, zoneOffset); } else {
} else { writePlacemark(marker.getName(), marker.getCategory(), marker.getDescription(), marker.getLocation(), zoneOffset);
writePlacemark(marker.getName(), marker.getCategory(), marker.getDescription(), marker.getLocation(), zoneOffset);
}
} }
} }
private void writeEndMarkers() { private void writeEndMarkers() {
if (printWriter != null) { printWriter.println("</Folder>");
printWriter.println("</Folder>");
}
} }
private void writeMultiTrackBegin() { private void writeMultiTrackBegin() {
if (printWriter != null) { printWriter.println("<Folder id=\"tracks\">");
printWriter.println("<Folder id=\"tracks\">"); printWriter.println("<name>" + context.getString(R.string.generic_tracks) + "</name>");
printWriter.println("<name>" + context.getString(R.string.generic_tracks) + "</name>"); printWriter.println("<open>1</open>");
printWriter.println("<open>1</open>");
}
} }
private void writeMultiTrackEnd() { private void writeMultiTrackEnd() {
if (printWriter != null) { printWriter.println("</Folder>");
printWriter.println("</Folder>");
}
} }
private void writeBeginTrack(Track track) { private void writeBeginTrack(Track track) {
if (printWriter != null) { printWriter.println("<Placemark>");
printWriter.println("<Placemark>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>"); printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
printWriter.println("<icon>" + StringUtils.formatCData(track.getActivityType().getIconId()) + "</icon>"); printWriter.println("<icon>" + StringUtils.formatCData(track.getActivityType().getIconId()) + "</icon>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityTypeLocalized()); writeActivityType(track.getActivityTypeLocalized());
printWriter.println("<MultiTrack>"); printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>"); printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>"); printWriter.println("<interpolate>1</interpolate>");
}
} }
private void writeEndTrack() { private void writeEndTrack() {
if (printWriter != null) { printWriter.println("</MultiTrack>");
printWriter.println("</MultiTrack>"); printWriter.println("</Placemark>");
printWriter.println("</Placemark>");
}
} }
@VisibleForTesting @VisibleForTesting
void writeOpenSegment() { void writeOpenSegment() {
if (printWriter != null) { printWriter.println("<Track>");
printWriter.println("<Track>"); speedList.clear();
speedList.clear(); distanceList.clear();
distanceList.clear(); powerList.clear();
powerList.clear(); cadenceList.clear();
cadenceList.clear(); heartRateList.clear();
heartRateList.clear(); altitudeGainList.clear();
altitudeGainList.clear(); altitudeLossList.clear();
altitudeLossList.clear(); accuracyHorizontal.clear();
accuracyHorizontal.clear(); accuracyVertical.clear();
accuracyVertical.clear();
}
} }
@VisibleForTesting @VisibleForTesting
void writeCloseSegment() { void writeCloseSegment() {
if (printWriter != null) { printWriter.println("<ExtendedData>");
printWriter.println("<ExtendedData>"); printWriter.println("<SchemaData schemaUrl=\"#" + SCHEMA_ID + "\">");
printWriter.println("<SchemaData schemaUrl=\"#" + SCHEMA_ID + "\">"); if (speedList.stream().anyMatch(Objects::nonNull)) {
if (speedList.stream().anyMatch(Objects::nonNull)) { writeSimpleArrayData(speedList, EXTENDED_DATA_TYPE_SPEED);
writeSimpleArrayData(speedList, EXTENDED_DATA_TYPE_SPEED);
}
if (distanceList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(distanceList, EXTENDED_DATA_TYPE_DISTANCE);
}
if (powerList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(powerList, EXTENDED_DATA_TYPE_POWER);
}
if (cadenceList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(cadenceList, EXTENDED_DATA_TYPE_CADENCE);
}
if (heartRateList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(heartRateList, EXTENDED_DATA_TYPE_HEART_RATE);
}
if (altitudeGainList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(altitudeGainList, EXTENDED_DATA_TYPE_ALTITUDE_GAIN);
}
if (altitudeLossList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(altitudeLossList, EXTENDED_DATA_TYPE_ALTITUDE_LOSS);
}
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("</Track>");
} }
if (distanceList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(distanceList, EXTENDED_DATA_TYPE_DISTANCE);
}
if (powerList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(powerList, EXTENDED_DATA_TYPE_POWER);
}
if (cadenceList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(cadenceList, EXTENDED_DATA_TYPE_CADENCE);
}
if (heartRateList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(heartRateList, EXTENDED_DATA_TYPE_HEART_RATE);
}
if (altitudeGainList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(altitudeGainList, EXTENDED_DATA_TYPE_ALTITUDE_GAIN);
}
if (altitudeLossList.stream().anyMatch(Objects::nonNull)) {
writeSimpleArrayData(altitudeLossList, EXTENDED_DATA_TYPE_ALTITUDE_LOSS);
}
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("</Track>");
} }
@VisibleForTesting @VisibleForTesting
void writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint) { void writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint) {
if (printWriter != null) { printWriter.println("<when>" + getTime(zoneOffset, trackPoint.getLocation()) + "</when>");
printWriter.println("<when>" + getTime(zoneOffset, trackPoint.getLocation()) + "</when>");
if (trackPoint.hasLocation()) { if (trackPoint.hasLocation()) {
printWriter.println("<coord>" + getCoordinates(trackPoint.getLocation(), " ") + "</coord>"); printWriter.println("<coord>" + getCoordinates(trackPoint.getLocation(), " ") + "</coord>");
} else { } else {
printWriter.println("<coord/>"); printWriter.println("<coord/>");
}
speedList.add(trackPoint.hasSpeed() ? (float) trackPoint.getSpeed().toMPS() : null);
distanceList.add(trackPoint.hasSensorDistance() ? (float) trackPoint.getSensorDistance().toM() : null);
heartRateList.add(trackPoint.hasHeartRate() ? trackPoint.getHeartRate().getBPM() : null);
cadenceList.add(trackPoint.hasCadence() ? trackPoint.getCadence().getRPM() : null);
powerList.add(trackPoint.hasPower() ? trackPoint.getPower().getW() : null);
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);
} }
speedList.add(trackPoint.hasSpeed() ? (float) trackPoint.getSpeed().toMPS() : null);
distanceList.add(trackPoint.hasSensorDistance() ? (float) trackPoint.getSensorDistance().toM() : null);
heartRateList.add(trackPoint.hasHeartRate() ? trackPoint.getHeartRate().getBPM() : null);
cadenceList.add(trackPoint.hasCadence() ? trackPoint.getCadence().getRPM() : null);
powerList.add(trackPoint.hasPower() ? trackPoint.getPower().getW() : null);
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);
} }
/** /**