forked from upstream-mirrors/OpenTracks
Bugfix: export of images via KMZ is now working.
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user