From 9c938b12607a599917f711f249bb17184b5cf50c Mon Sep 17 00:00:00 2001 From: Jimmy Shih Date: Thu, 3 Oct 2013 18:04:17 -0700 Subject: [PATCH] Store photos in /MyTracks/pictures directory --- .../apps/mytracks/TrackDetailActivity.java | 11 ++-- .../importer/AbstractFileTrackImporter.java | 14 +++++ .../io/file/importer/ImportAsyncTask.java | 19 ++++--- .../file/importer/KmlFileTrackImporter.java | 15 +++--- .../io/file/importer/KmzTrackImporter.java | 53 ++++++++++++------- .../android/apps/mytracks/util/FileUtils.java | 10 ++-- .../importer/KmlFileTrackImporterTest.java | 11 ++-- 7 files changed, 79 insertions(+), 54 deletions(-) diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java b/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java index 88d44942e..921058242 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java @@ -51,7 +51,6 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.os.Parcelable; import android.provider.MediaStore; import android.support.v4.app.TaskStackBuilder; @@ -216,8 +215,10 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity implements protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA); - photoUri = savedInstanceState != null ? (Uri) savedInstanceState.getParcelable(PHOTO_URI_KEY) : null; - hasPhoto = savedInstanceState != null ? savedInstanceState.getBoolean(HAS_PHOTO_KEY, false) : false; + photoUri = savedInstanceState != null ? (Uri) savedInstanceState.getParcelable(PHOTO_URI_KEY) + : null; + hasPhoto = savedInstanceState != null ? savedInstanceState.getBoolean(HAS_PHOTO_KEY, false) + : false; myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this); handleIntent(getIntent()); @@ -397,9 +398,7 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity implements } File dir = new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), - FileUtils.SDCARD_TOP_DIR); - + FileUtils.getDirectoryPath(FileUtils.PICTURES_DIR, Long.toString(trackId))); FileUtils.ensureDirectoryExists(dir); String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/AbstractFileTrackImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/AbstractFileTrackImporter.java index ea31f87f5..cbb30f099 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/AbstractFileTrackImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/AbstractFileTrackImporter.java @@ -25,6 +25,7 @@ import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.services.TrackRecordingService; import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatisticsUpdater; +import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.apps.mytracks.util.StringUtils; @@ -461,6 +462,19 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track locator.getLineNumber(), locator.getColumnNumber(), message); } + /** + * Gets the photo url for a file. + * + * @param fileName the file name + */ + protected String getPhotoUrl(String fileName) { + if (importTrackId == -1L) { + return null; + } + return FileUtils.getDirectoryPath( + FileUtils.PICTURES_DIR, Long.toString(importTrackId), fileName); + } + /** * Creates a location. */ diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/ImportAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/ImportAsyncTask.java index f2025e474..56178ab03 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/ImportAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/ImportAsyncTask.java @@ -16,16 +16,17 @@ package com.google.android.apps.mytracks.io.file.importer; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.io.file.TrackFileFormat; import com.google.android.apps.mytracks.io.file.exporter.KmzTrackExporter; -import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.apps.mytracks.util.SystemUtils; import com.google.android.maps.mytracks.R; import android.content.Context; +import android.net.Uri; import android.os.AsyncTask; -import android.os.Environment; import android.os.PowerManager.WakeLock; import android.util.Log; @@ -179,14 +180,12 @@ public class ImportAsyncTask extends AsyncTask { String name = file.getName(); if (name.endsWith("." + TrackFileFormat.KML.getExtension())) { trackImporter = new KmlFileTrackImporter(context, -1L, null); - } else { - File dir = new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), - FileUtils.SDCARD_TOP_DIR); - FileUtils.ensureDirectoryExists(dir); - dir = new File(dir, name.substring(0, name.lastIndexOf('.'))); - FileUtils.ensureDirectoryExists(dir); - trackImporter = new KmzTrackImporter(context, dir.getPath()); + } else { + MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context); + Uri uri = myTracksProviderUtils.insertTrack(new Track()); + long newId = Long.parseLong(uri.getLastPathSegment()); + + trackImporter = new KmzTrackImporter(context, newId); } } else { trackImporter = new GpxFileTrackImporter(context); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporter.java index 1ecd81212..d143a0941 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporter.java @@ -27,7 +27,6 @@ import android.content.Context; import android.location.Location; import android.net.Uri; -import java.io.File; import java.util.ArrayList; import org.xml.sax.Attributes; @@ -65,7 +64,6 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { private static final String ATTRIBUTE_NAME = "name"; - private final String photoPath; private boolean trackStarted = false; private String sensorName; private ArrayList locationList; @@ -79,15 +77,14 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { * @param context the context * @param importTrackId track id to import to. -1L to import to a new track. */ - public KmlFileTrackImporter(Context context, long importTrackId, String photoPath) { - this(context, importTrackId, photoPath, MyTracksProviderUtils.Factory.get(context)); + public KmlFileTrackImporter(Context context, long importTrackId) { + this(context, importTrackId, MyTracksProviderUtils.Factory.get(context)); } @VisibleForTesting - public KmlFileTrackImporter(Context context, long importTrackId, String photoPath, - MyTracksProviderUtils myTracksProviderUtils) { + public KmlFileTrackImporter( + Context context, long importTrackId, MyTracksProviderUtils myTracksProviderUtils) { super(context, importTrackId, myTracksProviderUtils); - this.photoPath = photoPath; } @Override @@ -184,9 +181,9 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { if (type == null) { return; } - if (photoUrl != null && photoPath != null) { + if (photoUrl != null) { Uri uri = Uri.parse(photoUrl); - photoUrl = photoPath + File.separatorChar + uri.getLastPathSegment(); + photoUrl = getPhotoUrl(uri.getLastPathSegment()); } addWaypoint(type); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmzTrackImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmzTrackImporter.java index 575b51805..726ae8f2a 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmzTrackImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/importer/KmzTrackImporter.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.io.file.importer; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.io.file.exporter.KmzTrackExporter; +import com.google.android.apps.mytracks.util.FileUtils; import android.content.Context; import android.util.Log; @@ -42,17 +43,24 @@ public class KmzTrackImporter implements TrackImporter { private static final int BUFFER_SIZE = 4096; private final Context context; - private final String photoPath; + private final long importTrackId; - public KmzTrackImporter(Context context, String photoPath) { + /** + * Constructor. + * + * @param context the context + * @param importTrackId track id to import to. This should not be -1L so that + * images in the kmz file can be imported. + */ + public KmzTrackImporter(Context context, long importTrackId) { this.context = context; - this.photoPath = photoPath; + this.importTrackId = importTrackId; } @Override public long importFile(InputStream inputStream) { ZipInputStream zipInputStream = null; - long importedTrackId = -1L; + long trackId = importTrackId; try { ZipEntry zipEntry; @@ -60,15 +68,15 @@ public class KmzTrackImporter implements TrackImporter { while ((zipEntry = zipInputStream.getNextEntry()) != null) { if (Thread.interrupted()) { Log.d(TAG, "Thread interrupted"); - cleanImport(importedTrackId); + cleanImport(trackId); return -1L; } String fileName = zipEntry.getName(); if (fileName.equals(KmzTrackExporter.KMZ_KML_FILE)) { - importedTrackId = parseKml(zipInputStream); - if (importedTrackId == -1L) { + trackId = parseKml(zipInputStream); + if (trackId == -1L) { Log.d(TAG, "Unable to parse kml in kmz"); - cleanImport(importedTrackId); + cleanImport(trackId); return -1L; } } else { @@ -79,10 +87,10 @@ public class KmzTrackImporter implements TrackImporter { } zipInputStream.closeEntry(); } - return importedTrackId; + return trackId; } catch (IOException e) { Log.e(TAG, "Unable to import file", e); - cleanImport(importedTrackId); + cleanImport(trackId); return -1L; } finally { if (zipInputStream != null) { @@ -98,15 +106,17 @@ public class KmzTrackImporter implements TrackImporter { /** * Cleans up import. * - * @param importedTrackId the imported track id + * @param trackId the trackId */ - private void cleanImport(long importedTrackId) { - if (importedTrackId != -1L) { + private void cleanImport(long trackId) { + if (trackId != -1L) { MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context); - myTracksProviderUtils.deleteTrack(importedTrackId); + myTracksProviderUtils.deleteTrack(trackId); } - if (photoPath != null) { - File dir = new File(photoPath); + + if (importTrackId != -1L) { + File dir = new File( + FileUtils.getDirectoryPath(FileUtils.PICTURES_DIR, Long.toString(importTrackId))); if (dir.exists() && dir.isDirectory()) { for (File file : dir.listFiles()) { file.delete(); @@ -125,7 +135,7 @@ public class KmzTrackImporter implements TrackImporter { private long parseKml(ZipInputStream zipInputStream) throws IOException { ByteArrayInputStream byteArrayInputStream = null; try { - KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, -1L, photoPath); + KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, importTrackId); byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream)); return kmlFileTrackImporter.importFile(byteArrayInputStream); } finally { @@ -166,7 +176,14 @@ public class KmzTrackImporter implements TrackImporter { private void readImageFile(ZipInputStream zipInputStream, String fileName) throws IOException { FileOutputStream fileOutputStream = null; try { - fileOutputStream = new FileOutputStream(photoPath + File.separatorChar + fileName); + if (importTrackId == -1L) { + return; + } + File dir = new File( + FileUtils.getDirectoryPath(FileUtils.PICTURES_DIR, Long.toString(importTrackId))); + FileUtils.ensureDirectoryExists(dir); + + fileOutputStream = new FileOutputStream(new File(dir, fileName)); byte[] buffer = new byte[BUFFER_SIZE]; int count; while ((count = zipInputStream.read(buffer)) != -1) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java index 023e6e579..91176ab89 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java @@ -30,14 +30,16 @@ public class FileUtils { private FileUtils() {} - public static final String BACKUPS_DIR = "backups"; - /** * Name of the top-level directory inside the SD card where our files will be * read from/written to. */ - public static final String SDCARD_TOP_DIR = "MyTracks"; - + protected static final String SDCARD_TOP_DIR = "MyTracks"; + + public static final String BACKUPS_DIR = "backups"; + + public static final String PICTURES_DIR = "pictures"; + /** * The maximum FAT32 path length. See the FAT32 spec at * http://msdn.microsoft.com/en-us/windows/hardware/gg463080 diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java index 6fe256e09..358d84316 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java @@ -20,7 +20,6 @@ import static com.google.android.testing.mocking.AndroidMock.eq; import static com.google.android.testing.mocking.AndroidMock.expect; import com.google.android.apps.mytracks.content.Track; -import com.google.android.apps.mytracks.io.file.importer.KmlFileTrackImporter; import com.google.android.testing.mocking.AndroidMock; import android.location.Location; @@ -73,8 +72,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime()); - expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) - .andReturn(TRACK_ID_0_URI); + myTracksProviderUtils.clearTrack(TRACK_ID_0); expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); // A flush happens at the end @@ -87,7 +85,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes()); KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter( - getContext(), -1L, null, myTracksProviderUtils); + getContext(), TRACK_ID_0, myTracksProviderUtils); long trackId = kmlFileTrackImporter.importFile(inputStream); assertEquals(TRACK_ID_0, trackId); @@ -106,8 +104,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); - expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) - .andReturn(TRACK_ID_0_URI); + myTracksProviderUtils.clearTrack(TRACK_ID_0); expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); // A flush happens at the end @@ -120,7 +117,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes()); KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter( - getContext(), -1L, null, myTracksProviderUtils); + getContext(), TRACK_ID_0, myTracksProviderUtils); long trackId = kmlFileTrackImporter.importFile(inputStream); assertEquals(TRACK_ID_0, trackId);