From 6723bfb979c3d4fa89c7d37816f0e461fd6d4efc Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Thu, 29 Apr 2021 18:22:35 +0200 Subject: [PATCH] TrackRecordingService: provide status updates via LiveData. Fixes #719 --- .../TrackRecordingServiceTestLocation.java | 1 + .../opentracks/AbstractListActivity.java | 17 ++- .../opentracks/MarkerListActivity.java | 32 +++-- .../opentracks/TrackController.java | 43 +++--- .../opentracks/TrackListActivity.java | 82 +++++------- .../opentracks/TrackRecordedActivity.java | 28 ++-- .../opentracks/TrackRecordingActivity.java | 63 ++++----- .../opentracks/content/TrackDataHub.java | 21 +-- .../services/TrackRecordingService.java | 123 +++++++++++++----- .../services/TrackRecordingServiceStatus.java | 83 ------------ .../services/handlers/GpsStatusValue.java | 4 + .../opentracks/settings/SettingsActivity.java | 23 ++-- 12 files changed, 246 insertions(+), 274 deletions(-) delete mode 100644 src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceStatus.java diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java index 8ef1d8559..ae1330814 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLocation.java @@ -44,6 +44,7 @@ import static org.junit.Assert.assertNotNull; * So, if it is executed on a real device, data might be lost. */ @RunWith(AndroidJUnit4.class) +//TODO Implement as mock test; no need to store data in database public class TrackRecordingServiceTestLocation { @Rule diff --git a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java index 1d7dc9162..f0d7066ea 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java @@ -18,6 +18,8 @@ package de.dennisguse.opentracks; import android.content.Intent; +import androidx.annotation.Nullable; + import java.util.ArrayList; import java.util.Arrays; @@ -36,6 +38,8 @@ import de.dennisguse.opentracks.util.IntentUtils; * * @author Jimmy Shih */ +//TODO It is actually not a List; we need a better name for this class +//TODO Check if this class is still such a good idea; inheritance might limit maintainability public abstract class AbstractListActivity extends AbstractActivity implements ConfirmDeleteCaller { private static final String TAG = AbstractListActivity.class.getSimpleName(); @@ -43,8 +47,6 @@ public abstract class AbstractListActivity extends AbstractActivity implements C protected static final int GPS_REQUEST_CODE = 6; private static final int DELETE_REQUEST_CODE = 3; - protected Track.Id recordingTrackId; - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == DELETE_REQUEST_CODE) { @@ -68,7 +70,7 @@ public abstract class AbstractListActivity extends AbstractActivity implements C boolean stopRecording = false; for (Track.Id trackId : trackIds) { - if (trackId.equals(recordingTrackId)) { + if (trackId.equals(getRecordingTrackId())) { stopRecording = true; break; } @@ -87,10 +89,17 @@ public abstract class AbstractListActivity extends AbstractActivity implements C * Gets the track recording service connection. * For stopping the current recording if need to delete the current recording track. */ - abstract protected TrackRecordingServiceConnection getTrackRecordingServiceConnection(); + protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() { + return null; + } /** * Called after {@link TrackDeleteActivity} returns its result. */ abstract protected void onTrackDeleted(); + + @Nullable + protected Track.Id getRecordingTrackId() { + return null; + } } diff --git a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java index 8044b3ee1..4053334eb 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java @@ -20,6 +20,7 @@ import android.app.SearchManager; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; +import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; @@ -42,7 +43,6 @@ import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.services.TrackRecordingServiceStatus; import de.dennisguse.opentracks.util.ActivityUtils; import de.dennisguse.opentracks.util.IntentUtils; @@ -51,7 +51,7 @@ import de.dennisguse.opentracks.util.IntentUtils; * * @author Leif Hendrik Wilden */ -public class MarkerListActivity extends AbstractActivity implements DeleteMarkerCaller, TrackRecordingServiceStatus.Listener { +public class MarkerListActivity extends AbstractActivity implements DeleteMarkerCaller { public static final String EXTRA_TRACK_ID = "track_id"; @@ -59,8 +59,8 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker private ContentProviderUtils contentProviderUtils; - private Track.Id recordingTrackId; - private boolean recordingTrackPaused; + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; + private Track track; private MarkerResourceCursorAdapter resourceCursorAdapter; @@ -74,9 +74,13 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker @Override public void run() { TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound(); - if (service != null) { - service.addListener(MarkerListActivity.this); + if (service == null) { + Log.w(TAG, "could not get TrackRecordingService"); + return; } + + service.getRecordingStatusObservable() + .observe(MarkerListActivity.this, status -> onRecordingStatusChanged(status)); } }; @@ -178,7 +182,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker @Override public boolean onPrepareOptionsMenu(Menu menu) { - insertMarkerMenuItem.setVisible(track != null && track.getId().equals(recordingTrackId) && !recordingTrackPaused); + insertMarkerMenuItem.setVisible(track != null && track.getId().equals(recordingStatus.getTrackId()) && !recordingStatus.isPaused()); return super.onPrepareOptionsMenu(menu); } @@ -290,6 +294,10 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker // Do nothing } + private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { + recordingStatus = status; + } + private class MarkerLoaderCallback implements LoaderManager.LoaderCallbacks { private String searchQuery = null; @@ -344,14 +352,4 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker resourceCursorAdapter.swapCursor(null); } } - - @Override - public void onTrackRecordingPaused(boolean isPaused) { - recordingTrackPaused = isPaused; - } - - @Override - public void onTrackRecordingId(Track.Id trackId) { - recordingTrackId = trackId; - } } diff --git a/src/main/java/de/dennisguse/opentracks/TrackController.java b/src/main/java/de/dennisguse/opentracks/TrackController.java index fe34a3f2b..79a1acf94 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackController.java +++ b/src/main/java/de/dennisguse/opentracks/TrackController.java @@ -37,6 +37,8 @@ import de.dennisguse.opentracks.util.StringUtils; * * @author Jimmy Shih */ +//TODO Subscribe to TrackRecordingService.recordingStatus +//TODO Could be a fragment public class TrackController implements View.OnTouchListener { private static final String TAG = TrackController.class.getSimpleName(); @@ -54,17 +56,16 @@ public class TrackController implements View.OnTouchListener { private final TrackControllerBinding viewBinding; private final TransitionDrawable transition; - private boolean isRecording; - private boolean isRecordingPaused; + + private TrackRecordingService.RecordingStatus recordingStatus; private Duration totalTime; - private boolean isResumed = false; private final Callback callback; // A runnable to update the total time. private final Runnable updateTotalTimeRunnable = new Runnable() { public void run() { - if (isResumed && isRecording && !isRecordingPaused) { + if (isResumed() && recordingStatus.isRecordingAndNotPaused()) { updateTotalTime(); setTotalTime(); handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis()); @@ -84,7 +85,7 @@ public class TrackController implements View.OnTouchListener { viewBinding.trackControllerRecord.setOnTouchListener(this); viewBinding.trackControllerRecord.setOnClickListener((view) -> { - if (buttonDelay != null || (isRecording && !isRecordingPaused)) { + if (buttonDelay != null || recordingStatus.isRecordingAndNotPaused()) { return; } @@ -120,7 +121,7 @@ public class TrackController implements View.OnTouchListener { //To pause a recording if (viewBinding.trackControllerRecord.equals(view) && event.getAction() == MotionEvent.ACTION_DOWN - && isRecording && !isRecordingPaused) { + && recordingStatus.isRecordingAndNotPaused()) { transition.startTransition(buttonDelayDuration); @@ -143,7 +144,7 @@ public class TrackController implements View.OnTouchListener { //To stop a recording if (viewBinding.trackControllerStop.equals(view) && event.getAction() == MotionEvent.ACTION_DOWN - && isRecording) { + && recordingStatus.isRecording()) { transition.startTransition(buttonDelayDuration); @@ -165,13 +166,15 @@ public class TrackController implements View.OnTouchListener { return false; } - public void update(boolean recording, boolean paused) { - if (!isResumed) { + public void update(TrackRecordingService.RecordingStatus recordingStatus) { + if (!isResumed()) { handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable); return; } - isRecording = recording; - isRecordingPaused = paused; + + this.recordingStatus = recordingStatus; + boolean isRecording = recordingStatus.isRecording(); + boolean isRecordingPaused = recordingStatus.isPaused(); boolean visible = alwaysShow || isRecording; viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE); @@ -197,19 +200,19 @@ public class TrackController implements View.OnTouchListener { viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE); - if (isRecording) { + if (recordingStatus.isRecording()) { updateTotalTime(); setTotalTime(); } } - void onResume(boolean recording, boolean paused) { - isResumed = true; - update(recording, paused); + void onResume(TrackRecordingService.RecordingStatus recordingStatus) { + this.recordingStatus = recordingStatus; + update(recordingStatus); } void onPause() { - isResumed = false; + recordingStatus = null; handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable); } @@ -235,12 +238,18 @@ public class TrackController implements View.OnTouchListener { } private void showStatusSetDefaultText() { - viewBinding.trackControllerStatus.setText(isRecordingPaused ? R.string.generic_paused : R.string.generic_recording); + viewBinding.trackControllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording); + } + + private boolean isResumed() { + return recordingStatus != null; } public interface Callback { void recordStart(); + void recordPause(); + void recordStop(); } } diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 538c1ee52..07ea5b701 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -38,6 +38,7 @@ import android.view.View; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; @@ -55,7 +56,6 @@ import de.dennisguse.opentracks.databinding.TrackListBinding; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.services.TrackRecordingServiceStatus; import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.ActivityUtils; @@ -71,7 +71,7 @@ import de.dennisguse.opentracks.util.TrackIconUtils; * * @author Leif Hendrik Wilden */ -public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackController.Callback, TrackRecordingServiceStatus.Listener { +public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackController.Callback { private static final String TAG = TrackListActivity.class.getSimpleName(); @@ -80,7 +80,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackController trackController; private ResourceCursorAdapter resourceCursorAdapter; - private GpsStatusValue gpsStatusValue; private TrackListBinding viewBinding; @@ -89,7 +88,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe // Preferences private boolean metricUnits = true; - private boolean recordingTrackPaused = true; + private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT; + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; // Callback when an item is selected in the contextual action mode private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() { @@ -118,7 +118,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe runOnUiThread(() -> { TrackListActivity.this.invalidateOptionsMenu(); loaderCallbacks.restart(); - trackController.update(isRecording(), recordingTrackPaused); + trackController.onResume(recordingStatus); }); } } @@ -133,27 +133,29 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe @Override public void run() { // After binding changes (e.g., becomes available), update the total time in trackController. - runOnUiThread(() -> trackController.update(isRecording(), recordingTrackPaused)); + runOnUiThread(() -> trackController.update(recordingStatus)); TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound(); if (service == null) { - Log.d(TAG, "service not available to start gps or a new recording"); - gpsStatusValue = GpsStatusValue.GPS_NONE; + Log.e(TAG, "service not available to start gps or a new recording"); return; } + service.getRecordingStatusObservable() + .observe(TrackListActivity.this, status -> onRecordingStatusChanged(status)); + // Get GPS status and listen GPS status changes. - gpsStatusValue = service.getGpsStatus(); - updateGpsMenuItem(true, isRecording()); - service.addListener(TrackListActivity.this); + service.getGpsStatusObservable() + .observe(TrackListActivity.this, status -> onGpsStatusChanged(status)); - if (isGpsStarted()) { + updateGpsMenuItem(true, recordingStatus.isRecording()); + + if (service.getGpsStatusObservable().getValue().isGpsStarted()) { return; } + //TODO Not cool to do this in a callback that might be called more than once! service.tryStartGps(); - gpsStatusValue = GpsStatusValue.GPS_ENABLED; - updateGpsMenuItem(true, isRecording()); } }; @@ -165,8 +167,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe super.onCreate(savedInstanceState); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); - gpsStatusValue = GpsStatusValue.GPS_NONE; - sharedPreferences = PreferencesUtils.getSharedPreferences(this); trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback); @@ -181,7 +181,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe viewBinding.trackList.setEmptyView(viewBinding.trackListEmptyView); viewBinding.trackList.setOnItemClickListener((parent, view, position, trackId) -> { - if (isRecording() && trackId == recordingTrackId.getId()) { + if (recordingStatus.isRecording() && trackId == recordingStatus.getTrackId().getId()) { // Is recording -> open record activity. Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class) .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, new Track.Id(trackId)); @@ -211,7 +211,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe int markerCountIndex = cursor.getColumnIndexOrThrow(TracksColumns.MARKER_COUNT); Track.Id trackId = new Track.Id(cursor.getLong(idIndex)); - boolean isRecording = trackId.equals(recordingTrackId); + boolean isRecording = trackId.equals(recordingStatus.getTrackId()); String icon = cursor.getString(iconIndex); int iconId = TrackIconUtils.getIconDrawable(icon); String name = cursor.getString(nameIndex); @@ -222,7 +222,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex); String description = cursor.getString(descriptionIndex); - ListItemUtils.setListItem(TrackListActivity.this, view, isRecording, recordingTrackPaused, + ListItemUtils.setListItem(TrackListActivity.this, view, isRecording, recordingStatus.isPaused(), iconId, R.string.image_track, name, totalTime, totalDistance, markerCount, startTime, true, category, description, false); } @@ -265,7 +265,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe // Update UI this.invalidateOptionsMenu(); LoaderManager.getInstance(this).restartLoader(0, null, loaderCallbacks); - trackController.onResume(isRecording(), recordingTrackPaused); + trackController.onResume(recordingStatus); } @Override @@ -306,7 +306,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe @Override public boolean onPrepareOptionsMenu(Menu menu) { - updateMenuItems(isGpsStarted(), isRecording()); + updateMenuItems(gpsStatusValue.isGpsStarted(), recordingStatus.isRecording()); SearchView searchView = (SearchView) searchMenuItem.getActionView(); searchView.setQuery("", false); @@ -322,7 +322,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); } else { // Invoke trackRecordingService - if (!isGpsStarted()) { + if (!gpsStatusValue.isGpsStarted()) { trackRecordingServiceConnection.startAndBind(this); bindChangedCallback.run(); } else { @@ -413,8 +413,10 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe // Do nothing } - private boolean isGpsStarted() { - return gpsStatusValue != GpsStatusValue.GPS_NONE && gpsStatusValue != GpsStatusValue.GPS_DISABLED; + @Nullable + @Override + protected Track.Id getRecordingTrackId() { + return recordingStatus.getTrackId(); } private void requestGPSPermissions() { @@ -554,16 +556,15 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe @Override public void recordStart() { - if (recordingTrackId == null) { + if (recordingStatus.getTrackId() == null) { // Not recording -> Recording updateMenuItems(false, true); Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class); startActivity(newIntent); - } else if (recordingTrackPaused) { + } else if (recordingStatus.isPaused()) { // Paused -> Resume updateMenuItems(false, true); trackRecordingServiceConnection.resumeTrack(); - trackController.update(true, false); } } @@ -571,7 +572,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe public void recordPause() { updateMenuItems(false, true); trackRecordingServiceConnection.pauseTrack(); - trackController.update(true, true); } @Override @@ -580,29 +580,15 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe trackRecordingServiceConnection.stopRecording(TrackListActivity.this); } - private boolean isRecording() { - return recordingTrackId != null; - } - - @Override - public void onGpsStatus(GpsStatusValue newStatus) { + public void onGpsStatusChanged(GpsStatusValue newStatus) { gpsStatusValue = newStatus; - updateGpsMenuItem(true, isRecording()); + updateGpsMenuItem(true, recordingStatus.isRecording()); } - @Override - public void onTrackRecordingPaused(boolean isPaused) { - if (recordingTrackPaused != isPaused) { - trackController.update(isRecording(), isPaused); - } - recordingTrackPaused = isPaused; - } - @Override - public void onTrackRecordingId(Track.Id trackId) { - if (!isRecording() && trackId != null) { - trackController.update(true, recordingTrackPaused); - } - recordingTrackId = trackId; + private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { + recordingStatus = status; + + trackController.update(recordingStatus); } } diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java index 72e8d884b..e82e757ca 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java @@ -24,6 +24,7 @@ import android.view.MenuItem; import android.view.View; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; @@ -42,7 +43,6 @@ import de.dennisguse.opentracks.fragments.IntervalsFragment; import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.services.TrackRecordingServiceStatus; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentUtils; @@ -54,7 +54,7 @@ import de.dennisguse.opentracks.util.IntentUtils; * @author Rodrigo Damazio */ //TODO Should not use TrackRecordingServiceConnection; only used to determine if there is NO current recording, to enable resume functionality. -public class TrackRecordedActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackActivityDataHubInterface, TrackRecordingServiceStatus.Listener { +public class TrackRecordedActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackActivityDataHubInterface { private static final String TAG = TrackRecordedActivity.class.getSimpleName(); @@ -72,6 +72,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi private TrackRecordedBinding viewBinding; private Track.Id trackId; + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private TrackRecordingServiceConnection trackRecordingServiceConnection; @@ -79,9 +80,14 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi @Override public void run() { TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound(); - if (service != null) { - service.addListener(TrackRecordedActivity.this); + if (service == null) { + Log.w(TAG, "could not get TrackRecordingService"); + return; } + + service.getRecordingStatusObservable() + .observe(TrackRecordedActivity.this, status -> onRecordingStatusChanged(status)); + } }; @@ -162,7 +168,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.track_detail_markers).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - menu.findItem(R.id.track_detail_resume_track).setVisible(recordingTrackId == null); + menu.findItem(R.id.track_detail_resume_track).setVisible(!recordingStatus.isRecording()); Track track = contentProviderUtils.getTrack(trackId); setTitle(track != null ? track.getName() : ""); return super.onPrepareOptionsMenu(menu); @@ -217,12 +223,13 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi return super.onOptionsItemSelected(item); } + @Nullable @Override - protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() { - // Not needed. - return null; + protected Track.Id getRecordingTrackId() { + return recordingStatus.getTrackId(); } + @Override protected void onTrackDeleted() { runOnUiThread(this::finish); @@ -305,8 +312,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi startPostponedEnterTransition(); } - @Override - public void onTrackRecordingId(Track.Id trackId) { - recordingTrackId = trackId; + private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { + recordingStatus = status; } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java index 8f823e0c7..01f364493 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java @@ -28,7 +28,6 @@ import de.dennisguse.opentracks.fragments.IntervalsFragment; import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.services.TrackRecordingServiceStatus; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentUtils; @@ -44,7 +43,7 @@ import de.dennisguse.opentracks.util.TrackUtils; */ //NOTE: This activity does NOT react to preference changes of R.string.recording_track_id_key. //This mode of communication should be removed anyhow. -public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, TrackController.Callback, TrackRecordingServiceStatus.Listener { +public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, TrackController.Callback { public static final String EXTRA_TRACK_ID = "track_id"; @@ -62,20 +61,23 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc private TrackRecordingBinding viewBinding; // Initialized from Intent; if a new track recording is started, a new TrackId will be provided by TrackRecordingService + @Deprecated private Track.Id trackId; - private boolean recordingTrackPaused; + + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private final Runnable bindChangedCallback = new Runnable() { @Override public void run() { - // After binding changes (is available), update the total time in trackController. - runOnUiThread(() -> trackController.update(true, recordingTrackPaused)); - TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound(); if (service == null) { - Log.d(TAG, "could not get TrackRecordingService"); + Log.w(TAG, "could not get TrackRecordingService"); return; } + + service.getRecordingStatusObservable() + .observe(TrackRecordingActivity.this, status -> onRecordingStatusChanged(status)); + if (!service.isRecording()) { if (trackId == null) { // trackId isn't initialized -> leads a new recording. @@ -87,12 +89,10 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc // A recording track is on. trackDataHub.loadTrack(trackId); - trackDataHub.setRecordingTrackId(trackId); + trackDataHub.setRecordingStatus(recordingStatus); - trackController.update(true, false); - trackController.onResume(true, recordingTrackPaused); + trackController.onResume(recordingStatus); } - service.addListener(TrackRecordingActivity.this); } }; @@ -109,10 +109,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc setFullscreenPolicy(); } if (key == null) return; - runOnUiThread(() -> { - TrackRecordingActivity.this.invalidateOptionsMenu(); - trackController.update(true, recordingTrackPaused); - }); + + runOnUiThread(TrackRecordingActivity.this::invalidateOptionsMenu); } }; @@ -207,13 +205,13 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc super.onResume(); // Update UI - this.invalidateOptionsMenu(); + invalidateOptionsMenu(); if (trackId != null) { + //TODO Pass recordingStatus directly to them trackDataHub.loadTrack(trackId); - trackDataHub.setRecordingTrackId(trackId); - trackDataHub.setRecordingTrackPaused(recordingTrackPaused); - trackController.onResume(true, recordingTrackPaused); + trackDataHub.setRecordingStatus(recordingStatus); + trackController.onResume(recordingStatus); } /* @@ -264,7 +262,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc @Override public boolean onPrepareOptionsMenu(Menu menu) { - updateMenuItems(recordingTrackPaused); + updateMenuItems(recordingStatus.isPaused()); return super.onPrepareOptionsMenu(menu); } @@ -339,14 +337,12 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc public void recordStart() { updateMenuItems(false); trackRecordingServiceConnection.resumeTrack(); - trackController.update(true, false); } @Override public void recordPause() { updateMenuItems(true); trackRecordingServiceConnection.pauseTrack(); - trackController.update(true, true); } @Override @@ -404,24 +400,13 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc } } - @Override - public void onTrackRecordingPaused(boolean isPaused) { - if (recordingTrackPaused != isPaused) { - trackController.update(true, isPaused); - trackDataHub.setRecordingTrackPaused(isPaused); - } - recordingTrackPaused = isPaused; + private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { + recordingStatus = status; + + trackController.update(recordingStatus); + trackDataHub.setRecordingStatus(recordingStatus); + setLockscreenPolicy(); setScreenOnPolicy(); } - - //TODO Why should this be interesting? This activity is only used for currently recording tracks. - @Override - public void onTrackRecordingId(Track.Id newTrackId) { - if (newTrackId != null && !newTrackId.equals(trackId)) { - trackId = newTrackId; - trackController.update(true, recordingTrackPaused); - trackDataHub.setRecordingTrackId(newTrackId); - } - } } diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java index 551e3adb4..8f402f6e1 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java @@ -39,6 +39,7 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns; import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.TrackPointIterator; +import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; /** @@ -76,12 +77,8 @@ public class TrackDataHub { private Handler handler; private Track.Id selectedTrackId; - @Deprecated - //TODO Is there a better way to handle this? e.g., passing information rather from Activity than from Activity to TrackDataHub - private Track.Id recordingTrackId; - @Deprecated - //TODO Is there a better way to handle this? e.g., passing information rather from Activity than from Activity to TrackDataHub - private boolean recordingTrackPaused; + + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; // Track points sampling state private int numLoadedPoints; @@ -208,14 +205,14 @@ public class TrackDataHub { * Returns true if the selected track is recording. */ public boolean isSelectedTrackRecording() { - return selectedTrackId != null && selectedTrackId.equals(recordingTrackId); + return selectedTrackId != null && selectedTrackId.equals(recordingStatus.getTrackId()); } /** * Returns true if the selected track is paused. */ public boolean isSelectedTrackPaused() { - return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && recordingTrackPaused; + return selectedTrackId != null && selectedTrackId.equals(recordingStatus.getTrackId()) && recordingStatus.isPaused(); } /** @@ -417,11 +414,7 @@ public class TrackDataHub { lastSeenTrackPointId = null; } - public void setRecordingTrackId(Track.Id recordingTrackId) { - this.recordingTrackId = recordingTrackId; - } - - public void setRecordingTrackPaused(boolean recordingTrackPaused) { - this.recordingTrackPaused = recordingTrackPaused; + public void setRecordingStatus(TrackRecordingService.RecordingStatus recordingStatus) { + this.recordingStatus = recordingStatus; } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 538730d39..94cb8ddfd 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -33,6 +33,8 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.core.app.TaskStackBuilder; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import java.time.Duration; import java.time.Instant; @@ -74,6 +76,9 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand private static final String TAG = TrackRecordingService.class.getSimpleName(); + public static final RecordingStatus STATUS_DEFAULT = new RecordingStatus(null, false); + public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE; + // The following variables are set in onCreate: private ContentProviderUtils contentProviderUtils; private PeriodicTaskExecutor voiceExecutor; @@ -119,12 +124,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand private HandlerServer handlerServer; - private final TrackRecordingServiceStatus serviceStatus = new TrackRecordingServiceStatus(); + private RecordingStatus recordingStatus; + private MutableLiveData recordingStatusObservable; + private MutableLiveData gpsStatusObservable; @Override public void onCreate() { super.onCreate(); + recordingStatusObservable = new MutableLiveData<>(); + updateRecordingStatus(STATUS_DEFAULT); + gpsStatusObservable = new MutableLiveData<>(STATUS_GPS_DEFAULT); + handlerServer = new HandlerServer(this); contentProviderUtils = new ContentProviderUtils(this); @@ -149,8 +160,6 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand @Override public void onDestroy() { - serviceStatus.onStop(); - handlerServer.stop(this); handlerServer = null; @@ -181,19 +190,22 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand // This should be the next to last operation wakeLock = SystemUtils.releaseWakeLock(wakeLock); + recordingStatusObservable = null; + gpsStatusObservable = null; + super.onDestroy(); } public boolean isRecording() { - return serviceStatus.isRecording(); + return recordingStatus.isRecording(); } public boolean isPaused() { - return serviceStatus.getRecordingTrackPaused(); + return recordingStatus.isPaused(); } public Track.Id getRecordingTrackId() { - return serviceStatus.getRecordingTrackId(); + return recordingStatus.getTrackId(); } public TrackStatistics getTrackStatistics() { @@ -223,14 +235,14 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } if (name == null) { - Integer nextMarkerNumber = contentProviderUtils.getNextMarkerNumber(serviceStatus.getRecordingTrackId()); + Integer nextMarkerNumber = contentProviderUtils.getNextMarkerNumber(getRecordingTrackId()); if (nextMarkerNumber == null) { nextMarkerNumber = 1; } name = getString(R.string.marker_name_format, nextMarkerNumber + 1); } - TrackPoint trackPoint = getLastValidTrackPointInCurrentSegment(serviceStatus.getRecordingTrackId()); + TrackPoint trackPoint = getLastValidTrackPointInCurrentSegment(getRecordingTrackId()); if (trackPoint == null) { Log.i(TAG, "Could not create a marker as trackPoint is unknown."); return null; @@ -244,7 +256,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand TrackStatistics stats = trackStatisticsUpdater.getTrackStatistics(); // Insert marker - Marker marker = new Marker(name, description, category, icon, serviceStatus.getRecordingTrackId(), stats, trackPoint, photoUrl); + Marker marker = new Marker(name, description, category, icon, getRecordingTrackId(), stats, trackPoint, photoUrl); Uri uri = contentProviderUtils.insertMarker(marker); return new Marker.Id(ContentUris.parseId(uri)); } @@ -266,7 +278,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand Track.Id trackId = new Track.Id(ContentUris.parseId(uri)); // Set recording status - serviceStatus.onChange(trackId, false); + updateRecordingStatus(new RecordingStatus(trackId, false)); // Update database track.setId(trackId); @@ -308,7 +320,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand insertTrackPoint(track, TrackPoint.createSegmentStartManual()); // Set recording status - serviceStatus.onChange(trackId, false); + updateRecordingStatus(new RecordingStatus(trackId, false)); startRecording(); } @@ -321,10 +333,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } // Set recording status - serviceStatus.onChange(false); + updateRecordingStatus(new RecordingStatus(getRecordingTrackId(), false)); // Update database - Track track = contentProviderUtils.getTrack(serviceStatus.getRecordingTrackId()); + Track track = contentProviderUtils.getTrack(getRecordingTrackId()); if (track != null) { insertTrackPoint(track, TrackPoint.createSegmentStartManual()); } @@ -373,10 +385,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand // Need to remember the recordingTrackId before setting it to null boolean wasPause = isPaused(); - Track.Id trackId = serviceStatus.getRecordingTrackId(); + Track.Id trackId = getRecordingTrackId(); // Set recording status - serviceStatus.onChange(null, true); + updateRecordingStatus(STATUS_DEFAULT); if (!wasPause) { // Update database @@ -404,10 +416,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } // Set recording status - serviceStatus.onChange(true); + updateRecordingStatus(new RecordingStatus(getRecordingTrackId(), true)); // Update database - Track track = contentProviderUtils.getTrack(serviceStatus.getRecordingTrackId()); + Track track = contentProviderUtils.getTrack(getRecordingTrackId()); if (track != null) { if (lastTrackPoint != null) { insertTrackPointIfNewer(track, lastTrackPoint); @@ -490,7 +502,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand return; } - Track track = contentProviderUtils.getTrack(serviceStatus.getRecordingTrackId()); + Track track = contentProviderUtils.getTrack(getRecordingTrackId()); if (track == null) { Log.w(TAG, "Ignore newTrackPoint. No track."); return; @@ -564,17 +576,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand @Override public void newGpsStatus(GpsStatusValue gpsStatusValue) { notificationManager.updateContent(getString(gpsStatusValue.message)); - serviceStatus.onChange(gpsStatusValue); - } - public void addListener(@NonNull TrackRecordingServiceStatus.Listener listener) { - serviceStatus.addListener(listener); - } - - //TODO Check that this is used everywhere, where addListener is called! - //Otherwise, we keep objects in referenced and waste memory until this service instance is terminated. - public void removeListener(@NonNull TrackRecordingServiceStatus.Listener listener) { - serviceStatus.removeListener(listener); + gpsStatusObservable.postValue(gpsStatusValue); } /** @@ -666,7 +669,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand private void showNotification(boolean isGpsStarted) { if (isRecording()) { Intent intent = IntentUtils.newIntent(this, TrackRecordingActivity.class) - .putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, serviceStatus.getRecordingTrackId()); + .putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, getRecordingTrackId()); PendingIntent pendingIntent = TaskStackBuilder.create(this) .addParentStack(TrackRecordingActivity.class) .addNextIntent(intent) @@ -702,8 +705,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand this.altitudeSumManager = altitudeSumManager; } - public GpsStatusValue getGpsStatus() { - return handlerServer.getGpsStatus(); + public LiveData getGpsStatusObservable() { + return gpsStatusObservable; + } + + public LiveData getRecordingStatusObservable() { + return recordingStatusObservable; + } + + private void updateRecordingStatus(RecordingStatus status) { + Log.i(TAG, "new status " + recordingStatus + " -> " + status); + recordingStatus = status; + recordingStatusObservable.postValue(recordingStatus); } @Override @@ -717,6 +730,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } } + public class Binder extends android.os.Binder { private Binder() { @@ -727,4 +741,51 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand return TrackRecordingService.this; } } + + public static class RecordingStatus { + private final Track.Id trackId; + private final boolean paused; + + public RecordingStatus(Track.Id trackId, boolean paused) { + this.trackId = trackId; + this.paused = paused; + } + + public Track.Id getTrackId() { + return trackId; + } + + public boolean isRecording() { + return trackId != null; + } + + public boolean isPaused() { + return paused; + } + + public boolean isRecordingAndNotPaused() { + return isRecording() && !isPaused(); + } + + public RecordingStatus pause() { + return new RecordingStatus(getTrackId(), true); + } + + public RecordingStatus record(@NonNull Track.Id track) { + return new RecordingStatus(trackId, false); + } + + public RecordingStatus stop() { + return STATUS_DEFAULT; + } + + + @Override + public String toString() { + return "RecordingStatus{" + + "trackId=" + trackId + + ", paused=" + paused + + '}'; + } + } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceStatus.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceStatus.java deleted file mode 100644 index 3a7b1ca73..000000000 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceStatus.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.dennisguse.opentracks.services; - -import androidx.annotation.NonNull; - -import java.util.ArrayList; -import java.util.List; - -import de.dennisguse.opentracks.content.data.Track; -import de.dennisguse.opentracks.services.handlers.GpsStatusValue; - -/** - * This class handles the status of the recording service. - * Also offer an interface through which to know the recording Track.Id, pause status and GPS status. - */ -public class TrackRecordingServiceStatus { - - private Track.Id recordingTrackId; - private boolean recordingTrackPaused; - - private final List listeners = new ArrayList<>(); - - void addListener(@NonNull Listener listener) { - if (this.listeners.contains(listener)) { - return; - } - this.listeners.add(listener); - listener.onTrackRecordingId(recordingTrackId); - listener.onTrackRecordingPaused(recordingTrackPaused); - } - - void removeListener(@NonNull Listener listener) { - this.listeners.remove(listener); - } - - public boolean getRecordingTrackPaused() { - return this.recordingTrackPaused; - } - - public Track.Id getRecordingTrackId() { - return this.recordingTrackId; - } - - public void onStop() { - for (Listener listener : listeners) { - listener.onGpsStatus(GpsStatusValue.GPS_NONE); - listener.onTrackRecordingId(null); - listener.onTrackRecordingPaused(true); - } - listeners.clear(); - } - - public boolean isRecording() { - return recordingTrackId != null; - } - - void onChange(Track.Id trackId, boolean paused) { - recordingTrackId = trackId; - recordingTrackPaused = paused; - for (Listener listener : listeners) { - listener.onTrackRecordingId(recordingTrackId); - listener.onTrackRecordingPaused(recordingTrackPaused); - } - } - - void onChange(boolean paused) { - recordingTrackPaused = paused; - for (Listener listener : listeners) { - listener.onTrackRecordingPaused(recordingTrackPaused); - } - } - - void onChange(GpsStatusValue statusValue) { - for (Listener listener : listeners) { - listener.onGpsStatus(statusValue); - } - } - - public interface Listener { - default void onGpsStatus(GpsStatusValue newValue) {} - default void onTrackRecordingPaused(boolean paused) {} - default void onTrackRecordingId(Track.Id trackId) {} - } -} diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java index db3a5315b..cb27a60a6 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java @@ -20,4 +20,8 @@ public enum GpsStatusValue { this.icon = icon; this.message = message; } + + public boolean isGpsStarted() { + return this != GpsStatusValue.GPS_NONE && this != GpsStatusValue.GPS_DISABLED; + } } diff --git a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java index 15a445c5a..1e99ae443 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java +++ b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java @@ -20,12 +20,10 @@ import java.util.Locale; import de.dennisguse.opentracks.AbstractActivity; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.services.TrackRecordingServiceStatus; import de.dennisguse.opentracks.settings.bluetooth.BluetoothLeCyclingCadenceAndSpeedPreference; import de.dennisguse.opentracks.settings.bluetooth.BluetoothLeCyclingPowerPreference; import de.dennisguse.opentracks.settings.bluetooth.BluetoothLeHeartRatePreference; @@ -93,7 +91,7 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity getSupportFragmentManager().beginTransaction().replace(R.id.settings_fragment, prefsFragment).commit(); } - public static class PrefsFragment extends PreferenceFragmentCompat implements TrackRecordingServiceStatus.Listener { + public static class PrefsFragment extends PreferenceFragmentCompat { private SharedPreferences sharedPreferences; @@ -107,15 +105,20 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity }; private TrackRecordingServiceConnection trackRecordingServiceConnection; - private boolean isRecording; + private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private final Runnable bindServiceCallback = new Runnable() { @Override public void run() { TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound(); - if (service != null) { - service.addListener(PrefsFragment.this); + if (service == null) { + Log.w(TAG, "could not get TrackRecordingService"); + return; } + + service.getRecordingStatusObservable() + .observe(PrefsFragment.this, status -> onRecordingStatusChanged(status)); + } }; @@ -218,6 +221,7 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity Preference importPreference = findPreference(getString(R.string.settings_import)); Preference exportPreference = findPreference(getString(R.string.settings_export)); + boolean isRecording = recordingStatus.isRecording(); resetPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : ""); importPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : ""); exportPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : ""); @@ -292,10 +296,9 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity }); } - @Override - public void onTrackRecordingId(Track.Id trackId) { - if (trackId != null && !isRecording && isAdded()) { - isRecording = true; + private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { + this.recordingStatus = status; + if (!status.isRecording() && isAdded()) { updatePrefsDependOnRecording(); } }