Use correct mime type for KML and KMZ.

This commit is contained in:
Dennis Guse
2019-08-23 07:19:40 +02:00
parent 70b5d799a2
commit 5e74e80a9a
5 changed files with 53 additions and 26 deletions
@@ -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);
@@ -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<Uri, String> 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);
@@ -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}.
*
* <p>
* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}.
*
* <p>
* 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<Uri, String> 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);
}
@@ -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<TrackFileFormat> CREATOR = new Creator<TrackFileFormat>() {
@@ -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.
@@ -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<Uri, String> 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);
}