From 56685a9dec0df35960d187725853e1f6e95afdcc Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Sat, 14 Sep 2019 23:35:28 +0200 Subject: [PATCH] Bugfix: export of images via KMZ is now working. --- .../content/ContentProviderUtilsImpl.java | 9 ++-- .../content/ShareContentProvider.java | 2 +- .../io/file/exporter/ExportAsyncTask.java | 2 +- .../io/file/exporter/FileTrackExporter.java | 6 ++- .../io/file/exporter/KmzTrackExporter.java | 54 ++++++++++--------- .../io/file/exporter/TrackExporter.java | 11 +++- .../dennisguse/opentracks/util/FileUtils.java | 2 +- 7 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java index a8c18a37d..72f640a4a 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java +++ b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java @@ -960,8 +960,7 @@ public class ContentProviderUtilsImpl implements ContentProviderUtils { @Override public Uri insertTrackPoint(Location location, long trackId) { - return contentResolver.insert( - TrackPointsColumns.CONTENT_URI, createContentValues(location, trackId)); + return contentResolver.insert(TrackPointsColumns.CONTENT_URI, createContentValues(location, trackId)); } /** @@ -1071,10 +1070,8 @@ public class ContentProviderUtilsImpl implements ContentProviderUtils { * @param selectionArgs the selection arguments * @param sortOrder the sort order */ - private Cursor getTrackPointCursor( - String[] projection, String selection, String[] selectionArgs, String sortOrder) { - return contentResolver.query( - TrackPointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder); + private Cursor getTrackPointCursor(String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return contentResolver.query(TrackPointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder); } /** diff --git a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java index 7b470e1fd..53d07d335 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java @@ -196,7 +196,7 @@ public class ShareContentProvider extends CustomContentProvider implements ICont @Override public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable String args) { try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) { - trackExporter.writeTrack(fileOutputStream); + trackExporter.writeTrack(getContext(), fileOutputStream); } catch (IOException e) { Log.w(TAG, "there occurred an error while sharing a file: " + e); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java index f47ee3671..f1199399c 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java @@ -163,7 +163,7 @@ public class ExportAsyncTask extends AsyncTask { File file = new File(directory, fileName); try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { - if (trackExporter.writeTrack(fileOutputStream)) { + if (trackExporter.writeTrack(context, fileOutputStream)) { return true; } else { if (!file.delete()) { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java index 161f0a66b..f098eadff 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java @@ -16,10 +16,13 @@ package de.dennisguse.opentracks.io.file.exporter; +import android.content.Context; import android.database.Cursor; import android.location.Location; import android.util.Log; +import androidx.annotation.NonNull; + import java.io.OutputStream; import de.dennisguse.opentracks.content.ContentProviderUtils; @@ -60,7 +63,7 @@ public class FileTrackExporter implements TrackExporter { } @Override - public boolean writeTrack(OutputStream outputStream) { + public boolean writeTrack(Context context, @NonNull OutputStream outputStream) { try { trackWriter.prepare(outputStream); trackWriter.writeHeader(tracks); @@ -76,6 +79,7 @@ public class FileTrackExporter implements TrackExporter { trackWriter.writeEndTracks(); trackWriter.writeFooter(); trackWriter.close(); + return true; } catch (InterruptedException e) { Log.e(TAG, "Thread interrupted", e); 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 513adb849..2a0de52ff 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 @@ -16,13 +16,17 @@ package de.dennisguse.opentracks.io.file.exporter; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.util.Log; +import androidx.annotation.NonNull; + import java.io.File; -import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -30,6 +34,7 @@ import java.util.zip.ZipOutputStream; import de.dennisguse.opentracks.content.ContentProviderUtils; import de.dennisguse.opentracks.content.Track; import de.dennisguse.opentracks.content.Waypoint; +import de.dennisguse.opentracks.util.FileUtils; /** * KMZ track exporter. @@ -61,7 +66,7 @@ public class KmzTrackExporter implements TrackExporter { } @Override - public boolean writeTrack(OutputStream outputStream) { + public boolean writeTrack(@NonNull Context context, @NonNull OutputStream outputStream) { ZipOutputStream zipOutputStream = null; try { zipOutputStream = new ZipOutputStream(outputStream); @@ -70,7 +75,7 @@ public class KmzTrackExporter implements TrackExporter { ZipEntry zipEntry = new ZipEntry(KMZ_KML_FILE); zipOutputStream.putNextEntry(zipEntry); - boolean success = fileTrackExporter.writeTrack(zipOutputStream); + boolean success = fileTrackExporter.writeTrack(context, zipOutputStream); zipOutputStream.closeEntry(); if (!success) { Log.e(TAG, "Unable to write kml in kmz"); @@ -78,7 +83,7 @@ public class KmzTrackExporter implements TrackExporter { } // Add photos - addImages(zipOutputStream); + addImages(context, zipOutputStream); return true; } catch (InterruptedException | IOException e) { Log.e(TAG, "Unable to write track", e); @@ -94,7 +99,7 @@ public class KmzTrackExporter implements TrackExporter { } } - private void addImages(ZipOutputStream zipOutputStream) throws InterruptedException, IOException { + private void addImages(Context context, ZipOutputStream zipOutputStream) throws InterruptedException, IOException { for (Track track : tracks) { try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, -1)) { if (cursor != null && cursor.moveToFirst()) { @@ -108,7 +113,7 @@ public class KmzTrackExporter implements TrackExporter { } Waypoint waypoint = contentProviderUtils.createWaypoint(cursor); if (waypoint.hasPhoto()) { - addImage(zipOutputStream, waypoint.getPhotoUrl()); + addImage(context, zipOutputStream, waypoint.getPhotoUrl()); } } } @@ -116,28 +121,29 @@ public class KmzTrackExporter implements TrackExporter { } } - private void addImage(ZipOutputStream zipOutputStream, String photoUrl) throws IOException { + private void addImage(Context context, ZipOutputStream zipOutputStream, String photoUrl) throws IOException { Uri uri = Uri.parse(photoUrl); - File file = new File(uri.getPath()); - if (!file.exists()) { - Log.e(TAG, "file not found " + photoUrl); - return; + + try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { + ZipEntry zipEntry = new ZipEntry(KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(uri.getLastPathSegment())); + zipOutputStream.putNextEntry(zipEntry); + + if (inputStream == null) throw new FileNotFoundException(); + + readToOutputStream(inputStream, zipOutputStream); + zipOutputStream.closeEntry(); + + Log.i(TAG, "added an image to zip"); + } catch (FileNotFoundException e) { + Log.e(TAG, "could not get image via FileProvider via uri " + uri); } - - ZipEntry zipEntry = new ZipEntry(KMZ_IMAGES_DIR + File.separatorChar + uri.getLastPathSegment()); - zipOutputStream.putNextEntry(zipEntry); - - readFromFile(zipOutputStream, uri); - zipOutputStream.closeEntry(); } - private void readFromFile(ZipOutputStream zipOutputStream, Uri uri) throws IOException { - try (FileInputStream fileInputStream = new FileInputStream(new File(uri.getPath()))) { - byte[] buffer = new byte[BUFFER_SIZE]; - int byteCount; - while ((byteCount = fileInputStream.read(buffer)) != -1) { - zipOutputStream.write(buffer, 0, byteCount); - } + private void readToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException { + byte[] buffer = new byte[BUFFER_SIZE]; + int byteCount; + while ((byteCount = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, byteCount); } } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/TrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/TrackExporter.java index 0cf8cc456..71befbb26 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/TrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/TrackExporter.java @@ -16,6 +16,11 @@ package de.dennisguse.opentracks.io.file.exporter; +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.io.OutputStream; /** @@ -26,9 +31,11 @@ import java.io.OutputStream; public interface TrackExporter { /** - * Write track to an output stream + * Write track to an output stream. + * Depending on the implementation a context might be required. * + * @param context the context * @param outputStream the output stream */ - boolean writeTrack(OutputStream outputStream); + boolean writeTrack(@Nullable Context context, @NonNull OutputStream outputStream); } diff --git a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java index ae94b6bb2..0a450527d 100644 --- a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java @@ -204,7 +204,7 @@ public class FileUtils { * * @param name name */ - static String sanitizeFileName(String name) { + public static String sanitizeFileName(String name) { StringBuilder builder = new StringBuilder(name.length()); for (int i = 0; i < name.length(); i++) { int codePoint = name.codePointAt(i);