diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java index 29a964a87..b3e7d126c 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java @@ -280,7 +280,12 @@ public class SearchEngineTest { } private void assertTrackResults(List results, Track.Id... trackIds) { - String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results; + long[] longTrackIds = new long[trackIds.length]; + for (int i = 0; i < trackIds.length; i++) { + longTrackIds[i] = trackIds[i].getId(); + } + + String errMsg = "Expected IDs=" + Arrays.toString(longTrackIds) + "; results=" + results; Assert.assertEquals(results.size(), trackIds.length); for (int i = 0; i < results.size(); i++) { ScoredResult result = results.get(i); @@ -297,7 +302,12 @@ public class SearchEngineTest { } private void assertWaypointResults(List results, Waypoint.Id... waypointIds) { - String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results; + long[] longWaypointIds = new long[waypointIds.length]; + for (int i = 0; i < waypointIds.length; i++) { + longWaypointIds[i] = waypointIds[i].getId(); + } + + String errMsg = "Expected IDs=" + Arrays.toString(longWaypointIds) + "; results=" + results; Assert.assertEquals(results.size(), waypointIds.length); for (int i = 0; i < results.size(); i++) { ScoredResult result = results.get(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 aa997c84f..30902e9f3 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -23,7 +23,7 @@ public class TestDataUtil { public static Track createTrack(Track.Id trackId) { Track track = new Track(); track.setId(trackId); - track.setName("Test: " + trackId); + track.setName("Test: " + trackId.getId()); return track; } 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 e7e01dbda..6d9ba0167 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/provider/CustomContentProviderUtilsTest.java @@ -135,7 +135,7 @@ public class CustomContentProviderUtilsTest { private long initializeTrack(Track.Id id, int numPoints) { Track track = new Track(); track.setId(id); - track.setName("Test: " + id); + track.setName("Test: " + id.getId()); contentProviderUtils.insertTrack(track); track = contentProviderUtils.getTrack(id); Assert.assertNotNull(track); @@ -173,13 +173,13 @@ public class CustomContentProviderUtilsTest { */ @Test public void testCreateTrack() { - long trackId = System.currentTimeMillis(); + Track.Id trackId = new Track.Id(System.currentTimeMillis()); int columnIndex = 1; // Id when(cursorMock.getColumnIndexOrThrow(TracksColumns._ID)).thenReturn(columnIndex); when(cursorMock.isNull(columnIndex)).thenReturn(false); - when(cursorMock.getLong(columnIndex)).thenReturn(trackId); + when(cursorMock.getLong(columnIndex)).thenReturn(trackId.getId()); //Uuid columnIndex++; @@ -189,7 +189,7 @@ public class CustomContentProviderUtilsTest { // Name columnIndex++; - String name = NAME_PREFIX + trackId; + String name = NAME_PREFIX + trackId.getId(); when(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).thenReturn(columnIndex); when(cursorMock.isNull(columnIndex)).thenReturn(false); when(cursorMock.getString(columnIndex)).thenReturn(name); @@ -468,7 +468,7 @@ public class CustomContentProviderUtilsTest { Waypoint.Id waypointId = new Waypoint.Id(System.currentTimeMillis()); waypoint.setId(waypointId); ContentValues contentValues = contentProviderUtils.createContentValues(waypoint); - Assert.assertEquals(waypointId, contentValues.get(WaypointsColumns._ID)); + Assert.assertEquals(waypointId.getId(), contentValues.get(WaypointsColumns._ID)); Assert.assertEquals((int) (TestDataUtil.INITIAL_LONGITUDE * 1000000), contentValues.get(WaypointsColumns.LONGITUDE)); Assert.assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION)); } @@ -694,7 +694,7 @@ public class CustomContentProviderUtilsTest { waypoint.setTrackId(trackId); Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); - File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); + File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId()); Assert.assertTrue(dir.exists()); Assert.assertTrue(dir.isDirectory()); Assert.assertEquals(1, dir.list().length); @@ -730,7 +730,7 @@ public class CustomContentProviderUtilsTest { waypoint.setTrackId(trackId); Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); - File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); + File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId()); Assert.assertTrue(dir.exists()); Assert.assertTrue(dir.isDirectory()); Assert.assertEquals(1, dir.list().length); @@ -769,7 +769,7 @@ public class CustomContentProviderUtilsTest { Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint))); contentProviderUtils.insertWaypoint(otherWaypoint); - File dir = new File(FileUtils.getPhotoDir(context), "" + trackId); + File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId()); Assert.assertTrue(dir.exists()); Assert.assertTrue(dir.isDirectory()); Assert.assertEquals(2, dir.list().length); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java index 2a240bafb..f3eedbbe4 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.location.Location; import android.os.IBinder; +import android.os.Looper; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -33,6 +34,7 @@ import androidx.test.rule.ServiceTestRule; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -69,6 +71,13 @@ public class TrackRecordingServiceTest { @Rule public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION); + @BeforeClass + public static void preSetUp() { + // Prepare looper for Android's message queue + if (Looper.myLooper() == null) Looper.prepare(); + } + + private final Context context = ApplicationProvider.getApplicationContext(); private ContentProviderUtils contentProviderUtils; @@ -136,7 +145,7 @@ public class TrackRecordingServiceTest { // then // Test if we start in no-recording mode by default. Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertNull(service.getRecordingTrackId()); } @MediumTest @@ -150,7 +159,7 @@ public class TrackRecordingServiceTest { // then Assert.assertFalse(service.isRecording()); - Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); + Assert.assertNull(service.getRecordingTrackId()); } @MediumTest @@ -234,7 +243,7 @@ public class TrackRecordingServiceTest { // then Assert.assertFalse(service.isRecording()); - Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); + Assert.assertNull(service.getRecordingTrackId()); } @MediumTest @@ -251,7 +260,7 @@ public class TrackRecordingServiceTest { Track.Id newTrackId = service.startNewTrack(); // then - Assert.assertNotNull(newTrackId); + Assert.assertNull(newTrackId); Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context)); Assert.assertEquals(trackId, service.getRecordingTrackId()); @@ -270,7 +279,7 @@ public class TrackRecordingServiceTest { // then Assert.assertFalse(PreferencesUtils.isRecording(context)); - Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); + Assert.assertNull(service.getRecordingTrackId()); } @MediumTest diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java index d57a4da05..46f018ef2 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java @@ -228,7 +228,7 @@ public class TrackRecordingServiceTestLooper { // Stop the track. Validate if it has correct data. service.endCurrentTrack(); Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertNull(service.getRecordingTrackId()); track = contentProviderUtils.getTrack(trackId); Assert.assertNotNull(track); Assert.assertEquals(trackId, track.getId()); diff --git a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java index f38f5a1ec..dbd25669e 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java @@ -18,6 +18,9 @@ package de.dennisguse.opentracks; import android.content.Intent; +import java.util.ArrayList; +import java.util.Arrays; + import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller; @@ -76,7 +79,7 @@ public abstract class AbstractListActivity extends AbstractActivity implements C getTrackRecordingServiceConnection().stopRecording(this, false); } Intent intent = IntentUtils.newIntent(this, TrackDeleteActivity.class); - intent.putExtra(TrackDeleteActivity.EXTRA_TRACK_IDS, trackIds); + intent.putParcelableArrayListExtra(TrackDeleteActivity.EXTRA_TRACK_IDS, new ArrayList<>(Arrays.asList(trackIds))); startActivityForResult(intent, DELETE_REQUEST_CODE); overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); } diff --git a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java index ac870b54c..3a7080e63 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java @@ -124,13 +124,13 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker contentProviderUtils = new ContentProviderUtils(this); sharedPreferences = PreferencesUtils.getSharedPreferences(this); - track = !trackId.isValid() ? contentProviderUtils.getTrack(trackId) : null; + track = trackId != null ? contentProviderUtils.getTrack(trackId) : null; listView = findViewById(R.id.marker_list); listView.setEmptyView(findViewById(R.id.marker_list_empty)); listView.setOnItemClickListener((parent, view, position, id) -> { Intent intent = IntentUtils.newIntent(MarkerListActivity.this, MarkerDetailActivity.class) - .putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, id); + .putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, new Waypoint.Id(id)); startActivity(intent); }); resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) { @@ -167,7 +167,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker if (track != null) { return new CursorLoader(MarkerListActivity.this, WaypointsColumns.CONTENT_URI, PROJECTION, WaypointsColumns.TRACKID + "=?", - new String[]{String.valueOf(track.getId())}, null); + new String[]{String.valueOf(track.getId().getId())}, null); } else { return new CursorLoader(MarkerListActivity.this, WaypointsColumns.CONTENT_URI, PROJECTION, null, null, null); @@ -242,8 +242,8 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker /** * Handles a context item selection. * - * @param itemId the menu item id - * @param waypointIds the marker ids + * @param itemId the menu item id + * @param longWaypointIds the marker ids * @return true if handled. */ private boolean handleContextItem(int itemId, long... longWaypointIds) { diff --git a/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java index 51caa3568..baa5bce96 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackDeleteActivity.java @@ -21,6 +21,8 @@ import android.os.Bundle; import android.os.PowerManager; import android.view.View; +import java.util.List; + import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.util.SystemUtils; @@ -34,7 +36,7 @@ public class TrackDeleteActivity extends AbstractActivity { public static final String EXTRA_TRACK_IDS = "track_ids"; - private Track.Id[] trackIds; + private List trackIds; private Thread deleteThread; @@ -45,7 +47,7 @@ public class TrackDeleteActivity extends AbstractActivity { setResult(RESULT_CANCELED); Intent intent = getIntent(); - trackIds = (Track.Id[]) intent.getParcelableArrayExtra(EXTRA_TRACK_IDS); + trackIds = intent.getParcelableArrayListExtra(EXTRA_TRACK_IDS); deleteThread = new Thread(() -> { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(TrackDeleteActivity.this); diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 069ed5e77..f2bf05639 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -105,7 +105,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe // Preferences private boolean metricUnits = true; - private Track.Id recordingTrackId = new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + private Track.Id recordingTrackId = null; // Callback when an item is selected in the contextual action mode private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() { @@ -249,11 +249,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe if (trackId == recordingTrackId.getId()) { // Is recording -> open record activity. newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class) - .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, new Track.Id(trackId)); } else { // Not recording -> open detail activity. newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordedActivity.class) - .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, new Track.Id(trackId)); } startActivity(newIntent); }); @@ -479,8 +479,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe /** * Handles a context item selection. * - * @param itemId the menu item id - * @param trackIds the track ids + * @param itemId the menu item id + * @param longTrackIds the track ids * @return true if handled. */ private boolean handleContextItem(int itemId, long... longTrackIds) { diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java index 530f5d300..35fa3ab0a 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java @@ -133,7 +133,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos // Update UI this.invalidateOptionsMenu(); - if (!trackId.isValid()) { + if (trackId.isValid()) { trackDataHub.loadTrack(trackId); } } @@ -251,7 +251,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos trackId = waypoint.getTrackId(); } - if (!trackId.isValid()) { + if (trackId == null) { 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 6384a9f50..fda11f21f 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java @@ -167,7 +167,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc trackId = savedInstanceState.getParcelable(EXTRA_TRACK_ID); } else { trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); - if (contentProviderUtils.getTrack(trackId) == null) { + if (trackId != null && contentProviderUtils.getTrack(trackId) == null) { + Log.w(TAG, "TrackId does not exists; cannot continue the recording."); finish(); } } @@ -247,7 +248,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc // Update UI this.invalidateOptionsMenu(); - if (!trackId.isValid()) { + if (trackId != null) { trackDataHub.loadTrack(trackId); trackController.onResume(true, recordingTrackPaused); } diff --git a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java index dc37ed418..79c5bc8c5 100644 --- a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java +++ b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java @@ -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.isValid() && waypoint.getTrackId().equals(query.currentTrackId)) { + if (waypoint.getTrackId() != null && waypoint.getTrackId().equals(query.currentTrackId)) { score *= CURRENT_TRACK_WAYPOINT_PROMOTION; } @@ -417,8 +417,8 @@ public class SearchEngine { @Override public String toString() { return "ScoredResult [" - + (track != null ? ("trackId=" + track.getId() + ", ") : "") - + (waypoint != null ? ("wptId=" + waypoint.getId() + ", ") : "") + + (track != null ? ("trackId=" + track.getId().getId() + ", ") : "") + + (waypoint != null ? ("wptId=" + waypoint.getId().getId() + ", ") : "") + "score=" + score + "]"; } } diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java index feb60bf1e..8d30c808c 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import java.util.Collections; @@ -174,10 +175,10 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL handler = null; } - public void loadTrack(final Track.Id trackId) { + public void loadTrack(final @NonNull Track.Id trackId) { runInHandlerThread(() -> { - if (trackId == selectedTrackId) { - Log.i(TAG, "Not reloading track " + trackId); + if (trackId.equals(selectedTrackId)) { + Log.i(TAG, "Not reloading track " + trackId.getId()); return; } selectedTrackId = trackId; @@ -212,14 +213,14 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL * Returns true if the selected track is recording. */ public boolean isSelectedTrackRecording() { - return selectedTrackId == recordingTrackId && PreferencesUtils.isRecording(recordingTrackId); + return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && PreferencesUtils.isRecording(recordingTrackId); } /** * Returns true if the selected track is paused. */ public boolean isSelectedTrackPaused() { - return selectedTrackId == recordingTrackId && recordingTrackPaused; + return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && recordingTrackPaused; } @Override @@ -356,6 +357,11 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L; long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId; + if (selectedTrackId == null) { + Log.w(TAG, "This should not happen, but it does"); //TODO + return; + } + long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId); int samplingFrequency = -1; boolean includeNextPoint = false; 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 111798649..70edf69a1 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/Track.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/Track.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.util.Objects; import java.util.UUID; @@ -49,7 +50,11 @@ public class Track { public Track() { } - public Id getId() { + /** + * May be null if the track was not loaded from the database. + */ + public @Nullable + Id getId() { return id; } @@ -122,6 +127,7 @@ public class Track { return id; } + @Deprecated //TODO Use a Track.Id of null instead public boolean isValid() { return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; } @@ -144,6 +150,12 @@ public class Track { return 0; } + @NonNull + @Override + public String toString() { + throw new RuntimeException("Not supported"); + } + @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeLong(id); 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 c76266611..a0ac55e26 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/Waypoint.java @@ -22,6 +22,7 @@ import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.util.Objects; @@ -69,7 +70,11 @@ public final class Waypoint { this.photoUrl = photoUrl; } - public Id getId() { + /** + * May be null if the waypoint was not loaded from the database. + */ + public @Nullable + Id getId() { return id; } @@ -171,6 +176,7 @@ public final class Waypoint { return id; } + @Deprecated //TODO Use a Waypoint.Id of null instead public boolean isValid() { return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; } @@ -188,6 +194,12 @@ public final class Waypoint { return Objects.hash(id); } + @NonNull + @Override + public String toString() { + throw new RuntimeException("Not supported"); + } + @Override public int describeContents() { return 0; 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 de48645e2..5c1c4b15e 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ContentProviderUtils.java @@ -23,6 +23,7 @@ import android.database.Cursor; import android.location.Location; import android.net.Uri; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -186,6 +187,9 @@ public class ContentProviderUtils { * @param trackId the track id */ public void deleteTrack(Context context, Track.Id trackId) { + if (trackId == null) { + return; + } deleteTrackPointsAndWaypoints(trackId); // Delete track folder resources. @@ -200,7 +204,7 @@ public class ContentProviderUtils { * * @param trackId the track id */ - private void deleteTrackPointsAndWaypoints(Track.Id trackId) { + private void deleteTrackPointsAndWaypoints(@NonNull Track.Id trackId) { String[] selectionArgs = new String[]{Long.toString(trackId.getId())}; contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, TrackPointsColumns.TRACKID + "=?", selectionArgs); @@ -297,7 +301,7 @@ public class ContentProviderUtils { TrackStatistics trackStatistics = track.getTrackStatistics(); // Value < 0 indicates no id is available - if (track.getId().isValid()) { + if (track.getId() != null && track.getId().isValid()) { values.put(TracksColumns._ID, track.getId().getId()); } values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid())); @@ -513,7 +517,7 @@ public class ContentProviderUtils { * @param waypoint the waypoint * @return the content provider URI of the inserted waypoint. */ - public Uri insertWaypoint(Waypoint waypoint) { + public Uri insertWaypoint(@NonNull Waypoint waypoint) { waypoint.setId(null); return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint)); } @@ -556,14 +560,16 @@ public class ContentProviderUtils { ContentValues createContentValues(@NonNull Waypoint waypoint) { ContentValues values = new ContentValues(); - if (waypoint.getId().isValid()) { + if (waypoint.getId() != null && 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().getId()); + if (waypoint.getTrackId() != null) { + values.put(WaypointsColumns.TRACKID, waypoint.getTrackId().getId()); + } values.put(WaypointsColumns.LENGTH, waypoint.getLength()); values.put(WaypointsColumns.DURATION, waypoint.getDuration()); @@ -693,7 +699,8 @@ public class ContentProviderUtils { */ @Deprecated public long getLastTrackPointId(Track.Id trackId) { - if (!trackId.isValid()) { + if (trackId == null || !trackId.isValid()) { + Log.w(TAG, "Fix callers who do this."); return -1L; } String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.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 33ab57e73..fe92aff97 100644 --- a/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/provider/ShareContentProvider.java @@ -86,7 +86,7 @@ public class ShareContentProvider extends CustomContentProvider implements ICont StringBuilder trackIdBuilder = new StringBuilder(); for (Track.Id trackId : trackIds) { - trackIdBuilder.append(trackId).append(TRACKID_DELIMITER); + trackIdBuilder.append(trackId.getId()).append(TRACKID_DELIMITER); } trackIdBuilder.deleteCharAt(trackIdBuilder.lastIndexOf(TRACKID_DELIMITER)); @@ -221,7 +221,7 @@ public class ShareContentProvider extends CustomContentProvider implements ICont PipeDataWriter pipeDataWriter = (output, uri1, mimeType, opts, args) -> { try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) { - trackExporter.writeTrack(tracks, fileOutputStream); + trackExporter.writeTrack(tracks.toArray(new Track[0]), fileOutputStream); } catch (IOException e) { Log.w(TAG, "there occurred an error while sharing a file: " + e); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 912344cfd..3d2e877d4 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -138,7 +138,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand notificationManager = new TrackRecordingServiceNotificationManager(this); // onSharedPreferenceChanged might not set recordingTrackId. - recordingTrackId = new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + recordingTrackId = null; PreferencesUtils.register(this, sharedPreferenceChangeListener); sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null); @@ -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(new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT), true); + updateRecordingState(null, true); } showNotification(false); return; @@ -406,7 +406,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand Track.Id trackId = recordingTrackId; boolean wasPaused = recordingTrackPaused; - updateRecordingState(new Track.Id(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT), true); + updateRecordingState(null, true); // Update database Track track = contentProviderUtils.getTrack(trackId); @@ -509,7 +509,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand */ private void updateRecordingState(Track.Id trackId, boolean paused) { recordingTrackId = trackId; - PreferencesUtils.setLong(this, R.string.recording_track_id_key, trackId.getId()); + long currentTrackId = trackId != null ? trackId.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + PreferencesUtils.setLong(this, R.string.recording_track_id_key, currentTrackId); recordingTrackPaused = paused; PreferencesUtils.setBoolean(this, R.string.recording_track_paused_key, recordingTrackPaused); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java index 393888c09..79baa5827 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java @@ -78,7 +78,7 @@ public interface TrackRecordingServiceInterface { boolean isPaused(); /** - * Gets the current recording track ID. Returns -1 if not recording. + * Gets the current recording track ID. Returns null if not recording. */ Track.Id getRecordingTrackId(); diff --git a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java index f50074f90..4459c4e7e 100644 --- a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java @@ -354,7 +354,10 @@ public class PreferencesUtils { @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(Track.Id recordingTrackId) { - return recordingTrackId == null || recordingTrackId.getId() != RECORDING_TRACK_ID_DEFAULT; + if (recordingTrackId == null) { + return false; + } + return recordingTrackId.getId() != RECORDING_TRACK_ID_DEFAULT; } public static void resetPreferences(Context context, boolean readAgain) {