Bugfix: export of images via KMZ is now working.

This commit is contained in:
Dennis Guse
2019-09-14 23:35:28 +02:00
parent 45b13ea813
commit 56685a9dec
7 changed files with 50 additions and 36 deletions
@@ -960,8 +960,7 @@ public class ContentProviderUtilsImpl implements ContentProviderUtils {
@Override @Override
public Uri insertTrackPoint(Location location, long trackId) { public Uri insertTrackPoint(Location location, long trackId) {
return contentResolver.insert( return contentResolver.insert(TrackPointsColumns.CONTENT_URI, createContentValues(location, trackId));
TrackPointsColumns.CONTENT_URI, createContentValues(location, trackId));
} }
/** /**
@@ -1071,10 +1070,8 @@ public class ContentProviderUtilsImpl implements ContentProviderUtils {
* @param selectionArgs the selection arguments * @param selectionArgs the selection arguments
* @param sortOrder the sort order * @param sortOrder the sort order
*/ */
private Cursor getTrackPointCursor( private Cursor getTrackPointCursor(String[] projection, String selection, String[] selectionArgs, String sortOrder) {
String[] projection, String selection, String[] selectionArgs, String sortOrder) { return contentResolver.query(TrackPointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder);
return contentResolver.query(
TrackPointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder);
} }
/** /**
@@ -196,7 +196,7 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
@Override @Override
public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable String args) { 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())) { try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) {
trackExporter.writeTrack(fileOutputStream); trackExporter.writeTrack(getContext(), fileOutputStream);
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "there occurred an error while sharing a file: " + e); Log.w(TAG, "there occurred an error while sharing a file: " + e);
} }
@@ -163,7 +163,7 @@ public class ExportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
File file = new File(directory, fileName); File file = new File(directory, fileName);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
if (trackExporter.writeTrack(fileOutputStream)) { if (trackExporter.writeTrack(context, fileOutputStream)) {
return true; return true;
} else { } else {
if (!file.delete()) { if (!file.delete()) {
@@ -16,10 +16,13 @@
package de.dennisguse.opentracks.io.file.exporter; package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.location.Location; import android.location.Location;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import java.io.OutputStream; import java.io.OutputStream;
import de.dennisguse.opentracks.content.ContentProviderUtils; import de.dennisguse.opentracks.content.ContentProviderUtils;
@@ -60,7 +63,7 @@ public class FileTrackExporter implements TrackExporter {
} }
@Override @Override
public boolean writeTrack(OutputStream outputStream) { public boolean writeTrack(Context context, @NonNull OutputStream outputStream) {
try { try {
trackWriter.prepare(outputStream); trackWriter.prepare(outputStream);
trackWriter.writeHeader(tracks); trackWriter.writeHeader(tracks);
@@ -76,6 +79,7 @@ public class FileTrackExporter implements TrackExporter {
trackWriter.writeEndTracks(); trackWriter.writeEndTracks();
trackWriter.writeFooter(); trackWriter.writeFooter();
trackWriter.close(); trackWriter.close();
return true; return true;
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(TAG, "Thread interrupted", e); Log.e(TAG, "Thread interrupted", e);
@@ -16,13 +16,17 @@
package de.dennisguse.opentracks.io.file.exporter; package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; 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.ContentProviderUtils;
import de.dennisguse.opentracks.content.Track; import de.dennisguse.opentracks.content.Track;
import de.dennisguse.opentracks.content.Waypoint; import de.dennisguse.opentracks.content.Waypoint;
import de.dennisguse.opentracks.util.FileUtils;
/** /**
* KMZ track exporter. * KMZ track exporter.
@@ -61,7 +66,7 @@ public class KmzTrackExporter implements TrackExporter {
} }
@Override @Override
public boolean writeTrack(OutputStream outputStream) { public boolean writeTrack(@NonNull Context context, @NonNull OutputStream outputStream) {
ZipOutputStream zipOutputStream = null; ZipOutputStream zipOutputStream = null;
try { try {
zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream = new ZipOutputStream(outputStream);
@@ -70,7 +75,7 @@ public class KmzTrackExporter implements TrackExporter {
ZipEntry zipEntry = new ZipEntry(KMZ_KML_FILE); ZipEntry zipEntry = new ZipEntry(KMZ_KML_FILE);
zipOutputStream.putNextEntry(zipEntry); zipOutputStream.putNextEntry(zipEntry);
boolean success = fileTrackExporter.writeTrack(zipOutputStream); boolean success = fileTrackExporter.writeTrack(context, zipOutputStream);
zipOutputStream.closeEntry(); zipOutputStream.closeEntry();
if (!success) { if (!success) {
Log.e(TAG, "Unable to write kml in kmz"); Log.e(TAG, "Unable to write kml in kmz");
@@ -78,7 +83,7 @@ public class KmzTrackExporter implements TrackExporter {
} }
// Add photos // Add photos
addImages(zipOutputStream); addImages(context, zipOutputStream);
return true; return true;
} catch (InterruptedException | IOException e) { } catch (InterruptedException | IOException e) {
Log.e(TAG, "Unable to write track", 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) { for (Track track : tracks) {
try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, -1)) { try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, -1)) {
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
@@ -108,7 +113,7 @@ public class KmzTrackExporter implements TrackExporter {
} }
Waypoint waypoint = contentProviderUtils.createWaypoint(cursor); Waypoint waypoint = contentProviderUtils.createWaypoint(cursor);
if (waypoint.hasPhoto()) { 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); Uri uri = Uri.parse(photoUrl);
File file = new File(uri.getPath());
if (!file.exists()) { try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
Log.e(TAG, "file not found " + photoUrl); ZipEntry zipEntry = new ZipEntry(KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(uri.getLastPathSegment()));
return; 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 { private void readToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException {
try (FileInputStream fileInputStream = new FileInputStream(new File(uri.getPath()))) { byte[] buffer = new byte[BUFFER_SIZE];
byte[] buffer = new byte[BUFFER_SIZE]; int byteCount;
int byteCount; while ((byteCount = inputStream.read(buffer)) != -1) {
while ((byteCount = fileInputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, byteCount);
zipOutputStream.write(buffer, 0, byteCount);
}
} }
} }
} }
@@ -16,6 +16,11 @@
package de.dennisguse.opentracks.io.file.exporter; package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.OutputStream; import java.io.OutputStream;
/** /**
@@ -26,9 +31,11 @@ import java.io.OutputStream;
public interface TrackExporter { 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 * @param outputStream the output stream
*/ */
boolean writeTrack(OutputStream outputStream); boolean writeTrack(@Nullable Context context, @NonNull OutputStream outputStream);
} }
@@ -204,7 +204,7 @@ public class FileUtils {
* *
* @param name name * @param name name
*/ */
static String sanitizeFileName(String name) { public static String sanitizeFileName(String name) {
StringBuilder builder = new StringBuilder(name.length()); StringBuilder builder = new StringBuilder(name.length());
for (int i = 0; i < name.length(); i++) { for (int i = 0; i < name.length(); i++) {
int codePoint = name.codePointAt(i); int codePoint = name.codePointAt(i);