From ce3f32472e3f81ebaed6ff2fc73c05e0509e9f01 Mon Sep 17 00:00:00 2001 From: Jeremy D Monin Date: Sun, 19 Aug 2012 11:56:24 -0400 Subject: [PATCH 1/4] ExportToStorageTask: static getExportDirectory for wider use; javadocs --- .../osmtracker/gpx/ExportToStorageTask.java | 72 +++++++++++++------ 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java index db4ada73..bd6cad06 100644 --- a/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java +++ b/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java @@ -25,32 +25,21 @@ public ExportToStorageTask(Context context, long trackId) { super(context, trackId); } + /** + * Calculate a track's export directory, and create if it doesn't exist already. + * @param startDate The track's starting date, from + * {@link me.guillaumin.android.osmtracker.db.TrackContentProvider.Schema#COL_START_DATE Schema.COL_START_DATE} + * @return The export directory + * @throws ExportTrackException if the directory can't be created + * @see #getExportDirectory(Context, Date) + */ @Override protected File getExportDirectory(Date startDate) throws ExportTrackException { File sdRoot = Environment.getExternalStorageDirectory(); - - // The location that the user has specified gpx files - // and associated content to be written - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - String userGPXExportDirectoryName = prefs.getString( - OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR); - - boolean directoryPerTrack = prefs.getBoolean(OSMTracker.Preferences.KEY_OUTPUT_DIR_PER_TRACK, - OSMTracker.Preferences.VAL_OUTPUT_GPX_OUTPUT_DIR_PER_TRACK); - - // Create the path to the directory to which we will be writing - // Trim the directory name, as additional spaces at the end will - // not allow the directory to be created if required - String exportDirectoryPath = userGPXExportDirectoryName.trim(); - String perTrackDirectory = ""; - if (directoryPerTrack) { - // If the user wants a directory per track, then create a name for the destination directory - // based on the start date of the track - perTrackDirectory = File.separator + DataHelper.FILENAME_FORMATTER.format(startDate); - } + final String exportDirectoryPath = getExportDirectory(context, startDate); // Create a file based on the path we've generated above - File trackGPXExportDirectory = new File(sdRoot + exportDirectoryPath + perTrackDirectory); + File trackGPXExportDirectory = new File(sdRoot + exportDirectoryPath); // Create track directory if needed if (! trackGPXExportDirectory.exists()) { @@ -63,7 +52,7 @@ protected File getExportDirectory(Date startDate) throws ExportTrackException { // Specific hack for Google Nexus S(See issue #168) if (android.os.Build.MODEL.equals(OSMTracker.Devices.NEXUS_S)) { // exportDirectoryPath always starts with "/" - trackGPXExportDirectory = new File(exportDirectoryPath + perTrackDirectory); + trackGPXExportDirectory = new File(exportDirectoryPath); trackGPXExportDirectory.mkdirs(); } } @@ -86,4 +75,43 @@ protected boolean exportMediaFiles() { protected boolean updateExportDate() { return true; } + + /** + *

Calculate a track's export directory path. Does not create the directory if missing.

+ * + *

The returned directory is relative to sdRoot because of bug #168 + * mentioned in {@link #getExportDirectory(Date)}. If you can't find the + * returned directory at sdRoot + directory, try just directory.

+ * + * @param context Calling activity context, for {@link PreferenceManager#getDefaultSharedPreferences(Context)} + * @param startDate The track's starting date, from + * {@link me.guillaumin.android.osmtracker.db.TrackContentProvider.Schema#COL_START_DATE Schema.COL_START_DATE} + * @return track export directory name within sdcard; + * The full path to dirname is {@link Environment#getExternalStorageDirectory()} + dirname + * @see #getExportDirectory(Date) + */ + public static String getExportDirectory(Context context, Date startDate) { + + // The location that the user has specified gpx files + // and associated content to be written + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String userGPXExportDirectoryName = prefs.getString( + OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR); + + boolean directoryPerTrack = prefs.getBoolean(OSMTracker.Preferences.KEY_OUTPUT_DIR_PER_TRACK, + OSMTracker.Preferences.VAL_OUTPUT_GPX_OUTPUT_DIR_PER_TRACK); + + // Create the path to the directory to which we will be writing + // Trim the directory name, as additional spaces at the end will + // not allow the directory to be created if required + String exportDirectoryPath = userGPXExportDirectoryName.trim(); + String perTrackDirectory = ""; + if (directoryPerTrack) { + // If the user wants a directory per track, then create a name for the destination directory + // based on the start date of the track + perTrackDirectory = File.separator + DataHelper.FILENAME_FORMATTER.format(startDate); + } + + return exportDirectoryPath + perTrackDirectory; + } } From ee098b0e64386e95515b32a2e8f26e872829cc25 Mon Sep 17 00:00:00 2001 From: Jeremy D Monin Date: Sun, 19 Aug 2012 11:57:03 -0400 Subject: [PATCH 2/4] ExportTrackTask: make trackFile protected for ExportToTempFileTask; javadocs --- .../android/osmtracker/gpx/ExportTrackTask.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java index a3c2314d..8474836b 100644 --- a/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java +++ b/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java @@ -88,7 +88,7 @@ public abstract class ExportTrackTask extends AsyncTask /** * Path to the exported GPX file */ - private File trackFile; + protected File trackFile; /** * Dialog to display while exporting @@ -138,7 +138,11 @@ protected void onPreExecute() { dialog.show(); } - + /** + * Export the track to a new GPX file. + * Calls {@link #exportTrackAsGpx(long)} which sets {@link #trackFile} to the file. + * If any error occurs, sets {@link #errorMsg}. + */ @Override protected Boolean doInBackground(Void... params) { try { @@ -180,6 +184,11 @@ public void onClick(DialogInterface dialog, int which) { } } + /** + * Export the track to a new GPX file. Sets {@link #trackFile} to the file. + * @param trackId Track ID + * @throws ExportTrackException if any error occurs during export + */ private void exportTrackAsGpx(long trackId) throws ExportTrackException { File sdRoot = Environment.getExternalStorageDirectory(); From d4cd9a1fd76f741ded441d82536c9f9ba52079d3 Mon Sep 17 00:00:00 2001 From: Jeremy D Monin Date: Sun, 19 Aug 2012 11:59:04 -0400 Subject: [PATCH 3/4] ExportToTempFileTask: If track already exported, try to re-use that file --- .../osmtracker/gpx/ExportToTempFileTask.java | 86 ++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java index 7c352162..a36f2dc7 100644 --- a/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java +++ b/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java @@ -4,25 +4,36 @@ import java.io.IOException; import java.util.Date; +import me.guillaumin.android.osmtracker.db.TrackContentProvider; +import me.guillaumin.android.osmtracker.db.TrackContentProvider.Schema; import me.guillaumin.android.osmtracker.exception.ExportTrackException; +import android.content.ContentUris; import android.content.Context; import android.database.Cursor; +import android.os.Environment; import android.util.Log; /** * Exports to a temporary file. Will not export associated * media, only the GPX file. + * If this track has already been exported, tries to find and re-use that file. * */ public abstract class ExportToTempFileTask extends ExportTrackTask { private static final String TAG = ExportToTempFileTask.class.getSimpleName(); - private final File tmpFile; + /** Temp file created in constructor, or actual export file if found */ + private File tmpFile; private String filename; + /** True if a previous export file was found */ + private boolean reusedRealExport = false; public ExportToTempFileTask(Context context, long trackId) { super(context, trackId); + tmpFile = checkForExportFile(); + if (tmpFile != null) + return; try { tmpFile = File.createTempFile("osm-upload", ".gpx", context.getCacheDir()); Log.d(TAG, "Temporary file: " + tmpFile.getAbsolutePath()); @@ -32,7 +43,63 @@ public ExportToTempFileTask(Context context, long trackId) { } } - + /** + * Checks whether this file's already been exported, based on the track + * db and our naming conventions. If so, we can reuse that GPX file, + * instead of creating a new temporary one. + * Sets {@link #reusedRealExport} but does not set {@link #tmpFile}. + * @return Export file if it exists + */ + private File checkForExportFile() { + reusedRealExport = false; + + Cursor c = context.getContentResolver().query(ContentUris.withAppendedId( + TrackContentProvider.CONTENT_URI_TRACK, trackId), null, null, + null, null); + if (null == c) + return null; // <--- Early return: could not query --- + + // Get the exportDate and startDate of this track + Date exportDate = null, startDate = null; + if (1 <= c.getCount()) { + c.moveToFirst(); + final int eidx = c.getColumnIndex(Schema.COL_EXPORT_DATE); + if (! c.isNull(eidx)) + { + exportDate = new Date(); + exportDate.setTime(c.getLong(eidx)); + startDate = new Date(); + startDate.setTime(c.getLong(c.getColumnIndex(Schema.COL_START_DATE))); + } + } + + if (exportDate == null) { + c.close(); + return null; // <--- Early return: Not exported --- + } + + final String exportDirectoryPath = ExportToStorageTask.getExportDirectory(context, startDate); + final File sdRoot = Environment.getExternalStorageDirectory(); + File expDir = new File(sdRoot + exportDirectoryPath); + if (! expDir.exists()) + expDir = new File(exportDirectoryPath); // Specific hack for Google Nexus S (See issue #168) + if (! expDir.exists()) { + c.close(); + return null; // <--- Early return: Export dir doesn't exist --- + } + + // Export dir exists. Does the GPX file exist with the expected name? + final String filenameBase = super.buildGPXFilename(c); + c.close(); + File f = new File(expDir, filenameBase); + if (f.exists()) { + reusedRealExport = true; + return f; + } else { + return null; + } + } + @Override protected File getExportDirectory(Date startDate) throws ExportTrackException { return tmpFile.getParentFile(); @@ -40,7 +107,10 @@ protected File getExportDirectory(Date startDate) throws ExportTrackException { @Override protected String buildGPXFilename(Cursor c) { - filename = super.buildGPXFilename(c); + if (reusedRealExport) + filename = tmpFile.getName(); + else + filename = super.buildGPXFilename(c); return tmpFile.getName(); } @@ -62,6 +132,16 @@ public String getFilename() { return filename; } + @Override + protected Boolean doInBackground(Void... params) { + if (reusedRealExport) { + trackFile = tmpFile; + return true; + } else { + return super.doInBackground(params); + } + } + @Override protected void onPostExecute(Boolean success) { super.onPostExecute(success); From 3639a2b64d044db9243c59a9036c495f3156bd12 Mon Sep 17 00:00:00 2001 From: Jeremy D Monin Date: Sun, 19 Aug 2012 12:08:10 -0400 Subject: [PATCH 4/4] ExportToTempFileTask: fewer columns in query --- .../android/osmtracker/gpx/ExportToTempFileTask.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java index a36f2dc7..ca5108c1 100644 --- a/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java +++ b/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java @@ -53,8 +53,10 @@ public ExportToTempFileTask(Context context, long trackId) { private File checkForExportFile() { reusedRealExport = false; + // Query the track columns needed by this method and buildGPXFilename + final String[] pro = { Schema.COL_EXPORT_DATE, Schema.COL_START_DATE, Schema.COL_NAME }; Cursor c = context.getContentResolver().query(ContentUris.withAppendedId( - TrackContentProvider.CONTENT_URI_TRACK, trackId), null, null, + TrackContentProvider.CONTENT_URI_TRACK, trackId), pro, null, null, null); if (null == c) return null; // <--- Early return: could not query ---