diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportToStorageTask.java index db4ada733..bd6cad067 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; + } } diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportToTempFileTask.java index 7c3521626..ca5108c11 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,65 @@ 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; + + // 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), pro, 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 +109,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 +134,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); diff --git a/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java b/src/me/guillaumin/android/osmtracker/gpx/ExportTrackTask.java index a3c2314de..8474836ba 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