From 9c9bdde6b9c408e57fa6a109711004ed89105045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 11 Nov 2020 18:18:35 +0100 Subject: [PATCH] Import files by track in memory (avoid clean track when error). Fixes #473. --- .../provider/ContentProviderUtils.java | 13 +++++- .../io/file/exporter/KmlTrackWriter.java | 2 +- .../io/file/exporter/KmzTrackExporter.java | 2 +- .../importer/AbstractFileTrackImporter.java | 43 ++++++++----------- .../ImportAlreadyExistsException.java | 4 ++ .../io/file/importer/KmzTrackImporter.java | 1 + src/main/res/values/strings.xml | 1 + 7 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java index 600f4a589..75269c680 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java @@ -488,7 +488,7 @@ public class ContentProviderUtils { private void deleteMarkerPhoto(Context context, Marker marker) { if (marker != null && marker.hasPhoto()) { Uri uri = marker.getPhotoURI(); - File file = FileUtils.getPhotoFileIfExists(context, marker.getTrackId(), uri); + File file = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), uri); if (file.exists()) { File parent = file.getParentFile(); file.delete(); @@ -616,7 +616,7 @@ public class ContentProviderUtils { * @param trackId the trackPoints id * @return the number of trackPoints inserted */ - //TODO Only used for testing and file import; might be better to replace it. + //TODO Only used for testing; might be better to replace it. public int bulkInsertTrackPoint(TrackPoint[] trackPoints, Track.Id trackId) { ContentValues[] values = new ContentValues[trackPoints.length]; for (int i = 0; i < values.length; i++) { @@ -625,6 +625,15 @@ public class ContentProviderUtils { return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI_BY_ID, values); } + //TODO Only used for file import; might be better to replace it. + public int bulkInsertTrackPoint(List trackPoints, Track.Id trackId) { + ContentValues[] values = new ContentValues[trackPoints.size()]; + for (int i = 0; i < trackPoints.size(); i++) { + values[i] = createContentValues(trackPoints.get(i), trackId); + } + return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI_BY_ID, values); + } + /** * Gets the first location id for a track. * Returns null if it doesn't exist. diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java index 1b224aa5e..cf0b7a867 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java @@ -167,7 +167,7 @@ public class KmlTrackWriter implements TrackWriter { @Override public void writeMarker(Marker marker) { if (printWriter != null && exportTrackDetail) { - boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, marker.getTrackId(), marker.getPhotoURI()) != null; + boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null; if (marker.hasPhoto() && exportPhotos && existsPhoto) { float heading = getHeading(marker.getTrackId(), marker.getLocation()); writePhotoOverlay(marker, heading); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java index 9d94b21c2..d06e071b2 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java @@ -108,7 +108,7 @@ public class KmzTrackExporter implements TrackExporter { Marker marker = contentProviderUtils.createMarker(cursor); if (marker.hasPhoto()) { Uri uriPhoto = marker.getPhotoURI(); - boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, track.getId(), uriPhoto) != null; + boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null; if (existsPhoto) { addImage(context, zipOutputStream, uriPhoto, marker); } 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 9c1f55d79..3ee29d19b 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,7 +29,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -61,9 +60,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track private static final String TAG = AbstractFileTrackImporter.class.getSimpleName(); - // The maximum number of buffered locations for bulk-insertion - private static final int MAX_BUFFERED_LOCATIONS = 512; - private final Context context; private final ContentProviderUtils contentProviderUtils; private final int recordingDistanceInterval; @@ -127,10 +123,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track saxParser.parse(inputStream, this); Log.d(TAG, "Total import time: " + (System.currentTimeMillis() - start) + "ms"); - if (trackIds.size() != 1) { - // TODO Multi track is not supported yet. - throw new ImportParserException("Multi track not supported"); - } return trackIds.get(0); } catch (IOException | SAXException | ParserConfigurationException e) { Log.e(TAG, "Unable to import file", e); @@ -228,17 +220,12 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track */ protected void onTrackStart() throws SAXException { trackData = new TrackData(); - Uri uri = contentProviderUtils.insertTrack(trackData.track); - Track.Id trackId = new Track.Id(Long.parseLong(uri.getLastPathSegment())); - trackIds.add(trackId); - trackData.track.setId(trackId); } /** * On track end. */ protected void onTrackEnd() { - flushLocations(trackData); if (name != null) { trackData.track.setName(name); } @@ -268,17 +255,27 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } trackData.track.setTrackStatistics(trackData.trackStatisticsUpdater.getTrackStatistics()); - try { - contentProviderUtils.updateTrack(trackData.track); - } catch (SQLiteConstraintException e) { + Track track = contentProviderUtils.getTrack(trackData.track.getUuid()); + if (track != null) { if (PreferencesUtils.getPreventReimportTracks(context)) { - throw e; + throw new ImportAlreadyExistsException(context.getString(R.string.import_prevent_reimport)); } //TODO This is a workaround until we have proper UI. trackData.track.setUuid(UUID.randomUUID()); - contentProviderUtils.updateTrack(trackData.track); } + + if (trackIds.size() > 0) { + // TODO Multi track is not supported yet. + cleanImport(); + throw new ImportParserException("Multi track not supported"); + } + Uri uri = contentProviderUtils.insertTrack(trackData.track); + Track.Id trackId = new Track.Id(Long.parseLong(uri.getLastPathSegment())); + trackIds.add(trackId); + trackData.track.setId(trackId); + + flushLocations(trackData); } /** @@ -482,13 +479,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } trackData.trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval); - trackData.bufferedTrackPoints[trackData.numBufferedTrackPoints] = trackPoint; + trackData.bufferedTrackPoints.add(trackPoint); trackData.numBufferedTrackPoints++; trackData.numberOfLocations++; - - if (trackData.numBufferedTrackPoints >= MAX_BUFFERED_LOCATIONS) { - flushLocations(trackData); - } } /** @@ -500,7 +493,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track if (data.numBufferedTrackPoints <= 0) { return; } - contentProviderUtils.bulkInsertTrackPoint(Arrays.copyOfRange(data.bufferedTrackPoints, 0, data.numBufferedTrackPoints), data.track.getId()); + contentProviderUtils.bulkInsertTrackPoint(data.bufferedTrackPoints, data.track.getId()); data.numBufferedTrackPoints = 0; } @@ -537,7 +530,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track final long importTime = System.currentTimeMillis(); // The buffered locations - final TrackPoint[] bufferedTrackPoints = new TrackPoint[MAX_BUFFERED_LOCATIONS]; + final List bufferedTrackPoints = new ArrayList<>(); // The number of buffered locations int numBufferedTrackPoints = 0; diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAlreadyExistsException.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAlreadyExistsException.java index c8f493314..d5c654dd2 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAlreadyExistsException.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAlreadyExistsException.java @@ -4,4 +4,8 @@ class ImportAlreadyExistsException extends RuntimeException { public ImportAlreadyExistsException(Exception e) { super(e); } + + public ImportAlreadyExistsException(String msg) { + super(msg); + } } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java index 3fe350291..8eb440c9b 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java @@ -271,6 +271,7 @@ public class KmzTrackImporter implements TrackImporter { * Reads an image file (zipInputStream) and save it in a file called fileName inside photo folder. * * @param zipInputStream the zip input stream + * @param trackId the track's id which image belongs to. * @param fileName the file name */ private void readAndSaveImageFile(ZipInputStream zipInputStream, Track.Id trackId, String fileName) throws IOException { diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index c6dce953d..187788b19 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -294,6 +294,7 @@ limitations under the License. Files not imported File %1$s imported Imported %1$d of %2$s from %3$s + You have set prevent re-import track %1$s does not exist There were no files to import. Connect your device to your computer and place the files to import in %1$s. Import files