From 7c030857616f3bbe9ba9702b1c1d9c043992f511 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Wed, 19 Aug 2026 20:45:23 +0200 Subject: [PATCH] GPX: on import ignore TrackPoints without time. Previous behavior: abort import. Fixes #2384. --- .../file/importer/GPXTrackImporterTest.java | 41 +++++++++++++++++++ .../res/raw/gpx11_missing_time.gpx | 22 ++++++++++ .../io/file/importer/GPXTrackImporter.java | 17 ++++++-- 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/androidTest/res/raw/gpx11_missing_time.gpx 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 91dbaa188..32e37bde5 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 @@ -120,6 +120,47 @@ public class GPXTrackImporterTest { ), importedTrackPoints); } + @LargeTest + @Test + public void gpx_missing_time() throws IOException { + // given + XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter)); + InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx11_missing_time); + + // when + // 1. import + importTrackId = importer.importFile(inputStream).get(0); + + // then + // 2. track + Track importedTrack = contentProviderUtils.getTrack(importTrackId); + assertNotNull(importedTrack); + assertEquals("", importedTrack.activityTypeLocalized()); + assertEquals("", importedTrack.description()); + assertEquals("20210907_213924.gpx", importedTrack.name()); + assertEquals(ActivityType.UNKNOWN, importedTrack.activityType()); + + // 3. trackstatistics + Statistics trackStatistics = importedTrack.statistics(); + assertEquals(0, trackStatistics.maxSpeed().toMPS(), 0.01); + assertEquals(Duration.ofSeconds(0), trackStatistics.movingDuration()); + + // 4. trackpoints + List importedTrackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId); + assertEquals(1, importedTrackPoints.size()); + + TrackPointAssert a = new TrackPointAssert(); + a.assertEquals(List.of( + new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, + new Position( + Instant.parse("2021-09-07T22:12:00Z"), + 30.14185982, -40.3863038, null, + Altitude.WGS84.of(-5), null, + null, + null)) + ), importedTrackPoints); + } + @LargeTest @Test public void gpx_speed_no_namespace() throws IOException { diff --git a/src/androidTest/res/raw/gpx11_missing_time.gpx b/src/androidTest/res/raw/gpx11_missing_time.gpx new file mode 100644 index 000000000..4cadd43bd --- /dev/null +++ b/src/androidTest/res/raw/gpx11_missing_time.gpx @@ -0,0 +1,22 @@ + + + + 20210907_213924.gpx + + + -5 + 4 + + + -5 + + + -5 + + 4 + + + + \ No newline at end of file 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 1cd877c83..de24a08a5 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 @@ -18,8 +18,11 @@ package de.dennisguse.opentracks.io.file.importer; import android.content.Context; import android.net.Uri; +import android.text.TextUtils; import android.util.Log; +import androidx.annotation.Nullable; + import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.xml.sax.helpers.DefaultHandler; @@ -178,7 +181,10 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac zoneOffset = null; } case TAG_TRACK_SEGMENT -> onTrackSegmentEnd(); - case TAG_TRACK_POINT -> currentSegment.add(createTrackPoint()); + case TAG_TRACK_POINT -> { + TrackPoint trackPoint = createTrackPoint(); + if (trackPoint != null) currentSegment.add(trackPoint); + } case TAG_NAME -> { if (content != null) { name = content.trim(); @@ -284,8 +290,10 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac currentSegment.clear(); } - + @Nullable private TrackPoint createTrackPoint() throws ParsingException { + if (TextUtils.isEmpty(time)) return null; + OffsetDateTime parsedTime; try { parsedTime = StringUtils.parseTime(time); @@ -468,7 +476,10 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac } TrackPoint trackPoint = createTrackPoint(); - + if (trackPoint == null) { + Log.w(TAG, "Marker with no TrackPoint"); + return; + } if (!trackPoint.position().hasLocation()) { Log.w(TAG, "Marker with invalid coordinates ignored: " + trackPoint.position()); return;