From 0f1d8500d1feebde73d043d1ceb291afe180fb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n?= Date: Sun, 12 Apr 2020 17:25:30 +0200 Subject: [PATCH] KMZ importing: firstly copies images then parses kml (checks kml's href link to image is correct). --- .../importer/AbstractFileTrackImporter.java | 11 ++- .../io/file/importer/ImportAsyncTask.java | 2 +- .../io/file/importer/KmzTrackImporter.java | 76 ++++++++++++++++--- 3 files changed, 73 insertions(+), 16 deletions(-) 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 9c056342e..49fb6379b 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 @@ -393,10 +393,13 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track File dir = FileUtils.getPhotoDir(context, importTrackId); File file = new File(dir, filename); - - Uri photoUri = FileUtils.getUriForFile(context, file); - - return "" + photoUri; + if (file.exists()) { + Uri photoUri = FileUtils.getUriForFile(context, file); + return "" + photoUri; + } + else { + return null; + } } /** diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java index 5c24c0ad2..fa8c55c95 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java @@ -186,7 +186,7 @@ class ImportAsyncTask extends AsyncTask { Uri uri = contentProviderUtils.insertTrack(new Track()); long newId = Long.parseLong(uri.getLastPathSegment()); - trackImporter = new KmzTrackImporter(importActivity, newId); + trackImporter = new KmzTrackImporter(importActivity, newId, file.getUri()); } } 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 3db706bdd..a69059fc8 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 @@ -17,6 +17,7 @@ package de.dennisguse.opentracks.io.file.importer; import android.content.Context; +import android.net.Uri; import android.util.Log; import java.io.ByteArrayInputStream; @@ -46,50 +47,103 @@ public class KmzTrackImporter implements TrackImporter { private final Context context; private final long importTrackId; + private Uri uriKmzFile; /** * Constructor. * * @param context the context * @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported. + * @param uriFile URI of the kmz file. */ - KmzTrackImporter(Context context, long importTrackId) { + KmzTrackImporter(Context context, long importTrackId, Uri uriFile) { this.context = context; this.importTrackId = importTrackId; + this.uriKmzFile = uriFile; } @Override public long importFile(InputStream inputStream) { - long trackId = importTrackId; - try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { + long trackId; + + if (!copyKmzImages()) { + cleanImport(context, importTrackId); + return -1L; + } + + trackId = findAndParseKmlFile(inputStream); + if (trackId == -1L) { + cleanImport(context, importTrackId); + return -1L; + } + + return trackId; + } + + /** + * Copies KMZ images that are inside KmzTrackExporter.KMZ_IMAGES_DIR to OpenTracks external storage. + * + * @return false if there are errors or true otherwise. + */ + private boolean copyKmzImages() { + try (InputStream inputStream = context.getContentResolver().openInputStream(uriKmzFile); + ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { ZipEntry zipEntry; while ((zipEntry = zipInputStream.getNextEntry()) != null) { if (Thread.interrupted()) { Log.d(TAG, "Thread interrupted"); - cleanImport(context, trackId); + return false; + } + + String fileName = zipEntry.getName(); + String prefix = KmzTrackExporter.KMZ_IMAGES_DIR + File.separatorChar; + if (fileName.startsWith(prefix)) { + readImageFile(zipInputStream, fileName.substring(prefix.length())); + } + + zipInputStream.closeEntry(); + } + + return true; + } catch (IOException e) { + Log.e(TAG, "Unable to import file", e); + return false; + } + } + + /** + * Finds KmzTrackExporter.KMZ_KML_FILE file inside kmz file (inputStream) and it parses it. + * + * @param inputStream kmz input stream. + * @return -1 if error or the id of the track otherwise. + */ + private long findAndParseKmlFile(InputStream inputStream) { + try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { + ZipEntry zipEntry; + long trackId = -1L; + + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + if (Thread.interrupted()) { + Log.d(TAG, "Thread interrupted"); return -1L; } + String fileName = zipEntry.getName(); if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) { trackId = parseKml(zipInputStream); if (trackId == -1L) { Log.d(TAG, "Unable to parse kml in kmz"); - cleanImport(context, trackId); return -1L; } - } else { - String prefix = KmzTrackExporter.KMZ_IMAGES_DIR + File.separatorChar; - if (fileName.startsWith(prefix)) { - readImageFile(zipInputStream, fileName.substring(prefix.length())); - } } + zipInputStream.closeEntry(); } + return trackId; } catch (IOException e) { Log.e(TAG, "Unable to import file", e); - cleanImport(context, trackId); return -1L; } }