diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java index a2c98c4c4..f9ceac3ad 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -1,9 +1,15 @@ package de.dennisguse.opentracks.content.data; +import android.content.Context; import android.location.Location; +import android.net.Uri; import android.util.Pair; +import java.io.File; +import java.io.IOException; + import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.util.FileUtils; public class TestDataUtil { @@ -73,4 +79,26 @@ public class TestDataUtil { contentProviderUtils.insertTrack(track); contentProviderUtils.bulkInsertTrackPoint(trackPoints, track.getId()); } + + /** + * Creates a Waypoint with a photo. + * + * @param context The context. + * @param trackId The track id. + * @param location The location. + * @return the Waypoint created. + */ + public static Waypoint createWaypointWithPhoto(Context context, long trackId, Location location) throws IOException { + String photoUrl = ""; + try { + File dstFile = new File(FileUtils.getImageUrl(context, trackId)); + dstFile.createNewFile(); + Uri photoUri = FileUtils.getUriForFile(context, dstFile); + photoUrl = photoUri.toString(); + } catch (IOException ioe) { + throw ioe; + } + + return new Waypoint("Waypoint name", "Waypoint description", "Waypoint category", "", trackId, 0.0, 0, location, photoUrl); + } } diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java index 930af3470..b88c70053 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java @@ -32,6 +32,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -44,6 +46,7 @@ import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.data.WaypointsColumns; import de.dennisguse.opentracks.stats.TrackStatistics; +import de.dennisguse.opentracks.util.FileUtils; import static org.mockito.Mockito.when; @@ -219,6 +222,44 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(0, waypointCursor.getCount()); } + /** + * Tests the method {@link ContentProviderUtils#deleteAllTracks(Context)} + */ + @Test + public void testDeleteAllTracks_withWaypointAndPhoto() throws IOException { + // Insert track, points and waypoint with photo at first. + long trackId = System.currentTimeMillis(); + Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); + + TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId); + Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation()); + contentProviderUtils.insertWaypoint(waypoint); + + ContentResolver contentResolver = context.getContentResolver(); + Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); + Assert.assertEquals(1, tracksCursor.getCount()); + Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI_BY_ID, null, null, null, TrackPointsColumns._ID); + Assert.assertEquals(10, tracksPointsCursor.getCount()); + Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); + Assert.assertEquals(1, waypointCursor.getCount()); + // Check waypoint has photo and it's in the external storage. + Assert.assertTrue(waypoint.hasPhoto()); + File dir = FileUtils.getPhotoDir(context, trackId); + Assert.assertTrue(dir.isDirectory()); + Assert.assertEquals(1, dir.list().length); + Assert.assertTrue(dir.exists()); + // Delete all. + contentProviderUtils.deleteAllTracks(context); + // Check whether all have been deleted. + tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); + Assert.assertEquals(0, tracksCursor.getCount()); + tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI_BY_ID, null, null, null, TrackPointsColumns._ID); + Assert.assertEquals(0, tracksPointsCursor.getCount()); + waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); + Assert.assertEquals(0, waypointCursor.getCount()); + Assert.assertFalse(dir.exists()); + } + /** * Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}. */ @@ -254,6 +295,56 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(0, waypointCursor.getCount()); } + /** + * Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}. + */ + @Test + public void testDeleteTrack_withWaypointPhoto() throws IOException { + // Insert three tracks. + long trackId = System.currentTimeMillis(); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10); + + // Insert a waypoint in tracks trackId and trackId + 1. + TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId); + Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint1.getLocation()); + contentProviderUtils.insertWaypoint(waypoint1); + File dir1 = FileUtils.getPhotoDir(context, trackId); + + TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId + 1); + Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId + 1, trackPoint2.getLocation()); + contentProviderUtils.insertWaypoint(waypoint2); + File dir2 = FileUtils.getPhotoDir(context, trackId + 1); + + // Check. + ContentResolver contentResolver = context.getContentResolver(); + Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); + Assert.assertEquals(3, tracksCursor.getCount()); + Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI_BY_ID, null, null, null, TrackPointsColumns._ID); + Assert.assertEquals(30, tracksPointsCursor.getCount()); + Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); + Assert.assertEquals(2, waypointCursor.getCount()); + Assert.assertTrue(waypoint1.hasPhoto()); + Assert.assertTrue(dir1.isDirectory()); + Assert.assertEquals(1, dir1.list().length); + Assert.assertTrue(dir1.exists()); + Assert.assertTrue(dir2.isDirectory()); + Assert.assertEquals(1, dir2.list().length); + Assert.assertTrue(dir2.exists()); + // Delete one track. + contentProviderUtils.deleteTrack(context, trackId); + // Check whether all data of a track has been deleted. + tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); + Assert.assertEquals(2, tracksCursor.getCount()); + tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI_BY_ID, null, null, null, TrackPointsColumns._ID); + Assert.assertEquals(20, tracksPointsCursor.getCount()); + waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); + Assert.assertEquals(1, waypointCursor.getCount()); + Assert.assertFalse(dir1.exists()); + Assert.assertTrue(dir2.exists()); + } + /** * Tests the method {@link ContentProviderUtils#getAllTracks()} */ @@ -387,7 +478,7 @@ public class CustomContentProviderUtilsTest { /** * Tests the method - * {@link ContentProviderUtils#deleteWaypoint(long)} + * {@link ContentProviderUtils#deleteWaypoint(Context, long)} * when there is only one waypoint in the track. */ @Test @@ -401,14 +492,56 @@ public class CustomContentProviderUtilsTest { waypoint1.setTrackId(trackId); contentProviderUtils.insertWaypoint(waypoint1); - // Delete - contentProviderUtils.deleteWaypoint(1); + // Check insert was done. + Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1); - Assert.assertNull(contentProviderUtils.getWaypoint(1)); + // Get waypoint id that needs to delete. + long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)); + + // Delete + contentProviderUtils.deleteWaypoint(context, waypoint1Id); + + Assert.assertNull(contentProviderUtils.getWaypoint(waypoint1Id)); } /** - * Tests the method {@link ContentProviderUtils#deleteWaypoint(long)} when there is more than one waypoint in the track. + * Tests the method + * {@link ContentProviderUtils#deleteWaypoint(Context, long)} + * when there is only one waypoint in the track. + */ + @Test + public void testDeleteWaypoint_onlyOneWayPointWithPhotoUrl() throws IOException { + long trackId = System.currentTimeMillis(); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); + + // Insert at first. + TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId); + Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation()); + contentProviderUtils.insertWaypoint(waypoint1); + + // Check insert was done. + Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1); + + // Get waypoint id that needs to delete. + long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)); + + // Check waypoint has photo and it's in the external storage. + Assert.assertTrue(waypoint1.hasPhoto()); + File dir = FileUtils.getPhotoDir(context, trackId); + Assert.assertTrue(dir.isDirectory()); + Assert.assertEquals(1, dir.list().length); + Assert.assertTrue(dir.exists()); + + // Delete + contentProviderUtils.deleteWaypoint(context, waypoint1Id); + + // Check waypoint doesn't exists and photo folder was deleted. + Assert.assertNull(contentProviderUtils.getWaypoint(waypoint1Id)); + Assert.assertFalse(dir.exists()); + } + + /** + * Tests the method {@link ContentProviderUtils#deleteWaypoint(Context, long)} when there is more than one waypoint in the track. */ @Test public void testDeleteWaypoint_hasNextWayPoint() { @@ -444,7 +577,7 @@ public class CustomContentProviderUtilsTest { // Delete Assert.assertNotNull(contentProviderUtils.getWaypoint(waypoint1Id)); - contentProviderUtils.deleteWaypoint(waypoint1Id); + contentProviderUtils.deleteWaypoint(context, waypoint1Id); Assert.assertNull(contentProviderUtils.getWaypoint(waypoint1Id)); Assert.assertEquals(MOCK_DESC, contentProviderUtils.getWaypoint(waypoint2Id).getDescription()); diff --git a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java index 53a054881..dbfc1f0ab 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java @@ -170,7 +170,7 @@ public class ContentProviderUtils { contentResolver.delete(TracksColumns.CONTENT_URI, null, null); File dir = FileUtils.getPhotoDir(context); - deleteDirectoryRecurse(dir); + FileUtils.deleteDirectoryRecurse(dir); } /** @@ -181,6 +181,9 @@ public class ContentProviderUtils { public void deleteTrack(Context context, long trackId) { deleteTrackPointsAndWaypoints(context, trackId); + // Delete track folder resources. + FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId)); + // Delete track last since it triggers a database vacuum call contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId)}); } @@ -196,21 +199,6 @@ public class ContentProviderUtils { contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, where, selectionArgs); contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", new String[]{Long.toString(trackId)}); - deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId)); - } - - /** - * Delete the directory recursively. - * - * @param dir the directory - */ - private void deleteDirectoryRecurse(File dir) { - if (dir != null && dir.exists() && dir.isDirectory()) { - for (File child : dir.listFiles()) { - deleteDirectoryRecurse(child); - } - dir.delete(); - } } /** @@ -392,11 +380,11 @@ public class ContentProviderUtils { return waypoint; } - public void deleteWaypoint(long waypointId) { + public void deleteWaypoint(Context context, long waypointId) { final Waypoint waypoint = getWaypoint(waypointId); if (waypoint != null && waypoint.hasPhoto()) { Uri uri = waypoint.getPhotoURI(); - File file = new File(uri.getPath()); + File file = FileUtils.getPhotoFileIfExists(context, waypoint.getTrackId(), uri); if (file.exists()) { File parent = file.getParentFile(); file.delete(); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java index 139e36497..3de0ec2c2 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java @@ -85,7 +85,7 @@ public class DeleteMarkerDialogFragment extends DialogFragment { public void run() { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(fragmentActivity); for (long markerId : markerIds) { - contentProviderUtils.deleteWaypoint(markerId); + contentProviderUtils.deleteWaypoint(getContext(), markerId); } caller.onDeleteMarkerDone(); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java index beda05523..b604c25c1 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java @@ -189,7 +189,6 @@ public class KmzTrackImporter implements TrackImporter { zipInputStream.closeEntry(); } - return trackId; } catch (IOException e) { Log.e(TAG, "Unable to import file", e); @@ -241,16 +240,6 @@ public class KmzTrackImporter implements TrackImporter { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); contentProviderUtils.deleteTrack(context, trackId); } - - if (importTrackId != -1L) { - File dir = FileUtils.getPhotoDir(context, importTrackId); - if (dir.exists() && dir.isDirectory()) { - for (File file : dir.listFiles()) { - file.delete(); - } - dir.delete(); - } - } } /** diff --git a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java index 3a609b247..ea50a8648 100644 --- a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java @@ -284,4 +284,20 @@ public class FileUtils { return file; } + + /** + * Delete the directory recursively. + * + * @param file the directory + */ + public static void deleteDirectoryRecurse(File file) { + if (file != null && file.exists() && file.isDirectory()) { + for (File child : file.listFiles()) { + deleteDirectoryRecurse(child); + } + file.delete(); + } else if (file != null && file.isFile()) { + file.delete(); + } + } }