diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyImportTest.java new file mode 100644 index 000000000..a52bbe0ea --- /dev/null +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyImportTest.java @@ -0,0 +1,142 @@ +package de.dennisguse.opentracks.io.file.importer; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.io.InputStream; +import java.util.List; + +import de.dennisguse.opentracks.content.data.Track; +import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.util.StringUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * Test that legacy KML/GPX formats can still be imported. + */ +@RunWith(JUnit4.class) +public class LegacyImportTest { + + private final Context context = ApplicationProvider.getApplicationContext(); + private final ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); + + private Track.Id importTrackId; + + @After + public void tearDown() { + if (importTrackId != null) { + contentProviderUtils.deleteTrack(context, importTrackId); + } + } + + /** + * Check that data with statistics markers is imported and those ignored. + * Statistics marker were created to avoid recomputing the track statistics (e.g., distance until a certain time). + */ + @LargeTest + @Test + public void kml_with_statistics_marker() { + // given + KmlFileTrackImporter trackImporter = new KmlFileTrackImporter(context); + InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_kml_statistics_marker); + + // when + // 1. import + importTrackId = trackImporter.importFile(inputStream); + + // then + // 1. track + Track importedTrack = contentProviderUtils.getTrack(importTrackId); + assertNotNull(importedTrack); + assertEquals("unknown", importedTrack.getCategory()); + assertEquals("Test Track", importedTrack.getDescription()); + assertEquals("2020-11-28 18:06", importedTrack.getName()); + assertEquals("UNKNOWN", importedTrack.getIcon()); + + // 2. markers + assertEquals(0, contentProviderUtils.getMarkerCount(importTrackId)); + + // 3. trackpoints + List importedTrackPoints = contentProviderUtils.getTrackPoints(importTrackId); + assertEquals(6, importedTrackPoints.size()); + + // first 3 trackpoints + assertTrackpoint(importedTrackPoints.get(0), TrackPoint.Type.SEGMENT_START_AUTOMATIC, "2020-11-28T17:06:22.401Z", 1.234156, 12.340097, 469.286376953125); + assertTrackpoint(importedTrackPoints.get(1), TrackPoint.Type.TRACKPOINT, "2020-11-28T17:06:25.448Z", 1.23415, 12.340036, 439.1626281738281); + assertTrackpoint(importedTrackPoints.get(2), TrackPoint.Type.TRACKPOINT, "2020-11-28T17:06:47.888Z", 1.23405, 12.340057, 421.8070983886719); + + // created resume trackpoint with time of next valid trackpoint + assertTrackpoint(importedTrackPoints.get(3), TrackPoint.Type.SEGMENT_START_AUTOMATIC, "2020-11-28T17:06:55.861Z", 1.23405, 12.340057, 419.93902587890625); + assertTrackpoint(importedTrackPoints.get(4), TrackPoint.Type.TRACKPOINT, "2020-11-28T17:06:56.905Z", 1.23405, 12.340057, 419.9036560058594); + assertTrackpoint(importedTrackPoints.get(5), TrackPoint.Type.TRACKPOINT, "2020-11-28T17:07:20.870Z", 1.234046, 12.340082, 417.99432373046875); + } + + /** + * Check that data that contains pause (lat=100, lng=0) and resume (lat=200, lng=0) locations are restored to a segment break. + */ + @LargeTest + @Test + public void gpx_with_pause_resume() { + // given + GpxFileTrackImporter trackImporter = new GpxFileTrackImporter(context); + InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_gpx_pause_resume); + + // when + // 1. import + importTrackId = trackImporter.importFile(inputStream); + + // then + // 1. track + Track importedTrack = contentProviderUtils.getTrack(importTrackId); + assertNotNull(importedTrack); + assertEquals("the category", importedTrack.getCategory()); + assertEquals("the description", importedTrack.getDescription()); + assertEquals("2021-01-07 22:51", importedTrack.getName()); + assertEquals("UNKNOWN", importedTrack.getIcon()); + + // 3. trackpoints + List importedTrackPoints = contentProviderUtils.getTrackPoints(importTrackId); + assertEquals(6, importedTrackPoints.size()); + + // first segment + assertTrackpoint(importedTrackPoints.get(0), TrackPoint.Type.SEGMENT_START_AUTOMATIC, "2021-01-07T21:51:59.179Z", 14.0, 3.0, 10.0); + assertTrackpoint(importedTrackPoints.get(1), TrackPoint.Type.TRACKPOINT, "2021-01-07T21:52:00.653Z", 14.001, 3.0, 10.0); + assertTrackpoint(importedTrackPoints.get(2), TrackPoint.Type.TRACKPOINT, "2021-01-07T21:52:01.010Z", 14.002, 3.0, 10.0); + assertTrackpoint(importedTrackPoints.get(3), TrackPoint.Type.SEGMENT_END_MANUAL, "2021-01-07T21:52:02.658Z", null, null, null); + + // created resume trackpoint with time of next valid trackpoint + assertTrackpoint(importedTrackPoints.get(4), TrackPoint.Type.SEGMENT_START_MANUAL, "2021-01-07T21:52:03.873Z", null, null, null); + assertTrackpoint(importedTrackPoints.get(5), TrackPoint.Type.TRACKPOINT, "2021-01-07T21:52:04.103Z", 14.003, 3.0, 10.0); + } + + private void assertTrackpoint(final TrackPoint trackPoint, final TrackPoint.Type type, final String when, final Double longitude, final Double latitude, final Double altitude) { + assertEquals(StringUtils.parseTime(when), trackPoint.getTime()); + assertEquals(type, trackPoint.getType()); + + if (longitude == null) { + assertFalse(trackPoint.hasLocation()); + } else { + assertEquals(latitude, (Double) trackPoint.getLatitude()); + assertEquals(longitude, (Double) trackPoint.getLongitude()); + } + + if (altitude == null) { + assertFalse(trackPoint.hasAltitude()); + } else { + assertEquals(altitude, (Double) trackPoint.getAltitude()); + } + + } +} \ No newline at end of file diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyKmlImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyKmlImportTest.java deleted file mode 100644 index 765d08cd8..000000000 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/LegacyKmlImportTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package de.dennisguse.opentracks.io.file.importer; - -import android.content.Context; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.io.InputStream; -import java.util.List; - -import de.dennisguse.opentracks.content.data.Track; -import de.dennisguse.opentracks.content.data.TrackPoint; -import de.dennisguse.opentracks.content.provider.ContentProviderUtils; -import de.dennisguse.opentracks.util.StringUtils; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Imports a legacy kml file with a statistics marker at the beginning - */ -@RunWith(JUnit4.class) -public class LegacyKmlImportTest { - - private final Context context = ApplicationProvider.getApplicationContext(); - private final ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); - - private Track.Id importTrackId; - - @After - public void tearDown() { - if (importTrackId != null) { - contentProviderUtils.deleteTrack(context, importTrackId); - } - } - - @LargeTest - @Test - public void kml_legacy_track_import() { - // given - KmlFileTrackImporter trackImporter = new KmlFileTrackImporter(context); - InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_track); - - // when - // 1. import - importTrackId = trackImporter.importFile(inputStream); - - // then - // 1. track - Track importedTrack = contentProviderUtils.getTrack(importTrackId); - assertNotNull(importedTrack); - assertEquals("unknown", importedTrack.getCategory()); - assertEquals("Test Track", importedTrack.getDescription()); - assertEquals("2020-11-28 18:06", importedTrack.getName()); - assertEquals("UNKNOWN", importedTrack.getIcon()); - - // 2. markers - assertEquals(0, contentProviderUtils.getMarkerCount(importTrackId)); - - // 3. trackpoints - List importedTrackPoints = contentProviderUtils.getTrackPoints(importTrackId); - assertEquals(6, importedTrackPoints.size()); - - // first 3 trackpoints - assertEquals(TrackPoint.Type.SEGMENT_START_AUTOMATIC, importedTrackPoints.get(0).getType()); - assertTrackpoint(importedTrackPoints.get(0), "2020-11-28T17:06:22.401Z", 1.234156, 12.340097, 469.286376953125); - assertTrackpoint(importedTrackPoints.get(1), "2020-11-28T17:06:25.448Z", 1.23415, 12.340036, 439.1626281738281); - assertTrackpoint(importedTrackPoints.get(2), "2020-11-28T17:06:47.888Z", 1.23405, 12.340057, 421.8070983886719); - - // created resume trackpoint with time of next valid trackpoint - assertEquals(TrackPoint.Type.SEGMENT_START_AUTOMATIC, importedTrackPoints.get(3).getType()); - assertTrackpoint(importedTrackPoints.get(3), "2020-11-28T17:06:55.861Z", 1.23405, 12.340057, 419.93902587890625); - assertTrackpoint(importedTrackPoints.get(4), "2020-11-28T17:06:56.905Z", 1.23405, 12.340057, 419.9036560058594); - assertTrackpoint(importedTrackPoints.get(5), "2020-11-28T17:07:20.870Z", 1.234046, 12.340082, 417.99432373046875); - } - - private void assertTrackpoint(final TrackPoint trackPoint, final String when, final double longitude, final double latitude, final double altitude) { - assertEquals(StringUtils.parseTime(when), trackPoint.getTime()); - assertEquals(latitude, trackPoint.getLatitude(), 0.001d); - assertEquals(longitude, trackPoint.getLongitude(), 0.001d); - assertEquals(altitude, trackPoint.getAltitude(), 0.001d); - } - -} \ No newline at end of file diff --git a/src/androidTest/res/.readme b/src/androidTest/res/.readme deleted file mode 100644 index 5700541c0..000000000 --- a/src/androidTest/res/.readme +++ /dev/null @@ -1 +0,0 @@ -This hidden file is here to ensure there is a res folder. diff --git a/src/androidTest/res/raw/legacy_gpx_pause_resume.gpx b/src/androidTest/res/raw/legacy_gpx_pause_resume.gpx new file mode 100644 index 000000000..2f3f1a54a --- /dev/null +++ b/src/androidTest/res/raw/legacy_gpx_pause_resume.gpx @@ -0,0 +1,55 @@ + + + + + + + + 10 + + + + + + + 10 + + + + + + + + + + + c0c0c0 + 7002101e-4198-4613-8c24-544e01ca3981 + + + + 10 + + + + 10 + + + + 10 + + + + + + + + + + + 10 + + + + + \ No newline at end of file diff --git a/src/androidTest/res/raw/legacy_kml_statistics_marker.kml b/src/androidTest/res/raw/legacy_kml_statistics_marker.kml new file mode 100644 index 000000000..bd95dbd7e --- /dev/null +++ b/src/androidTest/res/raw/legacy_kml_statistics_marker.kml @@ -0,0 +1,193 @@ + + + + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 1970-01-01T00:00:00Z + + #waypoint + + 180.0,100.0 + + + + + + + + 2020-11-28T17:06:22.401Z + + #start + + 1.234156,12.340097,469.286376953125 + + + + + + + 2f170875-55d7-445d-b2b8-22a573c81dbc + #track + + + + + + + absolute + 1 + + 2020-11-28T17:06:22.401Z + 1.234156 12.340097 469.286376953125 + 2020-11-28T17:06:25.448Z + 1.23415 12.340036 439.1626281738281 + 2020-11-28T17:06:47.888Z + 1.23405 12.340057 421.8070983886719 + + + + 0.5391469 + 0.15777911 + 0.0 + + + 0.0 + 0.0 + 0.0 + + + + + + 2020-11-28T17:06:55.861Z + 1.23405 12.340057 419.93902587890625 + 2020-11-28T17:06:56.905Z + 1.23405 12.340057 419.9036560058594 + 2020-11-28T17:07:20.870Z + 1.234046 12.340082 417.99432373046875 + + + + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + + + + + + 2020-11-28T17:07:20.870Z + + #end + + 1.234046,12.340082,417.99432373046875 + + + + \ No newline at end of file diff --git a/src/androidTest/res/raw/legacy_track.kml b/src/androidTest/res/raw/legacy_track.kml deleted file mode 100644 index 445cc8eb7..000000000 --- a/src/androidTest/res/raw/legacy_track.kml +++ /dev/null @@ -1,173 +0,0 @@ - - - -1 -1 - - - - - - - - - - - - - - - - - - - - - - -1 - - - -1970-01-01T00:00:00Z -#waypoint - -180.0,100.0 - - - - - - -2020-11-28T17:06:22.401Z -#start - -1.234156,12.340097,469.286376953125 - - - - - - -2f170875-55d7-445d-b2b8-22a573c81dbc -#track - - - - -absolute -1 - -2020-11-28T17:06:22.401Z -1.234156 12.340097 469.286376953125 -2020-11-28T17:06:25.448Z -1.23415 12.340036 439.1626281738281 -2020-11-28T17:06:47.888Z -1.23405 12.340057 421.8070983886719 - - - -0.5391469 -0.15777911 -0.0 - - -0.0 -0.0 -0.0 - - - - - -2020-11-28T17:06:55.861Z -1.23405 12.340057 419.93902587890625 -2020-11-28T17:06:56.905Z -1.23405 12.340057 419.9036560058594 -2020-11-28T17:07:20.870Z -1.234046 12.340082 417.99432373046875 - - - -0.0 -0.0 -0.0 - - -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 - - - - - - - - - -2020-11-28T17:07:20.870Z -#end - -1.234046,12.340082,417.99432373046875 - - - - diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java index 5086ab014..f31dafe18 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java @@ -279,7 +279,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes } private void onExportCompleted(Track.Id trackId) { - trackIds.remove(trackId); + trackIds.remove(trackId); setProgress(); if (trackIds.isEmpty()) { onExportEnded(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java index 7409c6fda..c9bf1cc0b 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -284,7 +285,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track //If not the first segment, add a pause separator if there is at least one TrackPoint in the last segment. if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment != null - && (trackData.lastLocationInCurrentSegment.getType().equals(TrackPoint.Type.SEGMENT_START_MANUAL) || trackData.lastLocationInCurrentSegment.getType().equals(TrackPoint.Type.SEGMENT_START_AUTOMATIC)) + && (trackData.lastLocationInCurrentSegment.getType().equals(TrackPoint.Type.SEGMENT_START_MANUAL)) ) { insertTrackPoint(TrackPoint.createSegmentEndWithTime(trackData.lastLocationInCurrentSegment.getTime())); } @@ -336,6 +337,23 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track protected TrackPoint getTrackPoint() throws SAXException { TrackPoint trackPoint = createTrackPoint(); + if (trackPoint.hasLocation()) { + long time = trackPoint.getTime(); + Date d = new Date(time); + if (trackPoint.getLatitude() == 100) { + //TODO Remove by 31st December 2021. + trackPoint = new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL); + trackPoint.setTime(time); + } else if (trackPoint.getLatitude() == 200) { + //TODO Remove by 31st December 2021. + trackPoint = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL); + trackPoint.setTime(time); + + } else if (!LocationUtils.isValidLocation(trackPoint.getLocation())) { + throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint)); + } + } + // Calculate derived attributes from the previous point if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) { if (!trackPoint.hasSpeed()) { @@ -368,10 +386,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } } - if (trackPoint.hasLocation() && !LocationUtils.isValidLocation(trackPoint.getLocation())) { - throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint)); - } - trackData.lastLocationInCurrentSegment = trackPoint; return trackPoint; } @@ -525,7 +539,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track * * @author Jimmy Shih */ - // TODO Why private inner class? +// TODO Why private inner class? private static class TrackData { // The current track final Track track = new Track();