forked from upstream-mirrors/OpenTracks
Show on map: draft via sharing temporary file.
This commit is contained in:
@@ -25,6 +25,7 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -46,20 +47,30 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||||
import androidx.loader.content.CursorLoader;
|
import androidx.loader.content.CursorLoader;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
||||||
|
import de.dennisguse.opentracks.content.Track;
|
||||||
import de.dennisguse.opentracks.content.TracksColumns;
|
import de.dennisguse.opentracks.content.TracksColumns;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
|
import de.dennisguse.opentracks.io.file.exporter.FileTrackExporter;
|
||||||
|
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||||
import de.dennisguse.opentracks.services.ITrackRecordingService;
|
import de.dennisguse.opentracks.services.ITrackRecordingService;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
import de.dennisguse.opentracks.util.ListItemUtils;
|
import de.dennisguse.opentracks.util.ListItemUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
@@ -107,8 +118,7 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD
|
|||||||
private boolean metricUnits = true;
|
private boolean metricUnits = true;
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
// Callback when an item is selected in the contextual action mode
|
// Callback when an item is selected in the contextual action mode
|
||||||
private final ContextualActionModeCallback
|
private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
||||||
contextualActionModeCallback = new ContextualActionModeCallback() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
|
public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
|
||||||
@@ -116,7 +126,6 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD
|
|||||||
boolean isSingleSelection = ids.length == 1;
|
boolean isSingleSelection = ids.length == 1;
|
||||||
|
|
||||||
menu.findItem(R.id.list_context_menu_share).setVisible(!isRecording && isSingleSelection);
|
menu.findItem(R.id.list_context_menu_share).setVisible(!isRecording && isSingleSelection);
|
||||||
menu.findItem(R.id.list_context_menu_show_on_map).setVisible(false);
|
|
||||||
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
|
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
|
||||||
menu.findItem(R.id.list_context_menu_select_all).setVisible(showSelectAll);
|
menu.findItem(R.id.list_context_menu_select_all).setVisible(showSelectAll);
|
||||||
}
|
}
|
||||||
@@ -128,7 +137,7 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD
|
|||||||
};
|
};
|
||||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
||||||
/*
|
/*
|
||||||
* Note that sharedPreferenceChangeListenr cannot be an anonymous inner class.
|
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
|
||||||
* Anonymous inner class will get garbage collected.
|
* Anonymous inner class will get garbage collected.
|
||||||
*/
|
*/
|
||||||
private final OnSharedPreferenceChangeListener
|
private final OnSharedPreferenceChangeListener
|
||||||
@@ -556,6 +565,59 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD
|
|||||||
bindChangedCallback.run();
|
bindChangedCallback.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save tracks in one file and send an intent to show it with a map application.
|
||||||
|
* TODO: Exported file is not deleted automatically.
|
||||||
|
*
|
||||||
|
* @param trackIds
|
||||||
|
*/
|
||||||
|
private void showOnExternalMap(long[] trackIds) {
|
||||||
|
if (trackIds.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track[] tracks = new Track[trackIds.length];
|
||||||
|
for (int i = 0; i < trackIds.length; i++) {
|
||||||
|
tracks[i] = contentProviderUtils.getTrack(trackIds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackFileFormat trackFileFormat = TrackFileFormat.KML;
|
||||||
|
TrackExporter trackExporter = new FileTrackExporter(contentProviderUtils, tracks,
|
||||||
|
trackFileFormat.newTrackWriter(this, tracks.length > 1), null);
|
||||||
|
|
||||||
|
File directory = new File(FileUtils.getPath(trackFileFormat.getExtension()));
|
||||||
|
if (!FileUtils.ensureDirectoryExists(directory)) {
|
||||||
|
Toast.makeText(this, R.string.external_storage_not_writable, Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = FileUtils.buildUniqueFileName(directory, tracks[0].getName(), trackFileFormat.getExtension());
|
||||||
|
File file = new File(directory, fileName);
|
||||||
|
|
||||||
|
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
|
||||||
|
if (trackExporter.writeTrack(fileOutputStream)) {
|
||||||
|
Uri fileUri = FileProvider.getUriForFile(this, FileUtils.FILEPROVIDER, file);
|
||||||
|
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||||
|
intent.setDataAndType(fileUri, "application/vnd.google-earth.kml+xml");
|
||||||
|
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
startActivity(intent);
|
||||||
|
} else {
|
||||||
|
if (!file.delete()) {
|
||||||
|
Log.d(TAG, "Unable to delete file");
|
||||||
|
}
|
||||||
|
Log.e(TAG, "Unable to export track");
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e(TAG, "Unable to open file " + file.getName(), e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Unable to close file output stream", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a context item selection.
|
* Handles a context item selection.
|
||||||
*
|
*
|
||||||
@@ -565,6 +627,9 @@ public class TrackListActivity extends AbstractTrackActivity implements ConfirmD
|
|||||||
*/
|
*/
|
||||||
private boolean handleContextItem(int itemId, long[] trackIds) {
|
private boolean handleContextItem(int itemId, long[] trackIds) {
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
|
case R.id.list_context_menu_show_on_map:
|
||||||
|
showOnExternalMap(trackIds);
|
||||||
|
return true;
|
||||||
case R.id.list_context_menu_share:
|
case R.id.list_context_menu_share:
|
||||||
//TODO
|
//TODO
|
||||||
Log.e(TAG, "Not implemented");
|
Log.e(TAG, "Not implemented");
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import de.dennisguse.opentracks.util.SystemUtils;
|
|||||||
*
|
*
|
||||||
* @author Jimmy Shih
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
|
//TODO Make independent from ExportActivity?
|
||||||
public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||||
|
|
||||||
private static final String TAG = SaveAsyncTask.class.getSimpleName();
|
private static final String TAG = SaveAsyncTask.class.getSimpleName();
|
||||||
@@ -144,7 +145,7 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves tracks to one file.
|
* Saves tracks to one file (uses first track to determine the filename).
|
||||||
*
|
*
|
||||||
* @param tracks the tracks
|
* @param tracks the tracks
|
||||||
*/
|
*/
|
||||||
@@ -153,7 +154,6 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Track track = tracks[0];
|
|
||||||
FileTrackExporter fileTrackExporter = new FileTrackExporter(contentProviderUtils, tracks,
|
FileTrackExporter fileTrackExporter = new FileTrackExporter(contentProviderUtils, tracks,
|
||||||
trackFileFormat.newTrackWriter(context, tracks.length > 1),
|
trackFileFormat.newTrackWriter(context, tracks.length > 1),
|
||||||
new TrackExporterListener() {
|
new TrackExporterListener() {
|
||||||
@@ -169,6 +169,7 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|||||||
String extension = useKmz ? KmzTrackExporter.KMZ_EXTENSION : trackFileFormat.getExtension();
|
String extension = useKmz ? KmzTrackExporter.KMZ_EXTENSION : trackFileFormat.getExtension();
|
||||||
TrackExporter trackExporter = useKmz ? new KmzTrackExporter(contentProviderUtils, fileTrackExporter, tracks) : fileTrackExporter;
|
TrackExporter trackExporter = useKmz ? new KmzTrackExporter(contentProviderUtils, fileTrackExporter, tracks) : fileTrackExporter;
|
||||||
|
|
||||||
|
Track track = tracks[0];
|
||||||
String fileName = FileUtils.buildUniqueFileName(directory, track.getName(), extension);
|
String fileName = FileUtils.buildUniqueFileName(directory, track.getName(), extension);
|
||||||
File file = new File(directory, fileName);
|
File file = new File(directory, fileName);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user