From 5e74e80a9adc24ef1be60730dfe2ac03ee4270a8 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Fri, 23 Aug 2019 07:19:40 +0200 Subject: [PATCH] Use correct mime type for KML and KMZ. --- .../opentracks/TrackDetailActivity.java | 3 +- .../opentracks/TrackListActivity.java | 5 ++- .../content/ShareContentProvider.java | 41 ++++++++++++------- .../opentracks/io/file/TrackFileFormat.java | 19 +++++++-- .../opentracks/util/IntentUtils.java | 11 ++--- 5 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java index 229e86146..f1d4e5962 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java @@ -55,7 +55,6 @@ import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment.Choos import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.fragments.FrequencyDialogFragment; import de.dennisguse.opentracks.fragments.StatsFragment; -import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.FileUtils; @@ -306,7 +305,7 @@ public class TrackDetailActivity extends AbstractTrackActivity implements Choose shareMenuItem = menu.findItem(R.id.track_detail_share); ShareActionProvider shareActionProvider = (ShareActionProvider) shareMenuItem.getActionProvider(); - shareActionProvider.setShareIntent(IntentUtils.newShareFileIntent(this, trackId, TrackFileFormat.KML)); + shareActionProvider.setShareIntent(IntentUtils.newShareFileIntent(this, trackId)); voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency); splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency); diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index fd450ed14..142835a20 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -26,9 +26,11 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; import android.database.Cursor; import android.location.LocationManager; +import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.util.Log; +import android.util.Pair; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; @@ -565,9 +567,10 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD return; } + Pair uriAndMime = ShareContentProvider.createURI(trackIds); Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(ShareContentProvider.createURI(trackIds), ShareContentProvider.MIME); + intent.setDataAndType(uriAndMime.first, uriAndMime.second); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try { startActivity(intent); diff --git a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java index 83f55497a..6453219b2 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java @@ -10,6 +10,7 @@ import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.provider.OpenableColumns; import android.util.Log; +import android.util.Pair; import android.widget.Toast; import androidx.annotation.NonNull; @@ -28,15 +29,14 @@ import de.dennisguse.opentracks.io.file.exporter.TrackWriter; /** * A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files. * The actual content of the virtual files is generated by using the functionality defined in {@link CustomContentProvider}. - * + *

* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}. - * + *

* Explanation: * Although a request is handled by a {@link android.content.ContentProvider} (with temporarily granted permission), Android's security infrastructure prevents forwarding queries to non-exported {@link android.content.ContentProvider}. * Thus, if {@link ShareContentProvider} and {@link CustomContentProvider} would be two different instances, the data would not be accessible to external apps. * While handling a request {@link ShareContentProvider} could `grantPermissions()` to the calling app for {@link CustomContentProvider}'s URI. * However, while handling the request this would allow the calling app to actually contact {@link CustomContentProvider} directly and get access to stored data that should remain private. - * */ public class ShareContentProvider extends CustomContentProvider implements IContentResolver { @@ -44,11 +44,14 @@ public class ShareContentProvider extends CustomContentProvider implements ICont public static final String TAG = ShareContentProvider.class.getCanonicalName(); - public static String MIME = "application/kml+xml"; private static final int URI_KML = 1; - private final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - public static Uri createURI(long[] trackIds) { + static { + uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/kml/*", URI_KML); + } + + public static Pair createURI(long[] trackIds) { if (trackIds.length == 0) { throw new UnsupportedOperationException(); } @@ -59,13 +62,9 @@ public class ShareContentProvider extends CustomContentProvider implements ICont } builder.deleteCharAt(builder.lastIndexOf(",")); - return Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TracksColumns.TABLE_NAME + "/kml/" + builder + ".kml"); - } - - @Override - public boolean onCreate() { - uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/kml/*", URI_KML); - return super.onCreate(); + Uri uri = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TracksColumns.TABLE_NAME + "/kml/" + builder + ".kml"); + String mime = getTypeMime(uri); + return new Pair<>(uri, mime); } /** @@ -132,12 +131,24 @@ public class ShareContentProvider extends CustomContentProvider implements ICont return cursor; } + @Nullable + public static String getTypeMime(@NonNull Uri uri) { + switch (uriMatcher.match(uri)) { + case URI_KML: + return TrackFileFormat.KML.getMimeType(); + } + + return null; + } + @Nullable @Override public String getType(@NonNull Uri uri) { - if (uriMatcher.match(uri) == URI_KML) { - return MIME; + String mime = getTypeMime(uri); + if (mime != null) { + return mime; } + return super.getType(uri); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/TrackFileFormat.java b/src/main/java/de/dennisguse/opentracks/io/file/TrackFileFormat.java index d67cda5cd..4c066ee55 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/TrackFileFormat.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/TrackFileFormat.java @@ -20,18 +20,33 @@ public enum TrackFileFormat implements Parcelable { public TrackWriter newTrackWriter(Context context, boolean multiple) { return new KmlTrackWriter(context, multiple, false); } + + @Override + public String getMimeType() { + return "application/vnd.google-earth.kml+xml"; + } }, KMZ { @Override public TrackWriter newTrackWriter(Context context, boolean multiple) { return new KmlTrackWriter(context, multiple, true); } + + @Override + public String getMimeType() { + return "application/vnd.google-earth.kmz"; + } }, GPX { @Override public TrackWriter newTrackWriter(Context context, boolean multiple) { return new GpxTrackWriter(context.getString(R.string.app_name)); } + + @Override + public String getMimeType() { + return "application/gpx+xml"; + } }; public static final Creator CREATOR = new Creator() { @@ -67,9 +82,7 @@ public enum TrackFileFormat implements Parcelable { /** * Returns the mime type for each format. */ - public String getMimeType() { - return "application/" + getExtension() + "+xml"; - } + public abstract String getMimeType(); /** * Returns the file extension for each format. diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java index f4cd5a733..96bda12a2 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java @@ -19,6 +19,7 @@ package de.dennisguse.opentracks.util; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.util.Pair; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.content.ContentProviderUtils; @@ -26,7 +27,6 @@ import de.dennisguse.opentracks.content.DescriptionGeneratorImpl; import de.dennisguse.opentracks.content.ShareContentProvider; import de.dennisguse.opentracks.content.Track; import de.dennisguse.opentracks.content.Waypoint; -import de.dennisguse.opentracks.io.file.TrackFileFormat; /** * Utilities for creating intents. @@ -54,17 +54,18 @@ public class IntentUtils { * * @param context the context * @param trackId the track id - * @param trackFileFormat the track file format */ - public static Intent newShareFileIntent(Context context, long trackId, TrackFileFormat trackFileFormat) { + public static Intent newShareFileIntent(Context context, long trackId) { Track track = ContentProviderUtils.Factory.get(context).getTrack(trackId); String trackDescription = track == null ? "" : new DescriptionGeneratorImpl(context).generateTrackDescription(track, false); + Pair uriAndMime = ShareContentProvider.createURI(new long[]{trackId}); + return new Intent(Intent.ACTION_SEND) - .putExtra(Intent.EXTRA_STREAM, ShareContentProvider.createURI(new long[]{trackId})) + .putExtra(Intent.EXTRA_STREAM, uriAndMime.first) .putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.share_track_subject)) .putExtra(Intent.EXTRA_TEXT, context.getString(R.string.share_track_share_file_body, trackDescription)) - .setType(trackFileFormat.getMimeType()) + .setType(uriAndMime.second) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); }