forked from upstream-mirrors/OpenTracks
@@ -268,6 +268,30 @@ public class TrackRecordingServiceTest {
|
|||||||
assertEquals(TrackPoint.Type.TRACKPOINT, trackPoints.get(3).getType());
|
assertEquals(TrackPoint.Type.TRACKPOINT, trackPoints.get(3).getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MediumTest
|
||||||
|
@Test
|
||||||
|
public void testRecording_stopPausedTrack() throws TimeoutException {
|
||||||
|
// given
|
||||||
|
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||||
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
assertTrue(service.isRecording());
|
||||||
|
service.pauseCurrentTrack();
|
||||||
|
|
||||||
|
assertEquals(2, contentProviderUtils.getTrackPoints(trackId).size());
|
||||||
|
|
||||||
|
// when
|
||||||
|
service.endCurrentTrack();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertFalse(service.isRecording());
|
||||||
|
assertNull(service.getRecordingTrackId());
|
||||||
|
|
||||||
|
List<TrackPoint> trackPoints = contentProviderUtils.getTrackPoints(trackId);
|
||||||
|
assertEquals(2, trackPoints.size());
|
||||||
|
assertEquals(TrackPoint.Type.SEGMENT_START_MANUAL, trackPoints.get(0).getType());
|
||||||
|
assertEquals(TrackPoint.Type.SEGMENT_END_MANUAL, trackPoints.get(1).getType());
|
||||||
|
}
|
||||||
|
|
||||||
@Ignore("Sometimes fails on CI.")
|
@Ignore("Sometimes fails on CI.")
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
private final TransitionDrawable transition;
|
private final TransitionDrawable transition;
|
||||||
|
|
||||||
private boolean isRecording;
|
private boolean isRecording;
|
||||||
private boolean isPaused;
|
private boolean isRecordingPaused;
|
||||||
private Duration totalTime;
|
private Duration totalTime;
|
||||||
private boolean isResumed = false;
|
private boolean isResumed = false;
|
||||||
|
|
||||||
@@ -63,8 +63,9 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
// A runnable to update the total time.
|
// A runnable to update the total time.
|
||||||
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isResumed && isRecording && !isPaused) {
|
if (isResumed && isRecording && !isRecordingPaused) {
|
||||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
updateTotalTime();
|
||||||
|
setTotalTime();
|
||||||
handlerUpdateTotalTime.postDelayed(this, UnitConversions.ONE_SECOND_MS);
|
handlerUpdateTotalTime.postDelayed(this, UnitConversions.ONE_SECOND_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
|
|
||||||
viewBinding.trackControllerRecord.setOnTouchListener(this);
|
viewBinding.trackControllerRecord.setOnTouchListener(this);
|
||||||
viewBinding.trackControllerRecord.setOnClickListener((view) -> {
|
viewBinding.trackControllerRecord.setOnClickListener((view) -> {
|
||||||
if (buttonDelay != null || (isRecording && !isPaused)) {
|
if (buttonDelay != null || (isRecording && !isRecordingPaused)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +119,7 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
//To pause a recording
|
//To pause a recording
|
||||||
if (viewBinding.trackControllerRecord.equals(view)
|
if (viewBinding.trackControllerRecord.equals(view)
|
||||||
&& event.getAction() == MotionEvent.ACTION_DOWN
|
&& event.getAction() == MotionEvent.ACTION_DOWN
|
||||||
&& isRecording && !isPaused) {
|
&& isRecording && !isRecordingPaused) {
|
||||||
|
|
||||||
transition.startTransition(buttonDelayDuration);
|
transition.startTransition(buttonDelayDuration);
|
||||||
|
|
||||||
@@ -165,10 +166,11 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
|
|
||||||
public void update(boolean recording, boolean paused) {
|
public void update(boolean recording, boolean paused) {
|
||||||
if (!isResumed) {
|
if (!isResumed) {
|
||||||
|
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isRecording = recording;
|
isRecording = recording;
|
||||||
isPaused = paused;
|
isRecordingPaused = paused;
|
||||||
boolean visible = alwaysShow || isRecording;
|
boolean visible = alwaysShow || isRecording;
|
||||||
viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
|
viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
@@ -177,27 +179,26 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.trackControllerRecord.setImageResource(isRecording && !isPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
|
if (isRecording && !isRecordingPaused) {
|
||||||
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isPaused ? R.string.image_pause : R.string.image_record));
|
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UnitConversions.ONE_SECOND_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewBinding.trackControllerRecord.setImageResource(isRecording && !isRecordingPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
|
||||||
|
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isRecordingPaused ? R.string.image_pause : R.string.image_record));
|
||||||
|
|
||||||
viewBinding.trackControllerStop.setEnabled(isRecording);
|
viewBinding.trackControllerStop.setEnabled(isRecording);
|
||||||
|
|
||||||
viewBinding.trackControllerStatus.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
viewBinding.trackControllerStatus.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
||||||
if (isRecording) {
|
if (isRecording) {
|
||||||
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isPaused ? android.R.color.white : R.color.recording_text));
|
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isRecordingPaused ? android.R.color.white : R.color.recording_text));
|
||||||
showStatusSetDefaultText();
|
showStatusSetDefaultText();
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
|
||||||
if (isRecording) {
|
if (isRecording) {
|
||||||
totalTime = getTotalTime();
|
updateTotalTime();
|
||||||
if (totalTime != null) {
|
setTotalTime();
|
||||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
|
||||||
}
|
|
||||||
if (!isPaused) {
|
|
||||||
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UnitConversions.ONE_SECOND_MS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,16 +220,21 @@ public class TrackController implements View.OnTouchListener {
|
|||||||
viewBinding.trackControllerContainer.setVisibility(View.VISIBLE);
|
viewBinding.trackControllerContainer.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void updateTotalTime() {
|
||||||
* Gets the total time for the current recording track.
|
|
||||||
*/
|
|
||||||
private Duration getTotalTime() {
|
|
||||||
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
return trackRecordingService != null ? trackRecordingService.getTotalTime() : null;
|
if (trackRecordingService != null) {
|
||||||
|
totalTime = trackRecordingService.getTotalTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTotalTime() {
|
||||||
|
if (totalTime != null) {
|
||||||
|
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showStatusSetDefaultText() {
|
private void showStatusSetDefaultText() {
|
||||||
viewBinding.trackControllerStatus.setText(isPaused ? R.string.generic_paused : R.string.generic_recording);
|
viewBinding.trackControllerStatus.setText(isRecordingPaused ? R.string.generic_paused : R.string.generic_recording);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import androidx.recyclerview.widget.GridLayoutManager;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -409,26 +408,15 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalTime() {
|
private void updateTotalTime() {
|
||||||
Duration totalTime;
|
Duration totalTime = lastTrackStatistics.getTotalTime();
|
||||||
if (isSelectedTrackRecording()) {
|
if (isSelectedTrackRecording()) {
|
||||||
totalTime = calculateTotalTime();
|
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
} else {
|
if (trackRecordingService != null) {
|
||||||
totalTime = lastTrackStatistics.getTotalTime();
|
totalTime = trackRecordingService.getTotalTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
|
||||||
* Return time from service.
|
|
||||||
* If service isn't bound then use lastTrackStatistics for calculate it.
|
|
||||||
*/
|
|
||||||
private Duration calculateTotalTime() {
|
|
||||||
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (trackRecordingService != null) {
|
|
||||||
return trackRecordingService.getTotalTime();
|
|
||||||
} else {
|
|
||||||
return Duration.between(lastTrackStatistics.getStopTime().plus(lastTrackStatistics.getTotalTime()), Instant.now());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLocationValues() {
|
private void setLocationValues() {
|
||||||
|
|||||||
@@ -234,10 +234,13 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
if (trackStatisticsUpdater == null) {
|
if (trackStatisticsUpdater == null) {
|
||||||
return Duration.ofSeconds(0);
|
return Duration.ofSeconds(0);
|
||||||
}
|
}
|
||||||
if (!isPaused()) {
|
if (isPaused()) {
|
||||||
trackStatisticsUpdater.updateTime(Instant.now());
|
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
|
||||||
}
|
}
|
||||||
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
|
|
||||||
|
TrackStatistics statistics = trackStatisticsUpdater.getTrackStatistics();
|
||||||
|
return Duration.between(statistics.getStopTime(), Instant.now())
|
||||||
|
.plus(statistics.getTotalTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Marker.Id insertMarker(String name, String category, String description, String photoUrl) {
|
public Marker.Id insertMarker(String name, String category, String description, String photoUrl) {
|
||||||
@@ -420,24 +423,24 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to remember the recordingTrackId before setting it to -1L
|
// Need to remember the recordingTrackId before setting it to -1L
|
||||||
|
boolean wasPause = isPaused();
|
||||||
Track.Id trackId = recordingTrackId;
|
Track.Id trackId = recordingTrackId;
|
||||||
boolean wasPaused = recordingTrackPaused;
|
|
||||||
|
|
||||||
updateRecordingState(null, true);
|
updateRecordingState(null, true);
|
||||||
|
|
||||||
// Update database
|
if (!wasPause) {
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
// Update database
|
||||||
if (track != null) {
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
if (lastTrackPoint != null) {
|
if (track != null) {
|
||||||
insertTrackPointIfNewer(track, lastTrackPoint);
|
if (lastTrackPoint != null) {
|
||||||
|
insertTrackPointIfNewer(track, lastTrackPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
insertTrackPoint(track, TrackPoint.createSegmentEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
insertTrackPoint(track, TrackPoint.createSegmentEnd());
|
|
||||||
|
|
||||||
// Update the recording track time
|
|
||||||
updateTrackTotalTime(track);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
ExportUtils.postWorkoutExport(this, track, new ExportServiceResultReceiver(new Handler(), this));
|
ExportUtils.postWorkoutExport(this, track, new ExportServiceResultReceiver(new Handler(), this));
|
||||||
|
|
||||||
endRecording(true);
|
endRecording(true);
|
||||||
@@ -663,7 +666,9 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
}
|
}
|
||||||
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
|
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
|
||||||
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
||||||
updateTrackTotalTime(track);
|
|
||||||
|
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||||
|
contentProviderUtils.updateTrack(track);
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
/*
|
/*
|
||||||
* Insert failed, most likely because of SqlLite error code 5 (SQLite_BUSY).
|
* Insert failed, most likely because of SqlLite error code 5 (SQLite_BUSY).
|
||||||
@@ -674,17 +679,6 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
voiceExecutor.update();
|
voiceExecutor.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the recording track time.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
*/
|
|
||||||
private void updateTrackTotalTime(Track track) {
|
|
||||||
trackStatisticsUpdater.updateTime(Instant.now());
|
|
||||||
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
|
||||||
contentProviderUtils.updateTrack(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
SensorDataSet getSensorDataSet() {
|
SensorDataSet getSensorDataSet() {
|
||||||
if (remoteSensorManager == null) {
|
if (remoteSensorManager == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
||||||
@@ -91,11 +90,6 @@ public class TrackStatisticsUpdater {
|
|||||||
trackInitialized = true;
|
trackInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTime(Instant time) {
|
|
||||||
currentSegment.setStopTime(time);
|
|
||||||
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), time));
|
|
||||||
}
|
|
||||||
|
|
||||||
public TrackStatistics getTrackStatistics() {
|
public TrackStatistics getTrackStatistics() {
|
||||||
// Take a snapshot - we don't want anyone messing with our trackStatistics
|
// Take a snapshot - we don't want anyone messing with our trackStatistics
|
||||||
TrackStatistics stats = new TrackStatistics(trackStatistics);
|
TrackStatistics stats = new TrackStatistics(trackStatistics);
|
||||||
@@ -120,7 +114,9 @@ public class TrackStatisticsUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always update time
|
// Always update time
|
||||||
updateTime(trackPoint.getTime());
|
currentSegment.setStopTime(trackPoint.getTime());
|
||||||
|
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), trackPoint.getTime()));
|
||||||
|
|
||||||
if (trackPoint.isSegmentStart() || trackPoint.isSegmentEnd()) {
|
if (trackPoint.isSegmentStart() || trackPoint.isSegmentEnd()) {
|
||||||
if (trackPoint.isSegmentEnd()) {
|
if (trackPoint.isSegmentEnd()) {
|
||||||
if (lastTrackPoint != null && lastMovingTrackPoint != null && lastTrackPoint != lastMovingTrackPoint) {
|
if (lastTrackPoint != null && lastMovingTrackPoint != null && lastTrackPoint != lastMovingTrackPoint) {
|
||||||
@@ -240,9 +236,6 @@ public class TrackStatisticsUpdater {
|
|||||||
return newAverage - oldAverage;
|
return newAverage - oldAverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the speed is valid.
|
|
||||||
*/
|
|
||||||
private boolean isValidSpeed(@NonNull TrackPoint trackPoint, @NonNull TrackPoint lastTrackPoint) {
|
private boolean isValidSpeed(@NonNull TrackPoint trackPoint, @NonNull TrackPoint lastTrackPoint) {
|
||||||
// There are a lot of noisy speed readings. Do the cheapest checks first, most expensive last.
|
// There are a lot of noisy speed readings. Do the cheapest checks first, most expensive last.
|
||||||
if (trackPoint.getSpeed() == 0) {
|
if (trackPoint.getSpeed() == 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user