diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java index e8a24c9af..29a964a87 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java @@ -74,7 +74,7 @@ public class SearchEngineTest { InstrumentationRegistry.getInstrumentation().getTargetContext().deleteDatabase(TAG + CustomSQLiteOpenHelper.DATABASE_NAME); } - private long insertTrack(String title, String description, String category, long hoursAgo) { + private Track.Id insertTrack(String title, String description, String category, long hoursAgo) { Track track = new Track(); track.setName(title); track.setDescription(description); @@ -88,18 +88,18 @@ public class SearchEngineTest { } Uri uri = providerUtils.insertTrack(track); - return ContentUris.parseId(uri); + return new Track.Id(ContentUris.parseId(uri)); } - private long insertTrack(String title, String description, String category) { + private Track.Id insertTrack(String title, String description, String category) { return insertTrack(title, description, category, -1); } - private long insertTrack(String title, long hoursAgo) { + private Track.Id insertTrack(String title, long hoursAgo) { return insertTrack(title, "", "", hoursAgo); } - private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) { + private Waypoint.Id insertWaypoint(String title, String description, String category, double distance, long hoursAgo, Track.Id trackId) { Location location = new Location(HERE); location.setLatitude(location.getLatitude() + distance); location.setLongitude(location.getLongitude() + distance); @@ -113,22 +113,22 @@ public class SearchEngineTest { waypoint.setTrackId(trackId); Uri uri = providerUtils.insertWaypoint(waypoint); - return ContentUris.parseId(uri); + return new Waypoint.Id(ContentUris.parseId(uri)); } - private long insertWaypoint(String title, String description, String category) { - return insertWaypoint(title, description, category, 0.0, -1, -1); + private Waypoint.Id insertWaypoint(String title, String description, String category) { + return insertWaypoint(title, description, category, 0.0, -1, null); } - private long insertWaypoint(String title, double distance) { - return insertWaypoint(title, "", "", distance, -1, -1); + private Waypoint.Id insertWaypoint(String title, double distance) { + return insertWaypoint(title, "", "", distance, -1, null); } - private long insertWaypoint(String title, long hoursAgo) { - return insertWaypoint(title, "", "", 0.0, hoursAgo, -1); + private Waypoint.Id insertWaypoint(String title, long hoursAgo) { + return insertWaypoint(title, "", "", 0.0, hoursAgo, null); } - private long insertWaypoint(String title, long hoursAgo, long trackId) { + private Waypoint.Id insertWaypoint(String title, long hoursAgo, Track.Id trackId) { return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId); } @@ -143,14 +143,14 @@ public class SearchEngineTest { // - one which will match in title and description // - one which will match in all fields insertTrack("bb", "cc", "dd"); - long descriptionMatchId = insertTrack("bb", "aa", "cc"); - long categoryMatchId = insertTrack("bb", "cc", "aa"); - long titleMatchId = insertTrack("aa", "bb", "cc"); - long titleCategoryMatchId = insertTrack("aa", "bb", "ca"); - long titleDescriptionMatchId = insertTrack("aa", "ba", "cc"); - long allMatchId = insertTrack("aa", "ba", "ca"); + Track.Id descriptionMatchId = insertTrack("bb", "aa", "cc"); + Track.Id categoryMatchId = insertTrack("bb", "cc", "aa"); + Track.Id titleMatchId = insertTrack("aa", "bb", "cc"); + Track.Id titleCategoryMatchId = insertTrack("aa", "bb", "ca"); + Track.Id titleDescriptionMatchId = insertTrack("aa", "ba", "cc"); + Track.Id allMatchId = insertTrack("aa", "ba", "ca"); - SearchQuery query = new SearchQuery("a", null, -1, NOW); + SearchQuery query = new SearchQuery("a", null, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Title > Description > Category. @@ -168,14 +168,14 @@ public class SearchEngineTest { // - one which will match in title and description // - one which will match in all fields insertWaypoint("bb", "cc", "dd"); - long descriptionMatchId = insertWaypoint("bb", "aa", "cc"); - long categoryMatchId = insertWaypoint("bb", "cc", "aa"); - long titleMatchId = insertWaypoint("aa", "bb", "cc"); - long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca"); - long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc"); - long allMatchId = insertWaypoint("aa", "ba", "ca"); + Waypoint.Id descriptionMatchId = insertWaypoint("bb", "aa", "cc"); + Waypoint.Id categoryMatchId = insertWaypoint("bb", "cc", "aa"); + Waypoint.Id titleMatchId = insertWaypoint("aa", "bb", "cc"); + Waypoint.Id titleCategoryMatchId = insertWaypoint("aa", "bb", "ca"); + Waypoint.Id titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc"); + Waypoint.Id allMatchId = insertWaypoint("aa", "ba", "ca"); - SearchQuery query = new SearchQuery("a", null, -1, NOW); + SearchQuery query = new SearchQuery("a", null, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Title > Description > Category. @@ -190,13 +190,13 @@ public class SearchEngineTest { // - one waypoint which will match by title // - one track which won't match // - one track which will match by title - long descriptionWaypointId = insertWaypoint("bb", "aa", "cc"); + Waypoint.Id descriptionWaypointId = insertWaypoint("bb", "aa", "cc"); insertWaypoint("bb", "cc", "dd"); - long titleWaypointId = insertWaypoint("aa", "bb", "cc"); + Waypoint.Id titleWaypointId = insertWaypoint("aa", "bb", "cc"); insertTrack("bb", "cc", "dd"); - long trackId = insertTrack("aa", "bb", "cc"); + Track.Id trackId = insertTrack("aa", "bb", "cc"); - SearchQuery query = new SearchQuery("a", null, -1, NOW); + SearchQuery query = new SearchQuery("a", null, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Title > Description > Category. @@ -209,11 +209,11 @@ public class SearchEngineTest { @Test public void testSearchWaypointDistance() { // All results match text, but they're at difference distances from the user. - long farFarAwayId = insertWaypoint("aa", 0.3); - long nearId = insertWaypoint("ab", 0.1); - long farId = insertWaypoint("ac", 0.2); + Waypoint.Id farFarAwayId = insertWaypoint("aa", 0.3); + Waypoint.Id nearId = insertWaypoint("ab", 0.1); + Waypoint.Id farId = insertWaypoint("ac", 0.2); - SearchQuery query = new SearchQuery("a", HERE, -1, NOW); + SearchQuery query = new SearchQuery("a", HERE, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Distance order. @@ -222,11 +222,11 @@ public class SearchEngineTest { public void testSearchTrackRecent() { // All results match text, but they're were recorded at different times. - long oldestId = insertTrack("aa", 3); - long recentId = insertTrack("ab", 1); - long oldId = insertTrack("ac", 2); + Track.Id oldestId = insertTrack("aa", 3); + Track.Id recentId = insertTrack("ab", 1); + Track.Id oldId = insertTrack("ac", 2); - SearchQuery query = new SearchQuery("a", null, -1, NOW); + SearchQuery query = new SearchQuery("a", null, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Reverse time order. @@ -236,11 +236,11 @@ public class SearchEngineTest { @Test public void testSearchWaypointRecent() { // All results match text, but they're were recorded at different times. - long oldestId = insertWaypoint("aa", 2); - long recentId = insertWaypoint("ab", 0); - long oldId = insertWaypoint("ac", 1); + Waypoint.Id oldestId = insertWaypoint("aa", 2); + Waypoint.Id recentId = insertWaypoint("ab", 0); + Waypoint.Id oldId = insertWaypoint("ac", 1); - SearchQuery query = new SearchQuery("a", null, -1, NOW); + SearchQuery query = new SearchQuery("a", null, null, NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Reverse time order. @@ -250,8 +250,8 @@ public class SearchEngineTest { @Test public void testSearchCurrentTrack() { // All results match text, but one of them is the current track. - long currentId = insertTrack("ab", 1); - long otherId = insertTrack("aa", 1); + Track.Id currentId = insertTrack("ab", 1); + Track.Id otherId = insertTrack("aa", 1); SearchQuery query = new SearchQuery("a", null, currentId, NOW); ArrayList results = new ArrayList<>(engine.search(query)); @@ -263,23 +263,23 @@ public class SearchEngineTest { @Test public void testSearchCurrentTrackWaypoint() { // All results match text, but one of them is in the current track. - long otherId = insertWaypoint("aa", 1, 456); - long currentId = insertWaypoint("ab", 1, 123); + Waypoint.Id otherId = insertWaypoint("aa", 1, new Track.Id(456)); + Waypoint.Id currentId = insertWaypoint("ab", 1, new Track.Id(123)); - SearchQuery query = new SearchQuery("a", null, 123, NOW); + SearchQuery query = new SearchQuery("a", null, new Track.Id(123), NOW); ArrayList results = new ArrayList<>(engine.search(query)); // Waypoint in current track should be promoted. assertWaypointResults(results, currentId, otherId); } - private void assertTrackResult(long trackId, ScoredResult result) { + private void assertTrackResult(Track.Id trackId, ScoredResult result) { Assert.assertNotNull("Not a track", result.track); Assert.assertNull("Ambiguous result", result.waypoint); Assert.assertEquals(trackId, result.track.getId()); } - private void assertTrackResults(List results, long... trackIds) { + private void assertTrackResults(List results, Track.Id... trackIds) { String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results; Assert.assertEquals(results.size(), trackIds.length); for (int i = 0; i < results.size(); i++) { @@ -290,13 +290,13 @@ public class SearchEngineTest { } } - private void assertWaypointResult(long waypointId, ScoredResult result) { + private void assertWaypointResult(Waypoint.Id waypointId, ScoredResult result) { Assert.assertNotNull("Not a waypoint", result.waypoint); Assert.assertNull("Ambiguous result", result.track); Assert.assertEquals(waypointId, result.waypoint.getId()); } - private void assertWaypointResults(List results, long... waypointIds) { + private void assertWaypointResults(List results, Waypoint.Id... waypointIds) { String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results; Assert.assertEquals(results.size(), waypointIds.length); for (int i = 0; i < results.size(); i++) { 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 184790043..aa997c84f 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -20,7 +20,7 @@ public class TestDataUtil { /** * Create a track without any trackPoints. */ - public static Track createTrack(long trackId) { + public static Track createTrack(Track.Id trackId) { Track track = new Track(); track.setId(trackId); track.setName("Test: " + trackId); @@ -34,7 +34,7 @@ public class TestDataUtil { * @param trackId the trackId of the track * @param numPoints the trackPoints number in the track */ - public static Pair createTrack(long trackId, int numPoints) { + public static Pair createTrack(Track.Id trackId, int numPoints) { Track track = createTrack(trackId); TrackPoint[] trackPoints = new TrackPoint[numPoints]; @@ -45,7 +45,7 @@ public class TestDataUtil { return new Pair<>(track, trackPoints); } - public static Track createTrackAndInsert(ContentProviderUtils contentProviderUtils, long trackId, int numPoints) { + public static Track createTrackAndInsert(ContentProviderUtils contentProviderUtils, Track.Id trackId, int numPoints) { Pair pair = createTrack(trackId, numPoints); insertTrackWithLocations(contentProviderUtils, pair.first, pair.second); @@ -93,7 +93,7 @@ public class TestDataUtil { * @param location The location. * @return the Waypoint created. */ - public static Waypoint createWaypointWithPhoto(Context context, long trackId, Location location) throws IOException { + public static Waypoint createWaypointWithPhoto(Context context, Track.Id trackId, Location location) throws IOException { File dstFile = new File(FileUtils.getImageUrl(context, trackId)); dstFile.createNewFile(); Uri photoUri = FileUtils.getUriForFile(context, dstFile); 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 04f01122e..e7e01dbda 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java @@ -83,39 +83,39 @@ public class CustomContentProviderUtilsTest { @Test public void testLocationIterator_noPoints() { - testIterator(1, 0, 1, false); + testIterator(new Track.Id(1), 0, 1, false); } @Test public void testLocationIterator_noBatchAscending() { - testIterator(1, 50, 100, false); - testIterator(2, 50, 50, false); + testIterator(new Track.Id(1), 50, 100, false); + testIterator(new Track.Id(2), 50, 50, false); } @Test public void testLocationIterator_noBatchDescending() { - testIterator(1, 50, 100, true); - testIterator(2, 50, 50, true); + testIterator(new Track.Id(1), 50, 100, true); + testIterator(new Track.Id(2), 50, 50, true); } @Test public void testLocationIterator_batchAscending() { - testIterator(1, 50, 11, false); - testIterator(2, 50, 25, false); + testIterator(new Track.Id(1), 50, 11, false); + testIterator(new Track.Id(2), 50, 25, false); } @Test public void testLocationIterator_batchDescending() { - testIterator(1, 50, 11, true); - testIterator(2, 50, 25, true); + testIterator(new Track.Id(1), 50, 11, true); + testIterator(new Track.Id(2), 50, 25, true); } @Test public void testLocationIterator_largeTrack() { - testIterator(1, 20000, 2000, false); + testIterator(new Track.Id(1), 20000, 2000, false); } - private void testIterator(long trackId, int numPoints, int batchSize, boolean descending) { + private void testIterator(Track.Id trackId, int numPoints, int batchSize, boolean descending) { long lastPointId = initializeTrack(trackId, numPoints); contentProviderUtils.setDefaultCursorBatchSize(batchSize); List locations = new ArrayList<>(numPoints); @@ -132,7 +132,7 @@ public class CustomContentProviderUtilsTest { } } - private long initializeTrack(long id, int numPoints) { + private long initializeTrack(Track.Id id, int numPoints) { Track track = new Track(); track.setId(id); track.setName("Test: " + id); @@ -205,7 +205,7 @@ public class CustomContentProviderUtilsTest { @Test public void testDeleteAllTracks() { // Insert track, points and waypoint at first. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); @@ -235,7 +235,7 @@ public class CustomContentProviderUtilsTest { @Test public void testDeleteAllTracks_withWaypointAndPhoto() throws IOException { // Insert track, points and waypoint with photo at first. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId); @@ -268,20 +268,23 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}. + * Tests the method {@link ContentProviderUtils#deleteTrack(Context, Track.Id)}. */ @Test public void testDeleteTrack() { // Insert three tracks, points of two tracks and way point of one track. + long random = System.currentTimeMillis(); + Track.Id trackId1 = new Track.Id(random); + Track.Id trackId2 = new Track.Id(random + 1); + Track.Id trackId3 = new Track.Id(random + 2); - long trackId = System.currentTimeMillis(); - TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 0); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 0); - TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10); - TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10); - Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId + 1)); - waypoint.setTrackId(trackId); + Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId2)); + waypoint.setTrackId(trackId1); contentProviderUtils.insertWaypoint(waypoint); ContentResolver contentResolver = context.getContentResolver(); @@ -292,7 +295,7 @@ public class CustomContentProviderUtilsTest { Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); Assert.assertEquals(1, waypointCursor.getCount()); // Delete one track. - contentProviderUtils.deleteTrack(context, trackId); + contentProviderUtils.deleteTrack(context, trackId1); // 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()); @@ -303,26 +306,30 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}. + * Tests the method {@link ContentProviderUtils#deleteTrack(Context, Track.Id)}. */ @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); + long random = System.currentTimeMillis(); + Track.Id trackId1 = new Track.Id(random); + Track.Id trackId2 = new Track.Id(random + 1); + Track.Id trackId3 = new Track.Id(random + 2); + + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10); + TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10); // Insert a waypoint in tracks trackId and trackId + 1. - TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId); - Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint1.getLocation()); + TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId1); + Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId1, trackPoint1.getLocation()); contentProviderUtils.insertWaypoint(waypoint1); - File dir1 = FileUtils.getPhotoDir(context, trackId); + File dir1 = FileUtils.getPhotoDir(context, trackId1); - TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId + 1); - Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId + 1, trackPoint2.getLocation()); + TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId2); + Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId2, trackPoint2.getLocation()); contentProviderUtils.insertWaypoint(waypoint2); - File dir2 = FileUtils.getPhotoDir(context, trackId + 1); + File dir2 = FileUtils.getPhotoDir(context, trackId2); // Check. ContentResolver contentResolver = context.getContentResolver(); @@ -340,7 +347,7 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(1, dir2.list().length); Assert.assertTrue(dir2.exists()); // Delete one track. - contentProviderUtils.deleteTrack(context, trackId); + contentProviderUtils.deleteTrack(context, trackId1); // 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()); @@ -359,7 +366,7 @@ public class CustomContentProviderUtilsTest { public void testGetAllTracks() { // given int initialTrackNumber = contentProviderUtils.getAllTracks().size(); - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId)); // when @@ -375,18 +382,18 @@ public class CustomContentProviderUtilsTest { */ @Test public void testGetLastTrack() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId)); Assert.assertEquals(trackId, contentProviderUtils.getLastTrack().getId()); } /** - * Tests the method {@link ContentProviderUtils#getTrack(long)} + * Tests the method {@link ContentProviderUtils#getTrack(Track.Id)} */ @Test public void testGetTrack_by_id() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId)); // when / then @@ -394,12 +401,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getTrack(long)} + * Tests the method {@link ContentProviderUtils#getTrack(Track.Id)} */ @Test public void testGetTrack_by_uuid() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrack(trackId); contentProviderUtils.insertTrack(track); @@ -413,7 +420,7 @@ public class CustomContentProviderUtilsTest { @Test public void testUpdateTrack() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrack(trackId); String nameOld = "name1"; String nameNew = "name2"; @@ -432,7 +439,7 @@ public class CustomContentProviderUtilsTest { */ @Test public void testCreateContentValues_waypoint() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); // Bottom @@ -458,7 +465,7 @@ public class CustomContentProviderUtilsTest { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(contentResolverMock); - long waypointId = System.currentTimeMillis(); + Waypoint.Id waypointId = new Waypoint.Id(System.currentTimeMillis()); waypoint.setId(waypointId); ContentValues contentValues = contentProviderUtils.createContentValues(waypoint); Assert.assertEquals(waypointId, contentValues.get(WaypointsColumns._ID)); @@ -495,19 +502,19 @@ public class CustomContentProviderUtilsTest { when(cursorMock.getLong(columnIndex++)).thenReturn(trackId); Waypoint waypoint = contentProviderUtils.createWaypoint(cursorMock); - Assert.assertEquals(id, waypoint.getId()); + Assert.assertEquals(id, waypoint.getId().getId()); Assert.assertEquals(name, waypoint.getName()); - Assert.assertEquals(trackId, waypoint.getTrackId()); + Assert.assertEquals(trackId, waypoint.getTrackId().getId()); } /** * Tests the method - * {@link ContentProviderUtils#deleteWaypoint(Context, long)} + * {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)} * when there is only one waypoint in the track. */ @Test public void testDeleteWaypoint_onlyOneWayPoint() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. @@ -520,7 +527,7 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1); // Get waypoint id that needs to delete. - long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)); + Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1))); // Delete contentProviderUtils.deleteWaypoint(context, waypoint1Id); @@ -530,12 +537,12 @@ public class CustomContentProviderUtilsTest { /** * Tests the method - * {@link ContentProviderUtils#deleteWaypoint(Context, long)} + * {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)} * when there is only one waypoint in the track. */ @Test public void testDeleteWaypoint_onlyOneWayPointWithPhotoUrl() throws IOException { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. @@ -547,7 +554,7 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1); // Get waypoint id that needs to delete. - long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)); + Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1))); // Check waypoint has photo and it's in the external storage. Assert.assertTrue(waypoint1.hasPhoto()); @@ -565,11 +572,11 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#deleteWaypoint(Context, long)} when there is more than one waypoint in the track. + * Tests the method {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)} when there is more than one waypoint in the track. */ @Test public void testDeleteWaypoint_hasNextWayPoint() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Track track = TestDataUtil.createTrackAndInsert(trackId, 10); @@ -592,12 +599,12 @@ public class CustomContentProviderUtilsTest { Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); waypoint1.setDescription(MOCK_DESC); waypoint1.setTrackId(trackId); - long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)); + Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1))); Waypoint waypoint2 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); waypoint2.setDescription(MOCK_DESC); waypoint2.setTrackId(trackId); - long waypoint2Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2)); + Waypoint.Id waypoint2Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2))); // Delete Assert.assertNotNull(contentProviderUtils.getWaypoint(waypoint1Id)); @@ -608,11 +615,11 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getNextWaypointNumber(long)}. + * Tests the method {@link ContentProviderUtils#getNextWaypointNumber(Track.Id)}. */ @Test public void testGetNextWaypointNumber() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); @@ -633,17 +640,17 @@ public class CustomContentProviderUtilsTest { /** * Tests the method {@link ContentProviderUtils#insertWaypoint(Waypoint)} and - * {@link ContentProviderUtils#getWaypoint(long)}. + * {@link ContentProviderUtils#getWaypoint(Waypoint.Id)}. */ @Test public void testInsertAndGetWaypoint() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); waypoint.setDescription(TEST_DESC); waypoint.setTrackId(trackId); - long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)); + Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); Assert.assertEquals(TEST_DESC, contentProviderUtils.getWaypoint(waypointId).getDescription()); } @@ -653,14 +660,14 @@ public class CustomContentProviderUtilsTest { */ @Test public void testUpdateWaypoint() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId)); waypoint.setDescription(TEST_DESC); waypoint.setTrackId(trackId); - long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)); + Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); // Update waypoint = contentProviderUtils.getWaypoint(waypointId); @@ -677,7 +684,7 @@ public class CustomContentProviderUtilsTest { public void testUpdateWaypoint_withPhoto() throws IOException { // tests after update waypoint with photo the photo remains in the storage. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. @@ -685,7 +692,7 @@ public class CustomContentProviderUtilsTest { Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation()); waypoint.setDescription(TEST_DESC); waypoint.setTrackId(trackId); - long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)); + Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); Assert.assertTrue(dir.exists()); @@ -713,7 +720,7 @@ public class CustomContentProviderUtilsTest { public void testUpdateWaypoint_delPhotoAndDir() throws IOException { // tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Also empty directory is deleted. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. @@ -721,7 +728,7 @@ public class CustomContentProviderUtilsTest { Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation()); waypoint.setDescription(TEST_DESC); waypoint.setTrackId(trackId); - long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)); + Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); Assert.assertTrue(dir.exists()); @@ -748,7 +755,7 @@ public class CustomContentProviderUtilsTest { public void testUpdateWaypoint_delPhotoNotDir() throws IOException { // tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Directory remains if there are more photos from other waypoints. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert two waypoints with photos. @@ -759,8 +766,8 @@ public class CustomContentProviderUtilsTest { Waypoint otherWaypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation()); otherWaypoint.setDescription(TEST_DESC); otherWaypoint.setTrackId(trackId); - long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)); - long otherWaypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(otherWaypoint)); + Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); + contentProviderUtils.insertWaypoint(otherWaypoint); File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); Assert.assertTrue(dir.exists()); @@ -780,12 +787,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#bulkInsertTrackPoint(TrackPoint[], long)}. + * Tests the method {@link ContentProviderUtils#bulkInsertTrackPoint(TrackPoint[], Track.Id)}. */ @Test public void testBulkInsertTrackPoint() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); TestDataUtil.insertTrackWithLocations(contentProviderUtils, track.first, track.second); @@ -841,12 +848,12 @@ public class CustomContentProviderUtilsTest { /** * Tests the method - * {@link ContentProviderUtils#insertTrackPoint(TrackPoint, long)}. + * {@link ContentProviderUtils#insertTrackPoint(TrackPoint, Track.Id)}. */ @Test public void testInsertTrackPoint() { // Insert track, point at first. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId); @@ -856,7 +863,7 @@ public class CustomContentProviderUtilsTest { @Test public void testInsertAndLoadTrackPoint() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TrackPoint trackPoint = TestDataUtil.createTrackPoint(5); @@ -876,12 +883,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getLastValidTrackPoint(long)}. + * Tests the method {@link ContentProviderUtils#getLastValidTrackPoint(Track.Id)}. */ @Test public void testGetLastValidTrackPoint() { // Insert track, points at first. - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TrackPoint lastTrackPoint = contentProviderUtils.getLastValidTrackPoint(trackId); @@ -889,12 +896,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getTrackPointCursor(long, long, int, boolean)} in descending. + * Tests the method {@link ContentProviderUtils#getTrackPointCursor(Track.Id, long, int, boolean)} in descending. */ @Test public void testGetTrackPointCursor_desc() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); contentProviderUtils.insertTrack(track.first); @@ -911,12 +918,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getTrackPointCursor(long, long, int, boolean)} in ascending. + * Tests the method {@link ContentProviderUtils#getTrackPointCursor(Track.Id, long, int, boolean)} in ascending. */ @Test public void testGetTrackPointCursor_asc() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); contentProviderUtils.insertTrack(track.first); @@ -933,12 +940,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(long, long, boolean)} in descending. + * Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(Track.Id, long, boolean)} in descending. */ @Test public void testGetTrackPointLocationIterator_desc() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); contentProviderUtils.insertTrack(track.first); @@ -962,12 +969,12 @@ public class CustomContentProviderUtilsTest { } /** - * Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(long, long, boolean)} in ascending. + * Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(Track.Id, long, boolean)} in ascending. */ @Test public void testGetTrackPointLocationIterator_asc() { // given - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); Pair track = TestDataUtil.createTrack(trackId, 10); contentProviderUtils.insertTrack(track.first); @@ -995,7 +1002,7 @@ public class CustomContentProviderUtilsTest { /** * Checks the value of a location. * - * @param i the index of this location which created in the method {@link TestDataUtil#createTrack(long, int)} + * @param i the index of this location which created in the method {@link TestDataUtil#createTrack(Track.Id, int)} * @param location the location to be checked */ private void checkLocation(int i, Location location) { @@ -1005,12 +1012,10 @@ public class CustomContentProviderUtilsTest { Assert.assertEquals(i * TestDataUtil.ALTITUDE_INTERVAL, location.getAltitude(), 0.01); } - @Test public void testFormatIdListForUri() { - Assert.assertEquals("", ContentProviderUtils.formatIdListForUri(new long[]{})); - Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new long[]{12})); - Assert.assertEquals("42,43,44", ContentProviderUtils.formatIdListForUri(new long[]{42, 43, 44})); + Assert.assertEquals("", ContentProviderUtils.formatIdListForUri()); + Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new Track.Id(12))); + Assert.assertEquals("42,43,44", ContentProviderUtils.formatIdListForUri(new Track.Id(42), new Track.Id(43), new Track.Id(44))); } - } diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/provider/ShareContentProviderTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/provider/ShareContentProviderTest.java index 7ca737f27..bcd3e9577 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/provider/ShareContentProviderTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/provider/ShareContentProviderTest.java @@ -6,6 +6,10 @@ import android.util.Pair; import org.junit.Assert; import org.junit.Test; +import java.util.HashSet; +import java.util.Set; + +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.io.file.TrackFileFormat; public class ShareContentProviderTest { @@ -14,20 +18,25 @@ public class ShareContentProviderTest { public void testCreateandParseURI_invalid() { Uri uri = Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/1"); - Assert.assertArrayEquals(new long[]{}, ShareContentProvider.parseURI(uri)); + Assert.assertEquals(0, ShareContentProvider.parseURI(uri).size()); } @Test public void testCreateandParseURI_valid() { - long[] trackIds = {1, 3, 5}; + Set trackIds = new HashSet<>(); + trackIds.add(new Track.Id(1)); + trackIds.add(new Track.Id(3)); + trackIds.add(new Track.Id(5)); + Pair shareURIandMIME = ShareContentProvider.createURI(trackIds, "TrackName", TrackFileFormat.KML_ONLY_TRACK); - Assert.assertArrayEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first)); + Assert.assertEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first)); } @Test public void testCreateURIescapeFilename() { - long[] trackIds = {1}; + Set trackIds = new HashSet<>(); + trackIds.add(new Track.Id(1)); Pair shareURIandMIME = ShareContentProvider.createURI(trackIds, "../../&1=1", TrackFileFormat.KML_ONLY_TRACK); Assert.assertEquals(Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/kml_only_track/1/..%2F..%2F%261%3D1.kml"), shareURIandMIME.first); diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java index 9b441dd47..694997db2 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java @@ -96,11 +96,11 @@ public abstract class AbstractTestFileTrackImporter { /** * Expects the first track point to be added. * - * @param trackPoint the trackPoint + * @param trackPoint the trackPoint * @param trackId the track id * @param trackPointId the track point id */ - protected void expectFirstTrackPoint(TrackPoint trackPoint, long trackId, long trackPointId) { + protected void expectFirstTrackPoint(TrackPoint trackPoint, Track.Id trackId, long trackPointId) { when(contentProviderUtils.bulkInsertTrackPoint(trackPoint != null ? (TrackPoint[]) any() : (TrackPoint[]) any(), eq(trackId))).thenReturn(1); } @@ -111,7 +111,7 @@ public abstract class AbstractTestFileTrackImporter { * @param lastTrack true if it is the last track in the gpx * @param trackId the track id */ - protected void expectTrackUpdate(ArgumentCaptor trackCaptor, boolean lastTrack, long trackId) { + protected void expectTrackUpdate(ArgumentCaptor trackCaptor, boolean lastTrack, Track.Id trackId) { contentProviderUtils.updateTrack(trackCaptor.capture()); when(contentProviderUtils.insertWaypoint(any())).thenReturn(WAYPOINT_ID_O_URI); diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java index 8c39d8767..6fc9bfd39 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java @@ -56,8 +56,8 @@ public class ExportImportTest { private final List waypoints = new ArrayList<>(); private final List trackPoints = new ArrayList<>(); - private long importTrackId; - private final long trackId = System.currentTimeMillis(); + private Track.Id importTrackId; + private final Track.Id trackId = new Track.Id(System.currentTimeMillis()); @Before public void setUp() { diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java index 50e7f1b73..2a240bafb 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java @@ -72,7 +72,7 @@ public class TrackRecordingServiceTest { private final Context context = ApplicationProvider.getApplicationContext(); private ContentProviderUtils contentProviderUtils; - private final long trackId = Math.abs(new Random().nextLong()); + private final Track.Id trackId = new Track.Id(Math.abs(new Random().nextLong())); static Intent createStartIntent(Context context) { return new Intent(context, TrackRecordingService.class); @@ -245,13 +245,13 @@ public class TrackRecordingServiceTest { service.startNewTrack(); Assert.assertTrue(service.isRecording()); - long trackId = service.getRecordingTrackId(); + Track.Id trackId = service.getRecordingTrackId(); // when - long newTrackId = service.startNewTrack(); + Track.Id newTrackId = service.startNewTrack(); // then - Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId); + Assert.assertNotNull(newTrackId); Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context)); Assert.assertEquals(trackId, service.getRecordingTrackId()); @@ -281,10 +281,10 @@ public class TrackRecordingServiceTest { Assert.assertFalse(service.isRecording()); // when - long waypointId = service.insertWaypoint(null, null, null, null); + Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null); // then - Assert.assertEquals(-1L, waypointId); + Assert.assertNull(waypointId); } @MediumTest @@ -295,10 +295,10 @@ public class TrackRecordingServiceTest { service.startNewTrack(); Assert.assertTrue(service.isRecording()); newTrackPoint(service); - long trackId = service.getRecordingTrackId(); + Track.Id trackId = service.getRecordingTrackId(); // when - long waypointId = service.insertWaypoint(null, null, null, null); + Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null); // then Assert.assertNotEquals(-1L, waypointId); @@ -313,15 +313,15 @@ public class TrackRecordingServiceTest { } private void addTrack(Track track, boolean isRecording) { - Assert.assertTrue(track.getId() >= 0); + Assert.assertTrue(track.getId().isValid()); contentProviderUtils.insertTrack(track); Assert.assertEquals(track.getId(), contentProviderUtils.getTrack(track.getId()).getId()); - PreferencesUtils.setLong(context, R.string.recording_track_id_key, isRecording ? track.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + PreferencesUtils.setLong(context, R.string.recording_track_id_key, isRecording ? track.getId().getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording); } // NOTE: Do not use to create a track that is currently recording. - private void createDummyTrack(long id, long stopTime, boolean isRecording) { + private void createDummyTrack(Track.Id id, long stopTime, boolean isRecording) { Track dummyTrack = new Track(); dummyTrack.setId(id); dummyTrack.setName("Dummy Track"); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java index 0d761d892..644d3cc2e 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.data.TrackPointsColumns; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; @@ -89,7 +90,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_movingAccurate() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); // when TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15); @@ -113,7 +114,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_slowMovingAccurate() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); // when TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15); @@ -155,7 +156,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_idle() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); // when TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0); @@ -181,7 +182,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_idle_withMovement() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); // when TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15); @@ -209,7 +210,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_idle_withSensorData() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); service.setRemoteSensorManager(new BluetoothRemoteSensorManager(context) { @@ -253,7 +254,7 @@ public class TrackRecordingServiceTestLocation { @Test public void testOnLocationChangedAsync_segment() throws Exception { // given - long trackId = service.startNewTrack(); + Track.Id trackId = service.startNewTrack(); // when TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java index dbe04bc3b..d57a4da05 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java @@ -197,14 +197,14 @@ public class TrackRecordingServiceTestLooper { Assert.assertFalse(service.isRecording()); // Start a track. - long id = service.startNewTrack(); - Assert.assertTrue(id >= 0); + Track.Id trackId = service.startNewTrack(); + Assert.assertTrue(trackId.isValid()); Assert.assertTrue(service.isRecording()); - Track track = contentProviderUtils.getTrack(id); + Track track = contentProviderUtils.getTrack(trackId); Assert.assertNotNull(track); - Assert.assertEquals(id, track.getId()); - Assert.assertEquals(id, PreferencesUtils.getRecordingTrackId(context)); - Assert.assertEquals(id, service.getRecordingTrackId()); + Assert.assertEquals(trackId, track.getId()); + Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context)); + Assert.assertEquals(trackId, service.getRecordingTrackId()); // Insert a few points, markers and statistics. long startTime = System.currentTimeMillis(); @@ -229,9 +229,9 @@ public class TrackRecordingServiceTestLooper { service.endCurrentTrack(); Assert.assertFalse(service.isRecording()); Assert.assertEquals(-1L, service.getRecordingTrackId()); - track = contentProviderUtils.getTrack(id); + track = contentProviderUtils.getTrack(trackId); Assert.assertNotNull(track); - Assert.assertEquals(id, track.getId()); + Assert.assertEquals(trackId, track.getId()); TrackStatistics trackStatistics = track.getTrackStatistics(); Assert.assertNotNull(trackStatistics); Assert.assertTrue(trackStatistics.getStartTime_ms() > 0); diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java index 74e1dcb42..868bffa33 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java @@ -30,6 +30,7 @@ import java.util.Date; import java.util.Locale; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.content.data.Track; /** * Tests {@link TrackNameUtils}. @@ -39,7 +40,7 @@ import de.dennisguse.opentracks.R; @RunWith(AndroidJUnit4.class) public class TrackNameUtilsTest { - private static final long TRACK_ID = 1L; + private static final Track.Id TRACK_ID = new Track.Id(1L); private static final long START_TIME = 1288213406000L; private static final Context CONTEXT = ApplicationProvider.getApplicationContext(); @@ -69,6 +70,6 @@ public class TrackNameUtilsTest { @Test public void testTrackName_number() { PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_number_value)); - Assert.assertEquals("Track " + TRACK_ID, TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME)); + Assert.assertEquals("Track " + TRACK_ID.getId(), TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME)); } } diff --git a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java index 8c46b803d..f38f5a1ec 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java @@ -18,6 +18,7 @@ package de.dennisguse.opentracks; import android.content.Intent; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; @@ -55,17 +56,17 @@ public abstract class AbstractListActivity extends AbstractActivity implements C * * @param trackIds the track ids */ - protected void deleteTracks(long[] trackIds) { + protected void deleteTracks(Track.Id... trackIds) { ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds); } @Override - public void onConfirmDeleteDone(long[] trackIds) { + public void onConfirmDeleteDone(Track.Id... trackIds) { boolean stopRecording = false; - long recordingTrackId = PreferencesUtils.getRecordingTrackId(this); - for (long trackId : trackIds) { - if (trackId == recordingTrackId) { + Track.Id recordingTrackId = PreferencesUtils.getRecordingTrackId(this); + for (Track.Id trackId : trackIds) { + if (trackId.equals(recordingTrackId)) { stopRecording = true; break; } diff --git a/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java index bb24dce9e..87e6dca5d 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java @@ -48,32 +48,32 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark private static final String TAG = MarkerDetailActivity.class.getSimpleName(); - private List markerIds; + private List waypointIds; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); - long markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L); - if (markerId == -1L) { + Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID); + if (waypointId == null) { Log.d(TAG, "invalid marker id"); finish(); return; } ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); - Waypoint waypoint = contentProviderUtils.getWaypoint(markerId); + Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId); - markerIds = new ArrayList<>(); + waypointIds = new ArrayList<>(); int markerIndex = -1; - try (Cursor cursor = contentProviderUtils.getWaypointCursor(waypoint.getTrackId(), -1L, -1)) { + try (Cursor cursor = contentProviderUtils.getWaypointCursor(waypoint.getTrackId(), null, -1)) { if (cursor != null && cursor.moveToFirst()) { for (int i = 0; i < cursor.getCount(); i++) { Waypoint currentMarker = contentProviderUtils.createWaypoint(cursor); - markerIds.add(currentMarker.getId()); - if (currentMarker.getId() == markerId) { - markerIndex = markerIds.size() - 1; + waypointIds.add(currentMarker.getId()); + if (currentMarker.getId() == waypointId) { + markerIndex = waypointIds.size() - 1; } cursor.moveToNext(); @@ -126,7 +126,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark @Override @NonNull public Fragment getItem(int position) { - return MarkerDetailFragment.newInstance(markerIds.get(position)); + return MarkerDetailFragment.newInstance(waypointIds.get(position)); } @Nullable @@ -137,7 +137,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark @Override public int getCount() { - return markerIds.size(); + return waypointIds.size(); } } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java index 637d1b746..82f966bd9 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java @@ -42,6 +42,7 @@ import java.io.File; import java.io.FileDescriptor; import java.io.IOException; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; @@ -64,7 +65,7 @@ public class MarkerEditActivity extends AbstractActivity { private static final int GALLERY_IMG_REQUEST_CODE = 7; private static final String TAG = MarkerEditActivity.class.getSimpleName(); - private long trackId; + private Track.Id trackId; private TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection(); private Waypoint waypoint; @@ -85,8 +86,8 @@ public class MarkerEditActivity extends AbstractActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L); - long markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L); + trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); + Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID); hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY); @@ -111,7 +112,7 @@ public class MarkerEditActivity extends AbstractActivity { Button cancel = findViewById(R.id.marker_edit_cancel); cancel.setOnClickListener(v -> finish()); - final boolean isNewMarker = markerId == -1L; + final boolean isNewMarker = waypointId == null; setTitle(isNewMarker ? R.string.menu_insert_marker : R.string.menu_edit); Button done = findViewById(R.id.marker_edit_done); @@ -126,7 +127,7 @@ public class MarkerEditActivity extends AbstractActivity { }); if (isNewMarker) { - int nextWaypointNumber = trackId == -1L ? -1 : new ContentProviderUtils(this).getNextWaypointNumber(trackId); + int nextWaypointNumber = trackId == null ? -1 : new ContentProviderUtils(this).getNextWaypointNumber(trackId); if (nextWaypointNumber == -1) { nextWaypointNumber = 0; } @@ -135,7 +136,7 @@ public class MarkerEditActivity extends AbstractActivity { waypointMarkerType.setText(""); waypointDescription.setText(""); } else { - waypoint = new ContentProviderUtils(this).getWaypoint(markerId); + waypoint = new ContentProviderUtils(this).getWaypoint(waypointId); if (waypoint == null) { Log.d(TAG, "waypoint is null"); finish(); @@ -260,8 +261,8 @@ public class MarkerEditActivity extends AbstractActivity { /** * Returns the trackId. If trackId == -1 then get it from waypoint object. */ - private long getTrackId() { - return trackId == -1 ? waypoint.getTrackId() : trackId; + private Track.Id getTrackId() { + return trackId == null ? waypoint.getTrackId() : trackId; } /** diff --git a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java index 8992e91ba..ac870b54c 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java @@ -36,6 +36,7 @@ import androidx.loader.content.CursorLoader; import androidx.loader.content.Loader; import de.dennisguse.opentracks.content.data.Track; +import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.data.WaypointsColumns; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment; @@ -66,7 +67,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker private SharedPreferences sharedPreferences; - private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + private Track.Id recordingTrackId; private boolean recordingTrackPaused; private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { @@ -117,13 +118,13 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); - long trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L); + Track.Id trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this); contentProviderUtils = new ContentProviderUtils(this); sharedPreferences = PreferencesUtils.getSharedPreferences(this); - track = trackId != -1L ? contentProviderUtils.getTrack(trackId) : null; + track = !trackId.isValid() ? contentProviderUtils.getTrack(trackId) : null; listView = findViewById(R.id.marker_list); listView.setEmptyView(findViewById(R.id.marker_list_empty)); @@ -223,7 +224,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker @Override public boolean onPrepareOptionsMenu(Menu menu) { - insertMarkerMenuItem.setVisible(track != null && track.getId() == recordingTrackId && !recordingTrackPaused); + insertMarkerMenuItem.setVisible(track != null && track.getId().equals(recordingTrackId) && !recordingTrackPaused); return super.onPrepareOptionsMenu(menu); } @@ -241,30 +242,35 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker /** * Handles a context item selection. * - * @param itemId the menu item id - * @param markerIds the marker ids + * @param itemId the menu item id + * @param waypointIds the marker ids * @return true if handled. */ - private boolean handleContextItem(int itemId, long[] markerIds) { + private boolean handleContextItem(int itemId, long... longWaypointIds) { + Waypoint.Id[] waypointIds = new Waypoint.Id[longWaypointIds.length]; + for (int i = 0; i < longWaypointIds.length; i++) { + waypointIds[i] = new Waypoint.Id(longWaypointIds[i]); + } + Intent intent; switch (itemId) { case R.id.list_context_menu_show_on_map: - if (markerIds.length == 1) { - IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(markerIds[0])); + if (waypointIds.length == 1) { + IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(waypointIds[0])); } return true; case R.id.list_context_menu_edit: - if (markerIds.length == 1) { + if (waypointIds.length == 1) { intent = IntentUtils.newIntent(this, MarkerEditActivity.class) - .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerIds[0]); + .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointIds[0]); startActivity(intent); } return true; case R.id.list_context_menu_delete: - if (markerIds.length > 1 && markerIds.length == listView.getCount()) { - markerIds = new long[]{-1L}; + if (waypointIds.length > 1 && waypointIds.length == listView.getCount()) { + waypointIds = null; } - DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), markerIds); + DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointIds); return true; case R.id.list_context_menu_select_all: for (int i = 0; i < listView.getCount(); i++) { diff --git a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java index 92e1e78bb..1602ac25f 100644 --- a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java @@ -97,7 +97,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa private boolean metricUnits = true; - private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + private Track.Id recordingTrackId; private boolean recordingTrackPaused; @@ -203,7 +203,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa listView.setEmptyView(findViewById(R.id.search_list_empty)); listView.setOnItemClickListener((parent, view, position, id) -> { Map item = arrayAdapter.getItem(position); - Long trackId = (Long) item.get(TRACK_ID_FIELD); + Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD); Long markerId = (Long) item.get(MARKER_ID_FIELD); Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackRecordedActivity.class); if (markerId != null) { @@ -270,22 +270,22 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa return false; } Map item = arrayAdapter.getItem(positions[0]); - Long trackId = (Long) item.get(TRACK_ID_FIELD); - Long markerId = (Long) item.get(MARKER_ID_FIELD); + Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD); + Waypoint.Id waypointId = (Waypoint.Id) item.get(MARKER_ID_FIELD); Intent intent; switch (itemId) { case R.id.list_context_menu_show_on_map: IntentUtils.showCoordinateOnMap(this, (double) item.get(MARKER_LATITUDE_FIELD), (double) item.get(MARKER_LONGITUDE_FIELD), item.get(NAME_FIELD) + ""); return true; case R.id.list_context_menu_share: - intent = IntentUtils.newShareFileIntent(this, new long[]{trackId}); + intent = IntentUtils.newShareFileIntent(this, trackId); intent = Intent.createChooser(intent, null); startActivity(intent); return true; case R.id.list_context_menu_edit: - if (markerId != null) { + if (waypointId != null) { intent = IntentUtils.newIntent(this, MarkerEditActivity.class) - .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerId); + .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointId); } else { intent = IntentUtils.newIntent(this, TrackEditActivity.class) .putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId); @@ -296,10 +296,10 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa finish(); return true; case R.id.list_context_menu_delete: - if (markerId != null) { - DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), new long[]{markerId}); + if (waypointId != null) { + DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointId); } else { - deleteTracks(new long[]{trackId}); + deleteTracks(trackId); } return true; default: @@ -331,7 +331,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa * @param textQuery the query */ private void doSearch(String textQuery) { - SearchQuery query = new SearchQuery(textQuery, null, -1L, System.currentTimeMillis()); + SearchQuery query = new SearchQuery(textQuery, null, null, System.currentTimeMillis()); SortedSet scoredResults = searchEngine.search(query); final List> displayResults = prepareResultsforDisplay(scoredResults); @@ -372,8 +372,8 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa //TODO: It may be more appropriate to obtain the track name as a join in the retrieval phase of the searchable. String trackName = null; - long trackId = waypoint.getTrackId(); - if (trackId != -1L) { + Track.Id trackId = waypoint.getTrackId(); + if (!trackId.isValid()) { Track track = contentProviderUtils.getTrack(trackId); if (track != null) { trackName = track.getName(); diff --git a/src/main/java/de/dennisguse/opentracks/ShowOnMapProxyActivity.java b/src/main/java/de/dennisguse/opentracks/ShowOnMapProxyActivity.java index 7b92ab6b4..844ec4715 100644 --- a/src/main/java/de/dennisguse/opentracks/ShowOnMapProxyActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ShowOnMapProxyActivity.java @@ -8,6 +8,9 @@ import android.util.Pair; import androidx.appcompat.app.AppCompatActivity; +import java.util.Set; + +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPointsColumns; import de.dennisguse.opentracks.content.provider.ShareContentProvider; import de.dennisguse.opentracks.io.file.TrackFileFormat; @@ -26,7 +29,7 @@ public abstract class ShowOnMapProxyActivity extends AppCompatActivity { protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - long[] trackIds = IntentDashboardUtils.extractTrackIdsFromIntent(getIntent()); + Set trackIds = IntentDashboardUtils.extractTrackIdsFromIntent(getIntent()); showTrackTrackfileFormat(this, trackFileFormat, trackIds); @@ -39,14 +42,14 @@ public abstract class ShowOnMapProxyActivity extends AppCompatActivity { * @param context the context * @param trackIds the track ids */ - private static void showTrackTrackfileFormat(Context context, TrackFileFormat trackFileFormat, long[] trackIds) { - if (trackIds.length == 0) { + private static void showTrackTrackfileFormat(Context context, TrackFileFormat trackFileFormat, Set trackIds) { + if (trackIds.size() == 0) { return; } Intent intent = new Intent(android.content.Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(TrackPointsColumns.TRACKID, trackIds[0]); + intent.putExtra(TrackPointsColumns.TRACKID, trackIds.toArray(new Track.Id[0])[0]); Pair uriAndMime = ShareContentProvider.createURI(trackIds, "SharingTrack", trackFileFormat); intent.setDataAndType(uriAndMime.first, uriAndMime.second); diff --git a/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java index 70368780c..51caa3568 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java @@ -21,6 +21,7 @@ import android.os.Bundle; import android.os.PowerManager; import android.view.View; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.util.SystemUtils; @@ -33,7 +34,7 @@ public class TrackDeleteActivity extends AbstractActivity { public static final String EXTRA_TRACK_IDS = "track_ids"; - private long[] trackIds; + private Track.Id[] trackIds; private Thread deleteThread; @@ -44,13 +45,13 @@ public class TrackDeleteActivity extends AbstractActivity { setResult(RESULT_CANCELED); Intent intent = getIntent(); - trackIds = intent.getLongArrayExtra(EXTRA_TRACK_IDS); + trackIds = (Track.Id[]) intent.getParcelableArrayExtra(EXTRA_TRACK_IDS); deleteThread = new Thread(() -> { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(TrackDeleteActivity.this); PowerManager.WakeLock wakeLock = SystemUtils.acquireWakeLock(TrackDeleteActivity.this, null); - for (long id : trackIds) { + for (Track.Id id : trackIds) { if (Thread.interrupted()) { break; } diff --git a/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java b/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java index adba412bd..1b953a841 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java @@ -65,8 +65,8 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit super.onCreate(bundle); trackRecordingServiceConnection = new TrackRecordingServiceConnection(); - long trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L); - if (trackId == -1L) { + Track.Id trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); + if (!trackId.isValid()) { Log.e(TAG, "invalid trackId"); finish(); return; diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 5c7e0b185..069ed5e77 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -46,6 +46,7 @@ import androidx.loader.app.LoaderManager.LoaderCallbacks; import androidx.loader.content.CursorLoader; import androidx.loader.content.Loader; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; @@ -104,7 +105,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe // Preferences private boolean metricUnits = true; - private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + private Track.Id recordingTrackId = new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); // Callback when an item is selected in the contextual action mode private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() { @@ -245,7 +246,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe listView.setEmptyView(findViewById(R.id.track_list_empty_view)); listView.setOnItemClickListener((parent, view, position, trackId) -> { Intent newIntent; - if (trackId == recordingTrackId) { + if (trackId == recordingTrackId.getId()) { // Is recording -> open record activity. newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class) .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); @@ -269,7 +270,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY); int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION); - long trackId = cursor.getLong(idIndex); + Track.Id trackId = new Track.Id(cursor.getLong(idIndex)); boolean isRecording = trackId == recordingTrackId; String icon = cursor.getString(iconIndex); int iconId = TrackIconUtils.getIconDrawable(icon); @@ -459,8 +460,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe /** * Updates the menu items with the icon specified. * - * @param isGpsStarted true if gps is started - * @param isRecording true if recording + * @param isGpsStarted true if gps is started + * @param isRecording true if recording */ private void updateGpsMenuItem(boolean isGpsStarted, boolean isRecording) { if (startGpsMenuItem != null) { @@ -482,11 +483,16 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe * @param trackIds the track ids * @return true if handled. */ - private boolean handleContextItem(int itemId, long[] trackIds) { + private boolean handleContextItem(int itemId, long... longTrackIds) { + Track.Id[] trackIds = new Track.Id[longTrackIds.length]; + for (int i = 0; i < longTrackIds.length; i++) { + trackIds[i] = new Track.Id(longTrackIds[i]); + } + Intent intent; switch (itemId) { case R.id.list_context_menu_show_on_map: - IntentDashboardUtils.startDashboard(this, trackIds, false); + IntentDashboardUtils.startDashboard(this, false, trackIds); return true; case R.id.list_context_menu_share: intent = IntentUtils.newShareFileIntent(this, trackIds); diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java index a78d21023..530f5d300 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java @@ -66,7 +66,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos private ViewPager pager; // From intent. - private long trackId; + private Track.Id trackId; @Override protected void onCreate(Bundle savedInstanceState) { @@ -133,7 +133,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos // Update UI this.invalidateOptionsMenu(); - if (trackId != -1L) { + if (!trackId.isValid()) { trackDataHub.loadTrack(trackId); } } @@ -182,12 +182,12 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos Intent intent; switch (item.getItemId()) { case R.id.track_detail_share: - intent = IntentUtils.newShareFileIntent(this, new long[]{trackId}); + intent = IntentUtils.newShareFileIntent(this, trackId); intent = Intent.createChooser(intent, null); startActivity(intent); return true; case R.id.track_detail_menu_show_on_map: - IntentDashboardUtils.startDashboard(this, new long[]{trackId}, false); + IntentDashboardUtils.startDashboard(this, false, trackId); return true; case R.id.track_detail_markers: intent = IntentUtils.newIntent(this, MarkerListActivity.class) @@ -200,7 +200,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos startActivity(intent); return true; case R.id.track_detail_delete: - deleteTracks(new long[]{trackId}); + deleteTracks(trackId); return true; case R.id.track_detail_resume_track: Intent newIntent = IntentUtils.newIntent(TrackRecordedActivity.this, TrackRecordingActivity.class) @@ -238,12 +238,12 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos } private void handleIntent(Intent intent) { - trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); + trackId = intent.getParcelableExtra(EXTRA_TRACK_ID); - long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); - if (markerId != -1L) { + Waypoint.Id waypointId = intent.getParcelableExtra(EXTRA_MARKER_ID); + if (waypointId != null) { // Use the trackId from the marker - Waypoint waypoint = contentProviderUtils.getWaypoint(markerId); + Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId); if (waypoint == null) { finish(); return; @@ -251,7 +251,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos trackId = waypoint.getTrackId(); } - if (trackId == -1L) { + if (!trackId.isValid()) { Log.e(TAG, "TrackDetailActivity needs EXTRA_TRACK_ID."); finish(); } diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java index 907cdd268..6384a9f50 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java @@ -60,7 +60,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc private TrackController trackController; // Initialized from Intent; if a new track recording is started, a new TrackId will be provided by TrackRecordingService - private long trackId; + private Track.Id trackId; // Preferences private boolean recordingTrackPaused; @@ -78,7 +78,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc } if (!service.isRecording()) { // Starts or resumes a track. - if (trackId == -1L) { + if (trackId == null) { // trackId isn't initialized -> leads a new recording. trackId = service.startNewTrack(); } else { @@ -161,13 +161,13 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc super.onCreate(savedInstanceState); contentProviderUtils = new ContentProviderUtils(this); - trackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + trackId = null; if (savedInstanceState != null) { //Activity was recreated. - trackId = savedInstanceState.getLong(EXTRA_TRACK_ID, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + trackId = savedInstanceState.getParcelable(EXTRA_TRACK_ID); } else { - trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); - if (trackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT && contentProviderUtils.getTrack(trackId) == null) { + trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); + if (contentProviderUtils.getTrack(trackId) == null) { finish(); } } @@ -247,7 +247,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc // Update UI this.invalidateOptionsMenu(); - if (trackId != -1L) { + if (!trackId.isValid()) { trackDataHub.loadTrack(trackId); trackController.onResume(true, recordingTrackPaused); } @@ -265,7 +265,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem()); - outState.putLong(EXTRA_TRACK_ID, trackId); + outState.putParcelable(EXTRA_TRACK_ID, trackId); } @Override @@ -314,7 +314,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc startActivity(intent); return true; case R.id.track_detail_menu_show_on_map: - IntentDashboardUtils.startDashboard(this, new long[]{trackId}, true); + IntentDashboardUtils.startDashboard(this, true, trackId); return true; case R.id.track_detail_markers: intent = IntentUtils.newIntent(this, MarkerListActivity.class) diff --git a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java index 54c91bdab..dc37ed418 100644 --- a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java +++ b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java @@ -123,8 +123,8 @@ public class SearchEngine { } // Finally, use arbitrary ordering, by ID. - long id1 = r1.track != null ? r1.track.getId() : r1.waypoint.getId(); - long id2 = r2.track != null ? r2.track.getId() : r2.waypoint.getId(); + long id1 = r1.track != null ? r1.track.getId().getId() : r1.waypoint.getId().getId(); + long id2 = r2.track != null ? r2.track.getId().getId() : r2.waypoint.getId().getId(); long idDiff = id2 - id1; return Long.signum(idDiff); }; @@ -290,7 +290,7 @@ public class SearchEngine { score *= getTimeBoost(query, location.getTime()); // Score waypoints in the currently-selected track higher (searching inside the current track). - if (query.currentTrackId != -1 && waypoint.getTrackId() == query.currentTrackId) { + if (query.currentTrackId.isValid() && waypoint.getTrackId().equals(query.currentTrackId)) { score *= CURRENT_TRACK_WAYPOINT_PROMOTION; } @@ -382,10 +382,10 @@ public class SearchEngine { public static class SearchQuery { final String textQuery; final Location currentLocation; - final long currentTrackId; + final Track.Id currentTrackId; final long currentTimestamp; - public SearchQuery(String textQuery, Location currentLocation, long currentTrackId, long currentTimestamp) { + public SearchQuery(String textQuery, Location currentLocation, Track.Id currentTrackId, long currentTimestamp) { this.textQuery = textQuery.toLowerCase(Locale.getDefault()); this.currentLocation = currentLocation; this.currentTrackId = currentTrackId; diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java index ca6f676d9..feb60bf1e 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java @@ -78,8 +78,8 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL private Handler handler; // Preference values - private long selectedTrackId; - private long recordingTrackId; + private Track.Id selectedTrackId; + private Track.Id recordingTrackId; private boolean recordingTrackPaused; // Track points sampling state @@ -174,7 +174,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL handler = null; } - public void loadTrack(final long trackId) { + public void loadTrack(final Track.Id trackId) { runInHandlerThread(() -> { if (trackId == selectedTrackId) { Log.i(TAG, "Not reloading track " + trackId); @@ -311,7 +311,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL trackDataListener.clearWaypoints(); } - try (Cursor cursor = contentProviderUtils.getWaypointCursor(selectedTrackId, -1L, MAX_DISPLAYED_WAYPOINTS)) { + try (Cursor cursor = contentProviderUtils.getWaypointCursor(selectedTrackId, null, MAX_DISPLAYED_WAYPOINTS)) { if (cursor != null && cursor.moveToFirst()) { do { Waypoint waypoint = contentProviderUtils.createWaypoint(cursor); diff --git a/src/main/java/de/dennisguse/opentracks/content/data/Track.java b/src/main/java/de/dennisguse/opentracks/content/data/Track.java index ea6aa0821..111798649 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/Track.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/Track.java @@ -16,9 +16,16 @@ package de.dennisguse.opentracks.content.data; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.util.Objects; import java.util.UUID; import de.dennisguse.opentracks.stats.TrackStatistics; +import de.dennisguse.opentracks.util.PreferencesUtils; /** * A track. @@ -28,7 +35,7 @@ import de.dennisguse.opentracks.stats.TrackStatistics; */ public class Track { - private long id = -1L; + private Track.Id id; private UUID uuid = UUID.randomUUID(); private String name = ""; @@ -42,11 +49,11 @@ public class Track { public Track() { } - public long getId() { + public Id getId() { return id; } - public void setId(long id) { + public void setId(Id id) { this.id = id; } @@ -97,4 +104,59 @@ public class Track { public void setTrackStatistics(TrackStatistics trackStatistics) { this.trackStatistics = trackStatistics; } + + public static class Id implements Parcelable { + + private final long id; + + public Id(long id) { + this.id = id; + } + + public Id(@NonNull String id) { + this(Long.parseLong(id)); + } + + //TOOD Limit visibility to TrackRecordingService / ContentProvider + public long getId() { + return id; + } + + public boolean isValid() { + return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Id id1 = (Id) o; + return id == id1.id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeLong(id); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public Track.Id createFromParcel(Parcel in) { + return new Track.Id(in.readLong()); + } + + public Track.Id[] newArray(int size) { + return new Track.Id[size]; + } + }; + } } diff --git a/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java b/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java index 8341bc1bb..c76266611 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java @@ -18,10 +18,16 @@ package de.dennisguse.opentracks.content.data; import android.location.Location; import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import java.util.Objects; + +import de.dennisguse.opentracks.util.PreferencesUtils; + /** * A waypoint. * @@ -30,12 +36,12 @@ import androidx.annotation.VisibleForTesting; */ public final class Waypoint { - private long id = -1L; + private Id id; private String name = ""; private String description = ""; private String category = ""; private String icon = ""; - private long trackId = -1L; + private Track.Id trackId; private double length = 0.0; private long duration = 0; private Location location; @@ -51,7 +57,7 @@ public final class Waypoint { this.location = location; } - public Waypoint(String name, String description, String category, String icon, long trackId, double length, long duration, @NonNull Location location, String photoUrl) { + public Waypoint(String name, String description, String category, String icon, @NonNull Track.Id trackId, double length, long duration, @NonNull Location location, String photoUrl) { this.name = name; this.description = description; this.category = category; @@ -63,11 +69,11 @@ public final class Waypoint { this.photoUrl = photoUrl; } - public long getId() { + public Id getId() { return id; } - public void setId(long id) { + public void setId(Id id) { this.id = id; } @@ -103,11 +109,11 @@ public final class Waypoint { this.icon = icon; } - public long getTrackId() { + public Track.Id getTrackId() { return trackId; } - public void setTrackId(long trackId) { + public void setTrackId(Track.Id trackId) { this.trackId = trackId; } @@ -147,4 +153,59 @@ public final class Waypoint { public boolean hasPhoto() { return photoUrl != null && !"".equals(photoUrl); } + + public static class Id implements Parcelable { + + private final long id; + + public Id(long id) { + this.id = id; + } + + public Id(@NonNull String id) { + this(Long.parseLong(id)); + } + + //TOOD Limit visibility to TrackRecordingService / ContentProvider + public long getId() { + return id; + } + + public boolean isValid() { + return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Id id1 = (Id) o; + return id == id1.id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeLong(id); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public Id createFromParcel(Parcel in) { + return new Id(in.readLong()); + } + + public Id[] newArray(int size) { + return new Id[size]; + } + }; + } } 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 fbc7e1857..de48645e2 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java @@ -25,6 +25,7 @@ import android.net.Uri; import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.io.File; @@ -89,7 +90,7 @@ public class ContentProviderUtils { * * @param trackId the track id */ - public void clearTrack(long trackId) { + public void clearTrack(Track.Id trackId) { deleteTrackPointsAndWaypoints(trackId); Track track = new Track(); track.setId(trackId); @@ -121,7 +122,7 @@ public class ContentProviderUtils { Track track = new Track(); TrackStatistics trackStatistics = track.getTrackStatistics(); if (!cursor.isNull(idIndex)) { - track.setId(cursor.getLong(idIndex)); + track.setId(new Track.Id(cursor.getLong(idIndex))); } if (!cursor.isNull(uuidIndex)) { track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex))); @@ -184,14 +185,14 @@ public class ContentProviderUtils { * * @param trackId the track id */ - public void deleteTrack(Context context, long trackId) { + public void deleteTrack(Context context, Track.Id trackId) { deleteTrackPointsAndWaypoints(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)}); + contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())}); } /** @@ -199,8 +200,8 @@ public class ContentProviderUtils { * * @param trackId the track id */ - private void deleteTrackPointsAndWaypoints(long trackId) { - String[] selectionArgs = new String[]{Long.toString(trackId)}; + private void deleteTrackPointsAndWaypoints(Track.Id trackId) { + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, TrackPointsColumns.TRACKID + "=?", selectionArgs); contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", selectionArgs); @@ -233,11 +234,11 @@ public class ContentProviderUtils { /** * @param trackId the track id. */ - public Track getTrack(long trackId) { - if (trackId < 0) { + public Track getTrack(Track.Id trackId) { + if (trackId == null || !trackId.isValid()) { return null; } - try (Cursor cursor = getTrackCursor(TracksColumns._ID + "=?", new String[]{Long.toString(trackId)}, null)) { + try (Cursor cursor = getTrackCursor(TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())}, null)) { if (cursor != null && cursor.moveToNext()) { return createTrack(cursor); } @@ -288,7 +289,7 @@ public class ContentProviderUtils { * @param track the track */ public void updateTrack(Track track) { - contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId())}); + contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId().getId())}); } private ContentValues createContentValues(Track track) { @@ -296,8 +297,8 @@ public class ContentProviderUtils { TrackStatistics trackStatistics = track.getTrackStatistics(); // Value < 0 indicates no id is available - if (track.getId() >= 0) { - values.put(TracksColumns._ID, track.getId()); + if (track.getId().isValid()) { + values.put(TracksColumns._ID, track.getId().getId()); } values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid())); values.put(TracksColumns.NAME, track.getName()); @@ -363,7 +364,7 @@ public class ContentProviderUtils { Waypoint waypoint = new Waypoint(location); if (!cursor.isNull(idIndex)) { - waypoint.setId(cursor.getLong(idIndex)); + waypoint.setId(new Waypoint.Id(cursor.getLong(idIndex))); } if (!cursor.isNull(nameIndex)) { waypoint.setName(cursor.getString(nameIndex)); @@ -378,7 +379,7 @@ public class ContentProviderUtils { waypoint.setIcon(cursor.getString(iconIndex)); } if (!cursor.isNull(trackIdIndex)) { - waypoint.setTrackId(cursor.getLong(trackIdIndex)); + waypoint.setTrackId(new Track.Id(cursor.getLong(trackIdIndex))); } if (!cursor.isNull(lengthIndex)) { waypoint.setLength(cursor.getFloat(lengthIndex)); @@ -393,10 +394,10 @@ public class ContentProviderUtils { return waypoint; } - public void deleteWaypoint(Context context, long waypointId) { + public void deleteWaypoint(Context context, Waypoint.Id waypointId) { final Waypoint waypoint = getWaypoint(waypointId); deleteWaypointPhoto(context, waypoint); - contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns._ID + "=?", new String[]{Long.toString(waypointId)}); + contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns._ID + "=?", new String[]{Long.toString(waypointId.getId())}); } /** @@ -405,13 +406,13 @@ public class ContentProviderUtils { * @param trackId the track id * @return -1 if not able to get the next waypoint number. */ - public int getNextWaypointNumber(long trackId) { - if (trackId < 0) { + public int getNextWaypointNumber(Track.Id trackId) { + if (!trackId.isValid()) { return -1; } String[] projection = {WaypointsColumns._ID}; String selection = WaypointsColumns.TRACKID + "=?"; - String[] selectionArgs = new String[]{Long.toString(trackId)}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; try (Cursor cursor = getWaypointCursor(projection, selection, selectionArgs, WaypointsColumns._ID, -1)) { if (cursor != null) { return cursor.getCount(); @@ -420,12 +421,12 @@ public class ContentProviderUtils { return -1; } - public Waypoint getWaypoint(long waypointId) { - if (waypointId < 0) { + public Waypoint getWaypoint(Waypoint.Id waypointId) { + if (!waypointId.isValid()) { return null; } try (Cursor cursor = getWaypointCursor(null, WaypointsColumns._ID + "=?", - new String[]{Long.toString(waypointId)}, WaypointsColumns._ID, 1)) { + new String[]{Long.toString(waypointId.getId())}, WaypointsColumns._ID, 1)) { if (cursor != null && cursor.moveToFirst()) { return createWaypoint(cursor); } @@ -451,30 +452,30 @@ public class ContentProviderUtils { * The caller owns the returned cursor and is responsible for closing it. * * @param trackId the track id - * @param minWaypointId the minimum waypoint id. -1L to ignore + * @param minWaypointId the minimum waypoint id. null to ignore * @param maxWaypoints the maximum number of waypoints to return. -1 for no limit */ - public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints) { - if (trackId < 0) { + public Cursor getWaypointCursor(Track.Id trackId, @Nullable Waypoint.Id minWaypointId, int maxWaypoints) { + if (!trackId.isValid()) { return null; } String selection; String[] selectionArgs; - if (minWaypointId >= 0) { + if (minWaypointId != null && minWaypointId.isValid()) { selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns._ID + ">=?"; - selectionArgs = new String[]{Long.toString(trackId), Long.toString(minWaypointId)}; + selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(minWaypointId.getId())}; } else { selection = WaypointsColumns.TRACKID + "=?"; - selectionArgs = new String[]{Long.toString(trackId)}; + selectionArgs = new String[]{Long.toString(trackId.getId())}; } return getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, maxWaypoints); } @VisibleForTesting - public List getWaypoints(long trackId) { + public List getWaypoints(Track.Id trackId) { ArrayList waypoints = new ArrayList<>(); - try (Cursor cursor = getWaypointCursor(trackId, -1L, -1)) { + try (Cursor cursor = getWaypointCursor(trackId, null, -1)) { if (cursor.moveToFirst()) { do { waypoints.add(createWaypoint(cursor)); @@ -489,14 +490,14 @@ public class ContentProviderUtils { * * @param trackId the track id */ - public int getWaypointCount(long trackId) { - if (trackId < 0) { + public int getWaypointCount(Track.Id trackId) { + if (!trackId.isValid()) { return 0; } String[] projection = new String[]{"count(*) AS count"}; String selection = WaypointsColumns.TRACKID + "=?"; - String[] selectionArgs = new String[]{Long.toString(trackId)}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; try (Cursor cursor = contentResolver.query(WaypointsColumns.CONTENT_URI, projection, selection, selectionArgs, WaypointsColumns._ID)) { if (cursor == null) { return 0; @@ -513,7 +514,7 @@ public class ContentProviderUtils { * @return the content provider URI of the inserted waypoint. */ public Uri insertWaypoint(Waypoint waypoint) { - waypoint.setId(-1L); + waypoint.setId(null); return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint)); } @@ -548,22 +549,21 @@ public class ContentProviderUtils { if (!updatedWaypoint.hasPhoto()) { deleteWaypointPhoto(context, savedWaypoint); } - int rows = contentResolver.update(WaypointsColumns.CONTENT_URI, createContentValues(updatedWaypoint), WaypointsColumns._ID + "=?", new String[]{Long.toString(updatedWaypoint.getId())}); + int rows = contentResolver.update(WaypointsColumns.CONTENT_URI, createContentValues(updatedWaypoint), WaypointsColumns._ID + "=?", new String[]{Long.toString(updatedWaypoint.getId().getId())}); return rows == 1; } - ContentValues createContentValues(Waypoint waypoint) { + ContentValues createContentValues(@NonNull Waypoint waypoint) { ContentValues values = new ContentValues(); - // Value < 0 indicates no id is available - if (waypoint.getId() >= 0) { - values.put(WaypointsColumns._ID, waypoint.getId()); + if (waypoint.getId().isValid()) { + values.put(WaypointsColumns._ID, waypoint.getId().getId()); } values.put(WaypointsColumns.NAME, waypoint.getName()); values.put(WaypointsColumns.DESCRIPTION, waypoint.getDescription()); values.put(WaypointsColumns.CATEGORY, waypoint.getCategory()); values.put(WaypointsColumns.ICON, waypoint.getIcon()); - values.put(WaypointsColumns.TRACKID, waypoint.getTrackId()); + values.put(WaypointsColumns.TRACKID, waypoint.getTrackId().getId()); values.put(WaypointsColumns.LENGTH, waypoint.getLength()); values.put(WaypointsColumns.DURATION, waypoint.getDuration()); @@ -656,7 +656,7 @@ public class ContentProviderUtils { * @return the number of trackPoints inserted */ //TODO Only used for testing and file import; might be better to replace it. - public int bulkInsertTrackPoint(TrackPoint[] trackPoints, long trackId) { + public int bulkInsertTrackPoint(TrackPoint[] trackPoints, Track.Id trackId) { ContentValues[] values = new ContentValues[trackPoints.length]; for (int i = 0; i < values.length; i++) { values[i] = createContentValues(trackPoints[i], trackId); @@ -666,23 +666,23 @@ public class ContentProviderUtils { /** * Gets the first location id for a track. - * Returns -1L if it doesn't exist. + * Returns null if it doesn't exist. * * @param trackId the track id */ @Deprecated - public long getFirstTrackPointId(long trackId) { - if (trackId < 0) { - return -1L; + public Track.Id getFirstTrackPointId(Track.Id trackId) { + if (!trackId.isValid()) { + return null; } String selection = TrackPointsColumns._ID + "=(SELECT MIN(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)"; - String[] selectionArgs = new String[]{Long.toString(trackId)}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) { if (cursor != null && cursor.moveToFirst()) { - return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); + return new Track.Id(cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID))); } } - return -1L; + return null; } /** @@ -692,12 +692,12 @@ public class ContentProviderUtils { * @param trackId the track id */ @Deprecated - public long getLastTrackPointId(long trackId) { - if (trackId < 0) { + public long getLastTrackPointId(Track.Id trackId) { + if (!trackId.isValid()) { return -1L; } String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)"; - String[] selectionArgs = new String[]{Long.toString(trackId)}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) { if (cursor != null && cursor.moveToFirst()) { return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); @@ -713,12 +713,12 @@ public class ContentProviderUtils { * @param location the location * @return trackPoint id if the location is in the track. -1L otherwise. */ - public long getTrackPointId(long trackId, Location location) { - if (trackId < 0) { + public long getTrackPointId(Track.Id trackId, Location location) { + if (!trackId.isValid()) { return -1L; } String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.TIME + "=?)"; - String[] selectionArgs = new String[]{Long.toString(trackId), Long.toString(location.getTime())}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(location.getTime())}; try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) { if (cursor != null && cursor.moveToFirst()) { return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); @@ -744,8 +744,8 @@ public class ContentProviderUtils { * @param maxLocations maximum number of locations to return. -1 for no limit * @param descending true to sort the result in descending order (latest location first) */ - public Cursor getTrackPointCursor(long trackId, long startTrackPointId, int maxLocations, boolean descending) { - if (trackId < 0) { + public Cursor getTrackPointCursor(Track.Id trackId, long startTrackPointId, int maxLocations, boolean descending) { + if (!trackId.isValid()) { return null; } @@ -754,10 +754,10 @@ public class ContentProviderUtils { if (startTrackPointId >= 0) { String comparison = descending ? "<=" : ">="; selection = TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns._ID + comparison + "?"; - selectionArgs = new String[]{Long.toString(trackId), Long.toString(startTrackPointId)}; + selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(startTrackPointId)}; } else { selection = TrackPointsColumns.TRACKID + "=?"; - selectionArgs = new String[]{Long.toString(trackId)}; + selectionArgs = new String[]{Long.toString(trackId.getId())}; } String sortOrder = TrackPointsColumns._ID; @@ -777,12 +777,12 @@ public class ContentProviderUtils { * @param trackId the track id */ @Deprecated - public TrackPoint getLastValidTrackPoint(long trackId) { - if (trackId < 0) { + public TrackPoint getLastValidTrackPoint(Track.Id trackId) { + if (!trackId.isValid()) { return null; } String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.LATITUDE + "<=" + MAX_LATITUDE + ")"; - String[] selectionArgs = new String[]{Long.toString(trackId)}; + String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; return findTrackPointBy(selection, selectionArgs); } @@ -793,7 +793,7 @@ public class ContentProviderUtils { * @param trackId the track id * @return the content provider URI of the inserted trackPoint */ - public Uri insertTrackPoint(TrackPoint trackPoint, long trackId) { + public Uri insertTrackPoint(TrackPoint trackPoint, Track.Id trackId) { return contentResolver.insert(TrackPointsColumns.CONTENT_URI_BY_ID, createContentValues(trackPoint, trackId)); } @@ -803,9 +803,9 @@ public class ContentProviderUtils { * @param trackPoint the trackPoint * @param trackId the track id */ - private ContentValues createContentValues(TrackPoint trackPoint, long trackId) { + private ContentValues createContentValues(TrackPoint trackPoint, Track.Id trackId) { ContentValues values = new ContentValues(); - values.put(TrackPointsColumns.TRACKID, trackId); + values.put(TrackPointsColumns.TRACKID, trackId.getId()); values.put(TrackPointsColumns.LONGITUDE, (int) (trackPoint.getLongitude() * 1E6)); values.put(TrackPointsColumns.LATITUDE, (int) (trackPoint.getLatitude() * 1E6)); @@ -846,7 +846,7 @@ public class ContentProviderUtils { * @param startTrackPointId the starting trackPoint id. -1L to ignore * @param descending true to sort the result in descending order (latest location first) */ - public TrackPointIterator getTrackPointLocationIterator(final long trackId, final long startTrackPointId, final boolean descending) { + public TrackPointIterator getTrackPointLocationIterator(final Track.Id trackId, final long startTrackPointId, final boolean descending) { return new TrackPointIterator(this, trackId, startTrackPointId, descending); } @@ -872,7 +872,7 @@ public class ContentProviderUtils { } @VisibleForTesting - public List getTrackPoints(long trackId) { + public List getTrackPoints(Track.Id trackId) { List trackPoints = null; try (Cursor trackPointCursor = getTrackPointCursor(trackId, -1L, -1, false)) { @@ -903,13 +903,23 @@ public class ContentProviderUtils { this.defaultCursorBatchSize = defaultCursorBatchSize; } + + public static String formatIdListForUri(Track.Id... trackIds) { + long[] ids = new long[trackIds.length]; + for (int i = 0; i < trackIds.length; i++) { + ids[i] = trackIds[i].getId(); + } + + return formatIdListForUri(ids); + } + /** * Formats an array of IDs as comma separated string value * * @param ids array with IDs * @return comma separated list of ids */ - public static String formatIdListForUri(long[] ids) { + private static String formatIdListForUri(long[] ids) { StringBuilder idsPathSegment = new StringBuilder(); for (long id : ids) { if (idsPathSegment.length() > 0) { diff --git a/src/main/java/de/dennisguse/opentracks/content/provider/CustomSQLiteOpenHelper.java b/src/main/java/de/dennisguse/opentracks/content/provider/CustomSQLiteOpenHelper.java index 308e39943..0e05d6328 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/CustomSQLiteOpenHelper.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/CustomSQLiteOpenHelper.java @@ -11,6 +11,7 @@ import androidx.annotation.VisibleForTesting; import java.util.UUID; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPointsColumns; import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.data.WaypointsColumns; @@ -162,7 +163,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper { if (cursor.moveToFirst()) { int trackIdIndex = cursor.getColumnIndexOrThrow("_id"); do { - long trackId = cursor.getLong(trackIdIndex); + Track.Id trackId = new Track.Id(cursor.getLong(trackIdIndex)); ContentValues cv = new ContentValues(); cv.put("uuid", UUIDUtils.toBytes(UUID.randomUUID())); db.update("tracks", cv, "_id = ?", new String[]{String.valueOf(trackId)}); diff --git a/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java b/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java index 42a08b07a..33ab57e73 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java @@ -17,8 +17,11 @@ import androidx.annotation.Nullable; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import de.dennisguse.opentracks.android.IContentResolver; import de.dennisguse.opentracks.content.data.Track; @@ -29,9 +32,9 @@ import de.dennisguse.opentracks.io.file.exporter.TrackExporter; /** * A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files. * The actual content of the virtual files is generated by using the functionality defined in {@link CustomContentProvider}. - * + *

* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}. - * + *

* Explanation: * Although a request is handled by a {@link android.content.ContentProvider} (with temporarily granted permission), Android's security infrastructure prevents forwarding queries to non-exported {@link android.content.ContentProvider}. * Thus, if {@link ShareContentProvider} and {@link CustomContentProvider} would be two different instances, the data would not be accessible to external apps. @@ -70,13 +73,19 @@ public class ShareContentProvider extends CustomContentProvider implements ICont uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getName() + "/*/*", URI_KMZ_WITH_TRACKDETAIL_SENSORDATA_AND_PICTURES); } - public static Pair createURI(long[] trackIds, String trackName, @NonNull TrackFileFormat trackFileFormat) { - if (trackIds.length == 0) { + public static Pair createURI(Track.Id trackId, String trackName, @NonNull TrackFileFormat trackFileFormat) { + Set trackIds = new HashSet<>(1); + trackIds.add(trackId); + return createURI(trackIds, trackName, trackFileFormat); + } + + public static Pair createURI(Set trackIds, String trackName, @NonNull TrackFileFormat trackFileFormat) { + if (trackIds.size() == 0) { throw new UnsupportedOperationException(); } StringBuilder trackIdBuilder = new StringBuilder(); - for (long trackId : trackIds) { + for (Track.Id trackId : trackIds) { trackIdBuilder.append(trackId).append(TRACKID_DELIMITER); } trackIdBuilder.deleteCharAt(trackIdBuilder.lastIndexOf(TRACKID_DELIMITER)); @@ -89,18 +98,18 @@ public class ShareContentProvider extends CustomContentProvider implements ICont return new Pair<>(uri, mime); } - static long[] parseURI(Uri uri) { + static Set parseURI(Uri uri) { List uriPaths = uri.getPathSegments(); if (uriPaths == null || uriPaths.size() < 3) { Log.d(TAG, "URI does not contain any trackIds."); - return new long[]{}; + return new HashSet<>(); } String[] uriTrackIds = uriPaths.get(2).split(TRACKID_DELIMITER); - long[] trackIds = new long[uriTrackIds.length]; - for (int i = 0; i < trackIds.length; i++) { - trackIds[i] = Long.parseLong(uriTrackIds[i]); + Set trackIds = new HashSet<>(); + for (String uriTrackId : uriTrackIds) { + trackIds.add(new Track.Id(Long.parseLong(uriTrackId))); } return trackIds; } @@ -202,10 +211,10 @@ public class ShareContentProvider extends CustomContentProvider implements ICont public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); - long[] trackIds = parseURI(uri); - final Track[] tracks = new Track[trackIds.length]; - for (int i = 0; i < trackIds.length; i++) { - tracks[i] = contentProviderUtils.getTrack(trackIds[i]); + Set trackIds = parseURI(uri); + final ArrayList tracks = new ArrayList<>(); + for (Track.Id trackId : trackIds) { + tracks.add(contentProviderUtils.getTrack(trackId)); } final TrackExporter trackExporter = getTrackFileFormat(uri).newTrackExporter(getContext()); diff --git a/src/main/java/de/dennisguse/opentracks/content/provider/TrackPointIterator.java b/src/main/java/de/dennisguse/opentracks/content/provider/TrackPointIterator.java index dfd7cea09..de6735c05 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/TrackPointIterator.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/TrackPointIterator.java @@ -6,6 +6,7 @@ import android.util.Log; import java.util.Iterator; import java.util.NoSuchElementException; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; /** @@ -16,14 +17,14 @@ public class TrackPointIterator implements Iterator, AutoCloseable { private static final String TAG = TrackPointIterator.class.getSimpleName(); private final ContentProviderUtils contentProviderUtils; - private final long trackId; + private final Track.Id trackId; private final boolean descending; private final CachedTrackPointsIndexes indexes; private long lastTrackPointId = -1L; private Cursor cursor; - public TrackPointIterator(ContentProviderUtils contentProviderUtils, long trackId, long startTrackPointId, boolean descending) { + public TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, long startTrackPointId, boolean descending) { this.contentProviderUtils = contentProviderUtils; this.trackId = trackId; this.descending = descending; diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java index 2cdccad8f..2fdb95c5e 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java @@ -25,6 +25,7 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.util.DialogUtils; /** @@ -44,9 +45,9 @@ public class ConfirmDeleteDialogFragment extends DialogFragment { * * @param trackIds list of track ids to delete. */ - public static void showDialog(FragmentManager fragmentManager, long[] trackIds) { + public static void showDialog(FragmentManager fragmentManager, Track.Id... trackIds) { Bundle bundle = new Bundle(); - bundle.putLongArray(KEY_TRACK_IDS, trackIds); + bundle.putParcelableArray(KEY_TRACK_IDS, trackIds); ConfirmDeleteDialogFragment deleteTrackDialogFragment = new ConfirmDeleteDialogFragment(); deleteTrackDialogFragment.setArguments(bundle); @@ -66,7 +67,7 @@ public class ConfirmDeleteDialogFragment extends DialogFragment { @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { - final long[] trackIds = getArguments().getLongArray(KEY_TRACK_IDS); + final Track.Id[] trackIds = (Track.Id[]) getArguments().getParcelableArray(KEY_TRACK_IDS); int titleId = trackIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.track_delete_one_confirm_title; int messageId = trackIds.length > 1 ? R.string.track_delete_multiple_confirm_message : R.string.track_delete_one_confirm_message; @@ -85,6 +86,6 @@ public class ConfirmDeleteDialogFragment extends DialogFragment { */ public interface ConfirmDeleteCaller { - void onConfirmDeleteDone(long[] trackIds); + void onConfirmDeleteDone(Track.Id... trackIds); } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java index 47c352a3b..3d02bbbe5 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java @@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.util.DialogUtils; @@ -41,9 +42,9 @@ public class DeleteMarkerDialogFragment extends DialogFragment { private DeleteMarkerCaller caller; - public static void showDialog(FragmentManager fragmentManager, long[] markerIds) { + public static void showDialog(FragmentManager fragmentManager, Waypoint.Id... waypointIds) { Bundle bundle = new Bundle(); - bundle.putLongArray(KEY_MARKER_IDS, markerIds); + bundle.putParcelableArray(KEY_MARKER_IDS, waypointIds); DeleteMarkerDialogFragment deleteMarkerDialogFragment = new DeleteMarkerDialogFragment(); deleteMarkerDialogFragment.setArguments(bundle); @@ -63,23 +64,23 @@ public class DeleteMarkerDialogFragment extends DialogFragment { @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { - final long[] markerIds = getArguments().getLongArray(KEY_MARKER_IDS); + final Waypoint.Id[] waypointIds = (Waypoint.Id[]) getArguments().getParcelableArray(KEY_MARKER_IDS); final FragmentActivity fragmentActivity = getActivity(); int titleId; int messageId; - if (markerIds.length == 1 && markerIds[0] == -1L) { + if (waypointIds == null) { titleId = R.string.generic_delete_all_confirm_title; messageId = R.string.marker_delete_all_confirm_message; } else { - titleId = markerIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.marker_delete_one_confirm_title; - messageId = markerIds.length > 1 ? R.string.marker_delete_multiple_confirm_message : R.string.marker_delete_one_confirm_message; + titleId = waypointIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.marker_delete_one_confirm_title; + messageId = waypointIds.length > 1 ? R.string.marker_delete_multiple_confirm_message : R.string.marker_delete_one_confirm_message; } return DialogUtils.createConfirmationDialog( fragmentActivity, titleId, getString(messageId), (dialog, which) -> new Thread(() -> { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(fragmentActivity); - for (long markerId : markerIds) { - contentProviderUtils.deleteWaypoint(getContext(), markerId); + for (Waypoint.Id waypointId : waypointIds) { + contentProviderUtils.deleteWaypoint(getContext(), waypointId); } caller.onDeleteMarkerDone(); }).start()); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ImportProgressDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ImportProgressDialogFragment.java index 19638eec5..f6ffdada0 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ImportProgressDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ImportProgressDialogFragment.java @@ -214,7 +214,7 @@ public class ImportProgressDialogFragment extends DialogFragment { } try (InputStream inputStream = context.getContentResolver().openInputStream(file.getUri())) { - return trackImporter.importFile(inputStream) != -1L; + return trackImporter.importFile(inputStream) != null; } catch (IOException e) { Log.e(TAG, "Unable to import file", e); return false; diff --git a/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java index 941f000bb..e9bb726c1 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java @@ -93,9 +93,9 @@ public class MarkerDetailFragment extends Fragment { } }; - public static MarkerDetailFragment newInstance(long markerId) { + public static MarkerDetailFragment newInstance(Waypoint.Id waypointId) { Bundle bundle = new Bundle(); - bundle.putLong(KEY_MARKER_ID, markerId); + bundle.putParcelable(KEY_MARKER_ID, waypointId); MarkerDetailFragment fragment = new MarkerDetailFragment(); fragment.setArguments(bundle); @@ -106,8 +106,8 @@ public class MarkerDetailFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - long markerId = getArguments().getLong(KEY_MARKER_ID); - if (markerId == -1L) { + Waypoint.Id waypointId = getArguments().getParcelable(KEY_MARKER_ID); + if (waypointId == null) { Log.d(TAG, "invalid marker id"); getParentFragmentManager().popBackStack(); return; @@ -182,7 +182,7 @@ public class MarkerDetailFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - long markerId = getArguments().getLong(KEY_MARKER_ID); + Waypoint.Id waypointId = getArguments().getParcelable(KEY_MARKER_ID); //TODO Should only happen in onCreate? FragmentActivity fragmentActivity = getActivity(); Intent intent; switch (item.getItemId()) { @@ -191,7 +191,7 @@ public class MarkerDetailFragment extends Fragment { return true; case R.id.marker_detail_edit: intent = IntentUtils.newIntent(fragmentActivity, MarkerEditActivity.class) - .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerId); + .putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointId); startActivity(intent); return true; case R.id.marker_detail_share: @@ -202,7 +202,7 @@ public class MarkerDetailFragment extends Fragment { } return true; case R.id.marker_detail_delete: - DeleteMarkerDialogFragment.showDialog(getChildFragmentManager(), new long[]{markerId}); + DeleteMarkerDialogFragment.showDialog(getChildFragmentManager(), waypointId); return true; default: return super.onOptionsItemSelected(item); @@ -216,7 +216,7 @@ public class MarkerDetailFragment extends Fragment { */ private void updateWaypoint(boolean refresh) { if (refresh || waypoint == null) { - waypoint = contentProviderUtils.getWaypoint(getArguments().getLong(KEY_MARKER_ID)); + waypoint = contentProviderUtils.getWaypoint(getArguments().getParcelable(KEY_MARKER_ID)); //TODO Should only happen in onCreate? if (waypoint == null) { Log.d(TAG, "waypoint is null"); getParentFragmentManager().popBackStack(); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java index e50d0251c..2573429f8 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java @@ -76,7 +76,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } if (PreferencesUtils.isKey(getContext(), R.string.recording_track_id_key, key)) { recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(getContext()); - if (PreferencesUtils.getRecordingTrackId(getContext()) != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { + if (PreferencesUtils.getRecordingTrackId(getContext()).isValid()) { // A recording track id has been set -> Resumes track and starts timer. resumeTrackDataHub(); trackRecordingServiceConnection.startConnection(getContext()); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java index f850b37c2..69b8ba4b9 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java @@ -98,7 +98,7 @@ public class FileTrackExporter implements TrackExporter { * I am leaving the number of waypoints very high which should not be a problem, because we don't try to load them into objects all at the same time. */ boolean hasWaypoints = false; - try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, ContentProviderUtils.MAX_LOADED_WAYPOINTS_POINTS)) { + try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), null, ContentProviderUtils.MAX_LOADED_WAYPOINTS_POINTS)) { if (cursor != null && cursor.moveToFirst()) { for (int i = 0; i < cursor.getCount(); i++) { if (Thread.interrupted()) { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java index aeaf301c4..7ebee27bf 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmlTrackWriter.java @@ -388,7 +388,7 @@ public class KmlTrackWriter implements TrackWriter { * @param trackId the track id containing the location * @param location the location */ - private float getHeading(long trackId, Location location) { + private float getHeading(Track.Id trackId, Location location) { long trackPointId = contentProviderUtils.getTrackPointId(trackId, location); if (trackPointId == -1L) { return location.getBearing(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java index 5808129c2..bec0346a4 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java @@ -110,7 +110,7 @@ public class KmzTrackExporter implements TrackExporter { private void addImages(Context context, Track[] tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException { for (Track track : tracks) { - try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, -1)) { + try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), null, -1)) { if (cursor != null && cursor.moveToFirst()) { for (int i = 0; i < cursor.getCount(); i++) { if (Thread.interrupted()) { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java index 26630a6d2..93f83240d 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java @@ -68,8 +68,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track private final ContentProviderUtils contentProviderUtils; private final int recordingDistanceInterval; - private long importTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; - private final List trackIds = new ArrayList<>(); + private Track.Id importTrackId; + private final List trackIds = new ArrayList<>(); private final List waypoints = new ArrayList<>(); // The current element content @@ -104,7 +104,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track this.recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context); } - AbstractFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils, long importTrackId) { + AbstractFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils, Track.Id importTrackId) { this(context, contentProviderUtils); this.importTrackId = importTrackId; } @@ -126,7 +126,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } @Override - public long importFile(InputStream inputStream) { + public Track.Id importFile(InputStream inputStream) { try { SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); long start = System.currentTimeMillis(); @@ -140,7 +140,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } catch (MultiTracksImportException | IOException | SAXException | SQLiteConstraintException | ParserConfigurationException e) { Log.e(TAG, "Unable to import file", e); cleanImport(); - return -1L; + return null; } } @@ -153,7 +153,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track if (size == 0) { return; } - long trackId = trackIds.get(size - 1); + Track.Id trackId = trackIds.get(size - 1); Track track = contentProviderUtils.getTrack(trackId); if (track == null) { return; @@ -225,10 +225,10 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track */ protected void onTrackStart() throws SAXException { trackData = new TrackData(); - long trackId; - if (importTrackId == -1L) { + Track.Id trackId; + if (importTrackId == null) { Uri uri = contentProviderUtils.insertTrack(trackData.track); - trackId = Long.parseLong(uri.getLastPathSegment()); + trackId = new Track.Id(Long.parseLong(uri.getLastPathSegment())); } else { if (trackIds.size() > 0) { throw new SAXException(createErrorMessage("Cannot import more than one track to an existing track " + importTrackId)); @@ -399,7 +399,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track * @param externalPhotoUrl the file name */ protected String getInternalPhotoUrl(String externalPhotoUrl) { - if (importTrackId == -1L) { + if (importTrackId == null) { Log.e(TAG, "Track id is invalid."); return null; } @@ -517,7 +517,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track * Cleans up import. */ private void cleanImport() { - for (long trackId : trackIds) { + for (Track.Id trackId : trackIds) { contentProviderUtils.deleteTrack(context, trackId); } } 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 353745a30..853749bad 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 @@ -32,6 +32,7 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter; @@ -52,7 +53,7 @@ public class KmzTrackImporter implements TrackImporter { private static final int BUFFER_SIZE = 4096; private final Context context; - private long importTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + private Track.Id importTrackId; //TODO needed? private final Uri uriKmzFile; /** @@ -65,18 +66,18 @@ public class KmzTrackImporter implements TrackImporter { } @Override - public long importFile(InputStream inputStream) { - long trackId; + public Track.Id importFile(InputStream inputStream) { + Track.Id trackId; if (!copyKmzImages()) { cleanImport(context, importTrackId); - return -1L; + return null; } trackId = findAndParseKmlFile(inputStream); - if (trackId == -1L) { + if (trackId == null) { cleanImport(context, importTrackId); - return -1L; + return null; } deleteOrphanImages(context, trackId); @@ -91,7 +92,7 @@ public class KmzTrackImporter implements TrackImporter { */ private boolean copyKmzImages() { try (InputStream inputStream = context.getContentResolver().openInputStream(uriKmzFile); - ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { + ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { ZipEntry zipEntry; while ((zipEntry = zipInputStream.getNextEntry()) != null) { @@ -140,7 +141,7 @@ public class KmzTrackImporter implements TrackImporter { * Returns true if fileName ends with some of the KMZ_IMAGES_EXT suffixes. * Otherwise returns false. */ - private boolean hasImageExtension(String fileName) { + private boolean hasImageExtension(String fileName) { if (fileName == null) { return false; } @@ -155,27 +156,28 @@ public class KmzTrackImporter implements TrackImporter { /** * Finds KmzTrackExporter.KMZ_KML_FILE file inside kmz file (inputStream) and it parses it. + * TODO: May load multiple tracks, but only returns the last Track.Id. * * @param inputStream kmz input stream. - * @return -1 if error or the id of the track otherwise. + * @return null if error or the id of the track otherwise. */ - private long findAndParseKmlFile(InputStream inputStream) { + private Track.Id findAndParseKmlFile(InputStream inputStream) { try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { ZipEntry zipEntry; - long trackId = -1L; + Track.Id trackId = null; while ((zipEntry = zipInputStream.getNextEntry()) != null) { if (Thread.interrupted()) { Log.d(TAG, "Thread interrupted"); - return -1L; + return null; } String fileName = zipEntry.getName(); if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) { trackId = parseKml(zipInputStream); - if (trackId == -1L) { + if (trackId != null) { Log.d(TAG, "Unable to parse kml in kmz"); - return -1L; + return null; } } @@ -184,7 +186,7 @@ public class KmzTrackImporter implements TrackImporter { return trackId; } catch (IOException e) { Log.e(TAG, "Unable to import file", e); - return -1L; + return null; } } @@ -194,8 +196,8 @@ public class KmzTrackImporter implements TrackImporter { * @param context the Context object. * @param trackId the id of the Track. */ - private void deleteOrphanImages(Context context, long trackId) { - if (trackId != 1L) { + private void deleteOrphanImages(Context context, Track.Id trackId) { + if (!trackId.isValid()) { // 1.- Gets all photo names in the waypoints of the track identified by id. ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); List waypoints = contentProviderUtils.getWaypoints(trackId); @@ -227,7 +229,7 @@ public class KmzTrackImporter implements TrackImporter { * * @param trackId the trackId */ - private void cleanImport(Context context, long trackId) { + private void cleanImport(Context context, Track.Id trackId) { if (PreferencesUtils.isRecording(trackId)) { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); contentProviderUtils.deleteTrack(context, trackId); @@ -240,7 +242,7 @@ public class KmzTrackImporter implements TrackImporter { * @param zipInputStream the zip input stream * @return the imported track id or -1L */ - private long parseKml(ZipInputStream zipInputStream) throws IOException { + private Track.Id parseKml(ZipInputStream zipInputStream) throws IOException { KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context); try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream))) { @@ -271,7 +273,7 @@ public class KmzTrackImporter implements TrackImporter { * @param fileName the file name */ private void readAndSaveImageFile(ZipInputStream zipInputStream, String fileName) throws IOException { - if (importTrackId == -1L || fileName.equals("")) { + if (importTrackId == null || fileName.equals("")) { return; } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index 1525d865a..26259f1af 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -17,6 +17,8 @@ package de.dennisguse.opentracks.io.file.importer; import java.io.InputStream; +import de.dennisguse.opentracks.content.data.Track; + /** * Interface for a track importer. * @@ -28,8 +30,8 @@ public interface TrackImporter { * Import a file. * * @param inputStream the file's input stream - * @return the imported track id or RECORDING_TRACK_ID_DEFAULT. + * @return the imported track id or null. */ //TODO Figure out how can make the import an atomic operation (incl. database transaction rollback). - long importFile(InputStream inputStream); + Track.Id importFile(InputStream inputStream); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 75f2a8239..912344cfd 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -76,7 +76,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand private PeriodicTaskExecutor voiceExecutor; private TrackRecordingServiceNotificationManager notificationManager; - private long recordingTrackId; + private Track.Id recordingTrackId; private boolean recordingTrackPaused; private int recordingDistanceInterval; private int maxRecordingDistance; @@ -138,7 +138,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand notificationManager = new TrackRecordingServiceNotificationManager(this); // onSharedPreferenceChanged might not set recordingTrackId. - recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + recordingTrackId = new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); PreferencesUtils.register(this, sharedPreferenceChangeListener); sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null); @@ -204,7 +204,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand return recordingTrackPaused; } - public long getRecordingTrackId() { + public Track.Id getRecordingTrackId() { return recordingTrackId; } @@ -230,9 +230,9 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand * * @return the waypoint id */ - public long insertWaypoint(String name, String category, String description, String photoUrl) { + public Waypoint.Id insertWaypoint(String name, String category, String description, String photoUrl) { if (!isRecording() || isPaused()) { - return -1L; + return null; } if (name == null) { @@ -246,7 +246,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand TrackPoint trackPoint = getLastValidTrackPointInCurrentSegment(recordingTrackId); if (trackPoint == null) { Log.i(TAG, "Could not create a waypoint as trackPoint is unknown."); - return -1L; + return null; } category = category != null ? category : ""; @@ -261,7 +261,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand // Insert waypoint Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, length, duration, trackPoint.getLocation(), photoUrl); Uri uri = contentProviderUtils.insertWaypoint(waypoint); - return ContentUris.parseId(uri); + return new Waypoint.Id(ContentUris.parseId(uri)); } /** @@ -269,10 +269,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand * * @return the track id */ - long startNewTrack() { + Track.Id startNewTrack() { if (isRecording()) { Log.d(TAG, "Ignore startNewTrack. Already recording."); - return -1L; + return null; } long now = System.currentTimeMillis(); trackStatisticsUpdater = new TrackStatisticsUpdater(now); @@ -280,7 +280,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand // Insert a track Track track = new Track(); Uri uri = contentProviderUtils.insertTrack(track); - long trackId = ContentUris.parseId(uri); + Track.Id trackId = new Track.Id(ContentUris.parseId(uri)); // Update shared preferences updateRecordingState(trackId, false); @@ -305,7 +305,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand * * @param trackId the id of the track to be resumed. */ - void resumeTrack(long trackId) { + void resumeTrack(Track.Id trackId) { Track track = contentProviderUtils.getTrack(trackId); if (track == null) { Log.e(TAG, "Ignore resumeTrack. Track " + trackId + " does not exists."); @@ -333,7 +333,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand if (track == null) { if (isRecording()) { Log.w(TAG, "track is null, but recordingTrackId not -1L. " + recordingTrackId); - updateRecordingState(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, true); + updateRecordingState(new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT), true); } showNotification(false); return; @@ -403,10 +403,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } // Need to remember the recordingTrackId before setting it to -1L - long trackId = recordingTrackId; + Track.Id trackId = recordingTrackId; boolean wasPaused = recordingTrackPaused; - updateRecordingState(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, true); + updateRecordingState(new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT), true); // Update database Track track = contentProviderUtils.getTrack(trackId); @@ -489,7 +489,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand * @param trackId the track id * @return the location or null */ - private TrackPoint getLastValidTrackPointInCurrentSegment(long trackId) { + private TrackPoint getLastValidTrackPointInCurrentSegment(Track.Id trackId) { if (!currentSegmentHasTrackPoint()) { return null; } @@ -507,9 +507,9 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand * @param trackId the recording track id * @param paused true if the recording is paused */ - private void updateRecordingState(long trackId, boolean paused) { + private void updateRecordingState(Track.Id trackId, boolean paused) { recordingTrackId = trackId; - PreferencesUtils.setLong(this, R.string.recording_track_id_key, trackId); + PreferencesUtils.setLong(this, R.string.recording_track_id_key, trackId.getId()); recordingTrackPaused = paused; PreferencesUtils.setBoolean(this, R.string.recording_track_paused_key, recordingTrackPaused); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java index ca633d9f6..5d65c447c 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java @@ -2,7 +2,9 @@ package de.dennisguse.opentracks.services; import androidx.annotation.VisibleForTesting; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager; @@ -43,12 +45,12 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco } @Override - public long startNewTrack() { + public Track.Id startNewTrack() { return trackRecordingService.startNewTrack(); } @Override - public void resumeTrack(long trackId) { + public void resumeTrack(Track.Id trackId) { trackRecordingService.resumeTrack(trackId); } @@ -78,7 +80,7 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco } @Override - public long getRecordingTrackId() { + public Track.Id getRecordingTrackId() { return trackRecordingService.getRecordingTrackId(); } @@ -88,7 +90,7 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco } @Override - public long insertWaypoint(String name, String category, String description, String photoUrl) { + public Waypoint.Id insertWaypoint(String name, String category, String description, String photoUrl) { return trackRecordingService.insertWaypoint(name, category, description, photoUrl); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java index d865ee759..a3c2004f5 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java @@ -31,6 +31,8 @@ import androidx.annotation.NonNull; import de.dennisguse.opentracks.BuildConfig; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.TrackEditActivity; +import de.dennisguse.opentracks.content.data.Track; +import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.PreferencesUtils; @@ -177,18 +179,18 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death /** * Adds a marker. * - * @return the id of the marker or -1L if none could be created. + * @return the id of the marker or null if none could be created. */ - public long addMarker(Context context, String name, String category, String description, String photoUrl) { + public Waypoint.Id addMarker(Context context, String name, String category, String description, String photoUrl) { TrackRecordingServiceInterface trackRecordingService = getServiceIfBound(); if (trackRecordingService == null) { Log.d(TAG, "Unable to add marker, no track recording service"); } else { try { - long markerId = trackRecordingService.insertWaypoint(name, category, description, photoUrl); - if (markerId != -1L) { + Waypoint.Id waypoint = trackRecordingService.insertWaypoint(name, category, description, photoUrl); + if (waypoint != null) { Toast.makeText(context, R.string.marker_add_success, Toast.LENGTH_SHORT).show(); - return markerId; + return waypoint; } } catch (IllegalStateException e) { Log.e(TAG, "Unable to add marker.", e); @@ -196,7 +198,7 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death } Toast.makeText(context, R.string.marker_add_error, Toast.LENGTH_LONG).show(); - return -1L; + return null; } /** @@ -213,7 +215,7 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death try { if (showEditor) { // Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L. - long recordingTrackId = PreferencesUtils.getRecordingTrackId(context); + Track.Id recordingTrackId = PreferencesUtils.getRecordingTrackId(context); trackRecordingService.endCurrentTrack(); if (PreferencesUtils.isRecording(context)) { Intent intent = IntentUtils.newIntent(context, TrackEditActivity.class) diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java index c8068d77c..393888c09 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java @@ -17,7 +17,9 @@ package de.dennisguse.opentracks.services; import androidx.annotation.VisibleForTesting; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager; @@ -43,12 +45,12 @@ public interface TrackRecordingServiceInterface { * * @return the track ID of the new track. */ - long startNewTrack(); + Track.Id startNewTrack(); /** * Resumes the track identified by trackId. */ - void resumeTrack(long trackId); + void resumeTrack(Track.Id trackId); /** * Pauses the current recording track. @@ -78,11 +80,12 @@ public interface TrackRecordingServiceInterface { /** * Gets the current recording track ID. Returns -1 if not recording. */ - long getRecordingTrackId(); + Track.Id getRecordingTrackId(); /** * Gets the total time for the current recording track. Returns 0 if not recording. */ + //TODO milliseconds? long getTotalTime(); /** @@ -90,7 +93,7 @@ public interface TrackRecordingServiceInterface { * * @return the ID of the inserted waypoint */ - long insertWaypoint(String name, String category, String description, String photoUrl); + Waypoint.Id insertWaypoint(String name, String category, String description, String photoUrl); /** * Gets the current sensor data. Returns null if there is no data. diff --git a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java index 56edf48dd..63b2bb60f 100644 --- a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Date; import de.dennisguse.opentracks.BuildConfig; +import de.dennisguse.opentracks.content.data.Track; /** * Utilities for dealing with files. @@ -63,8 +64,8 @@ public class FileUtils { return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); } - public static File getPhotoDir(Context context, long trackId) { - File photoDirectory = new File(getPhotoDir(context), "" + trackId); + public static File getPhotoDir(Context context, Track.Id trackId) { + File photoDirectory = new File(getPhotoDir(context), "" + trackId.getId()); photoDirectory.mkdirs(); return photoDirectory; } @@ -223,7 +224,7 @@ public class FileUtils { * @param context the context. * @param trackId the track id. */ - public static String getImageUrl(Context context, long trackId) { + public static String getImageUrl(Context context, Track.Id trackId) { File dir = FileUtils.getPhotoDir(context, trackId); String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); @@ -267,7 +268,7 @@ public class FileUtils { * @param uri the uri to check. * @return File object or null. */ - public static File getPhotoFileIfExists(Context context, long trackId, Uri uri) { + public static File getPhotoFileIfExists(Context context, Track.Id trackId, Uri uri) { if (uri == null) { Log.w(TAG, "URI object is null."); return null; diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java index 4b1cd1424..9247d3356 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java @@ -8,7 +8,10 @@ import android.net.Uri; import androidx.annotation.NonNull; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPointsColumns; import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.data.WaypointsColumns; @@ -42,7 +45,7 @@ public class IntentDashboardUtils { * @param context the context * @param trackIds the track ids */ - public static void startDashboard(Context context, long[] trackIds, boolean isRecording) { + public static void startDashboard(Context context, boolean isRecording, Track.Id... trackIds) { if (trackIds.length == 0) { return; } @@ -73,14 +76,14 @@ public class IntentDashboardUtils { context.startActivity(intent); } - public static long[] extractTrackIdsFromIntent(@NonNull Intent intent) { + public static Set extractTrackIdsFromIntent(@NonNull Intent intent) { final ArrayList uris = intent.getParcelableArrayListExtra(ACTION_DASHBOARD_PAYLOAD); final Uri tracksUri = uris.get(TRACK_URI_INDEX); String[] trackIdsString = ContentProviderUtils.parseTrackIdsFromUri(tracksUri); - long[] trackIds = new long[trackIdsString.length]; - for (int i = 0; i < trackIdsString.length; i++) { - trackIds[i] = Long.parseLong(trackIdsString[i]); + Set trackIds = new HashSet<>(trackIdsString.length); + for (String s : trackIdsString) { + trackIds.add(new Track.Id(Long.parseLong(s))); } return trackIds; diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java index 38c7930c9..2ae273bf8 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java @@ -67,7 +67,7 @@ public class IntentUtils { * @param context the context * @param trackIds the track ids */ - public static Intent newShareFileIntent(Context context, long[] trackIds) { + public static Intent newShareFileIntent(Context context, Track.Id... trackIds) { if (trackIds.length == 0) { throw new RuntimeException("Need to share at least one track."); } @@ -84,14 +84,14 @@ public class IntentUtils { String mime = ""; ArrayList uris = new ArrayList<>(); - for (long trackId : trackIds) { + for (Track.Id trackId : trackIds) { Track track = contentProviderUtils.getTrack(trackId); if (track == null) { Log.e(TAG, "TrackId " + trackId + " could not be resolved."); continue; } - Pair uriAndMime = ShareContentProvider.createURI(new long[]{trackId}, track.getName(), PreferencesUtils.getExportTrackFileFormat(context)); + Pair uriAndMime = ShareContentProvider.createURI(trackId, track.getName(), PreferencesUtils.getExportTrackFileFormat(context)); uris.add(uriAndMime.first); mime = uriAndMime.second; } @@ -154,7 +154,6 @@ public class IntentUtils { } - /** * Sends a take picture request to the camera app. * The picture is then stored in the track's folder. @@ -162,7 +161,7 @@ public class IntentUtils { * @param context the context * @param trackId the track id */ - public static Pair createTakePictureIntent(Context context, long trackId) { + public static Pair createTakePictureIntent(Context context, Track.Id trackId) { File dir = FileUtils.getPhotoDir(context, trackId); String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); diff --git a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java index d3b812ec1..f50074f90 100644 --- a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java @@ -24,6 +24,7 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceManager; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.io.file.TrackFileFormat; /** @@ -54,9 +55,9 @@ public class PreferencesUtils { public static final long RECORDING_TRACK_ID_DEFAULT = -1L; @Deprecated //Use the TrackRecordingService - public static long getRecordingTrackId(Context context) { + public static Track.Id getRecordingTrackId(Context context) { SharedPreferences sharedPreferences = getSharedPreferences(context); - return sharedPreferences.getLong(getKey(context, R.string.recording_track_id_key), RECORDING_TRACK_ID_DEFAULT); + return new Track.Id(sharedPreferences.getLong(getKey(context, R.string.recording_track_id_key), RECORDING_TRACK_ID_DEFAULT)); } public static String getDefaultActivity(Context context) { @@ -347,14 +348,13 @@ public class PreferencesUtils { @Deprecated //Use TrackRecordingService public static boolean isRecording(Context context) { - long recordingTrackId = getRecordingTrackId(context); - return isRecording(recordingTrackId); + return isRecording(getRecordingTrackId(context)); } @Deprecated //TODO Method is very misleading: it only checks if the provided trackId not the default value (i.e., not recording). - public static boolean isRecording(long recordingTrackId) { - return recordingTrackId != RECORDING_TRACK_ID_DEFAULT; + public static boolean isRecording(Track.Id recordingTrackId) { + return recordingTrackId == null || recordingTrackId.getId() != RECORDING_TRACK_ID_DEFAULT; } public static void resetPreferences(Context context, boolean readAgain) { diff --git a/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java b/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java index eef66640f..a5423f853 100644 --- a/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java @@ -24,6 +24,7 @@ import java.text.SimpleDateFormat; import java.util.Locale; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.content.data.Track; /** * Utilities for track name. @@ -46,7 +47,7 @@ public class TrackNameUtils { * @param trackId the track id * @param startTime the track start time */ - public static String getTrackName(Context context, long trackId, long startTime) { + public static String getTrackName(Context context, Track.Id trackId, long startTime) { String trackName = PreferencesUtils.getString(context, R.string.track_name_key, context.getString(R.string.track_name_default)); if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_local_value))) { @@ -54,7 +55,7 @@ public class TrackNameUtils { } else if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_iso_8601_value))) { return new SimpleDateFormat(ISO_8601_FORMAT, Locale.US).format(startTime); } else { - return context.getString(R.string.track_name_format, trackId); + return context.getString(R.string.track_name_format, trackId.getId()); } } }