diff --git a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
index 8b0b63420..50ffbc9fa 100644
--- a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
+++ b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
@@ -21,11 +21,13 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Build;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
@@ -43,6 +45,7 @@ import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.fragments.StatsFragment;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
+import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
import de.dennisguse.opentracks.settings.SettingsActivity;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -50,7 +53,7 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils;
/**
- * An activity to show the track detail.
+ * An activity to show the track detail, record a new track or resumes an existing one.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
@@ -89,6 +92,34 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
trackController.update(isRecording(), recordingTrackPaused);
}
});
+
+ if (recordingTrackId == -1L) {
+ TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
+ if (service == null) {
+ Log.d(TAG, "it could not get service");
+ return;
+ }
+
+ // Starts or resumes a track.
+ int msg;
+ if (trackId == -1L) {
+ // trackId isn't initialized -> leads a new recording.
+ trackId = service.startNewTrack();
+ recordingTrackId = trackId;
+ msg = R.string.track_detail_record_success;
+ } else {
+ // trackId is initialized -> resumes the track.
+ recordingTrackId = trackId;
+ service.resumeTrack(trackId);
+ msg = R.string.track_detail_resume_success;
+ }
+
+ // A recording track is on.
+ Toast.makeText(TrackDetailActivity.this, msg, Toast.LENGTH_SHORT).show();
+ trackDataHub.loadTrack(trackId);
+ trackController.update(true, false);
+ trackController.onResume(true, recordingTrackPaused);
+ }
}
};
@@ -131,6 +162,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
private MenuItem insertMarkerMenuItem;
private MenuItem markerListMenuItem;
private MenuItem shareMenuItem;
+ private MenuItem resumeMenuItem;
private final OnClickListener recordListener = new OnClickListener() {
@Override
@@ -258,11 +290,16 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
@Override
protected void onResume() {
super.onResume();
- trackDataHub.loadTrack(trackId);
// Update UI
this.invalidateOptionsMenu();
- trackController.onResume(isRecording(), recordingTrackPaused);
+
+ if (trackId != -1L) {
+ trackDataHub.loadTrack(trackId);
+ trackController.onResume(isRecording(), recordingTrackPaused);
+ } else {
+ startRecording();
+ }
}
@Override
@@ -304,6 +341,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
shareMenuItem = menu.findItem(R.id.track_detail_share);
markerListMenuItem = menu.findItem(R.id.track_detail_markers);
+ resumeMenuItem = menu.findItem(R.id.track_detail_resume_track);
return super.onCreateOptionsMenu(menu);
}
@@ -345,6 +383,9 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
case R.id.track_detail_delete:
deleteTracks(new long[]{trackId});
return true;
+ case R.id.track_detail_resume_track:
+ startRecording();
+ return true;
case R.id.track_detail_settings:
intent = IntentUtils.newIntent(this, SettingsActivity.class);
startActivity(intent);
@@ -387,9 +428,13 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
return;
}
trackId = waypoint.getTrackId();
+ if (trackId == -1L) {
+ finish();
+ return;
+ }
}
+
if (trackId == -1L) {
- finish();
return;
}
Track track = contentProviderUtils.getTrack(trackId);
@@ -416,9 +461,12 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
String title;
if (isRecording()) {
title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording);
+ resumeMenuItem.setVisible(false);
} else {
Track track = contentProviderUtils.getTrack(trackId);
title = track != null ? track.getName() : "";
+ // Only visible if there aren't other tracks that is recording.
+ resumeMenuItem.setVisible(recordingTrackId == -1L);
}
setTitle(title);
}
@@ -437,4 +485,15 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
private boolean isRecording() {
return trackId == recordingTrackId;
}
+
+ private void startRecording() {
+ trackRecordingServiceConnection.startAndBind(this);
+
+ /*
+ * If the binding has happened, then invoke the callback to start a new recording.
+ * If the binding hasn't happened, then invoking the callback will have no effect.
+ * But when the binding occurs, the callback will get invoked.
+ */
+ bindChangedCallback.run();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java
index 8b2a73f48..85dedbd29 100644
--- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java
+++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java
@@ -160,7 +160,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
// Menu items
private MenuItem searchMenuItem;
private MenuItem startGpsMenuItem;
-// private MenuItem deleteAllMenuItem;
private final OnClickListener stopListener = new OnClickListener() {
@Override
@@ -172,8 +171,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
private boolean startGps = false; // true to start gps
- private boolean startNewRecording = false; // true to start a new recording
-
// Callback when the trackRecordingServiceConnection binding changes.
private final Runnable bindChangedCallback = new Runnable() {
@Override
@@ -188,7 +185,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
}
});
- if (!startGps && !startNewRecording) {
+ if (!startGps) {
return;
}
@@ -197,17 +194,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
Log.d(TAG, "service not available to start gps or a new recording");
return;
}
- if (startNewRecording) {
- startGps = false;
-
- long trackId = service.startNewTrack();
- startNewRecording = false;
- Intent intent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class)
- .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId);
- startActivity(intent);
- Toast.makeText(TrackListActivity.this, R.string.track_list_record_success, Toast.LENGTH_SHORT)
- .show();
- }
if (startGps) {
service.startGps();
startGps = false;
@@ -220,18 +206,19 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
if (!PreferencesUtils.isRecording(recordingTrackId)) {
// Not recording -> Recording
updateMenuItems(false, true);
- startRecording();
+ Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class);
+ startActivity(newIntent);
} else if (recordingTrackPaused) {
- // Paused -> Resume
- updateMenuItems(false, true);
- trackRecordingServiceConnection.resumeTrack();
- trackController.update(true, false);
- } else {
- // Recording -> Paused
- updateMenuItems(false, true);
- trackRecordingServiceConnection.pauseTrack();
- trackController.update(true, true);
- }
+ // Paused -> Resume
+ updateMenuItems(false, true);
+ trackRecordingServiceConnection.resumeTrack();
+ trackController.update(true, false);
+ } else {
+ // Recording -> Paused
+ updateMenuItems(false, true);
+ trackRecordingServiceConnection.pauseTrack();
+ trackController.update(true, true);
+ }
}
};
@@ -489,21 +476,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
}
}
- /**
- * Starts a new recording.
- */
- private void startRecording() {
- startNewRecording = true;
- trackRecordingServiceConnection.startAndBind(this);
-
- /*
- * If the binding has happened, then invoke the callback to start a new recording.
- * If the binding hasn't happened, then invoking the callback will have no effect.
- * But when the binding occurs, the callback will get invoked.
- */
- bindChangedCallback.run();
- }
-
/**
* Handles a context item selection.
*
diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java
index 207c6babf..963997968 100644
--- a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java
+++ b/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java
@@ -96,6 +96,16 @@ public class StatsFragment extends Fragment implements TrackDataListener {
}
if (PreferencesUtils.isKey(getContext(), R.string.recording_track_id_key, key)) {
recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(getContext());
+ if (PreferencesUtils.getRecordingTrackId(getContext()) != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
+ // A recording track id has been set -> Resumes track and starts timer.
+ resumeTrackDataHub();
+ if (trackRecordingServiceConnection == null) {
+ trackRecordingServiceConnection = new TrackRecordingServiceConnection(getContext(), null);
+ }
+ trackRecordingServiceConnection.startConnection(getContext());
+
+ handlerUpdateUI.post(updateUIeachSecond);
+ }
}
}
};
@@ -533,13 +543,26 @@ public class StatsFragment extends Fragment implements TrackDataListener {
private void updateTotalTime() {
long totalTime;
if (isSelectedTrackRecording()) {
- totalTime = System.currentTimeMillis() - lastTripStatistics.getStopTime() + lastTripStatistics.getTotalTime();
+ totalTime = calculateTotalTime();
} else {
totalTime = lastTripStatistics.getTotalTime();
}
totalTimeValueView.setText(StringUtils.formatElapsedTime(totalTime));
}
+ /**
+ * Return time from service.
+ * If service isn't bound then use lastTripStatistics for calculate it.
+ */
+ private long calculateTotalTime() {
+ TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
+ if (trackRecordingService != null) {
+ return trackRecordingService.getTotalTime();
+ } else {
+ return System.currentTimeMillis() - lastTripStatistics.getStopTime() + lastTripStatistics.getTotalTime();
+ }
+ }
+
private void setLocationValues() {
boolean metricUnits = PreferencesUtils.isMetricUnits(getContext());
boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext());
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
index 9c9b35cb7..f77670f29 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
@@ -352,6 +352,27 @@ public class TrackRecordingService extends Service {
return trackId;
}
+ /**
+ * Resumes the track identified by trackId.
+ *
+ * @param trackId
+ */
+ void resumeTrack(long trackId) {
+ Track track = contentProviderUtils.getTrack(trackId);
+ if (track == null) {
+ Log.e(TAG, "Ignore resumeTrack. Track " + trackId + " does not exists.");
+ return;
+ }
+
+ track.getTripStatistics().setStopTime(System.currentTimeMillis());
+ trackTripStatisticsUpdater = new TripStatisticsUpdater(track.getTripStatistics());
+
+ // Update shared preferences
+ updateRecordingState(trackId, false);
+
+ startRecording();
+ }
+
private void restartTrack(Track track) {
Log.d(TAG, "Restarting track: " + track.getId());
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java
index 12b63ed4e..19eb2723e 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java
@@ -36,6 +36,11 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
return trackRecordingService.startNewTrack();
}
+ @Override
+ public void resumeTrack(long trackId) {
+ trackRecordingService.resumeTrack(trackId);
+ }
+
@Override
public void pauseCurrentTrack() {
trackRecordingService.pauseCurrentTrack();
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java
index b3915772f..c7e01191f 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java
@@ -44,6 +44,13 @@ public interface TrackRecordingServiceInterface {
*/
long startNewTrack();
+ /**
+ * Resumes the track identified by trackId.
+ *
+ * @param trackId
+ */
+ void resumeTrack(long trackId);
+
/**
* Pauses the current recording track.
*/
diff --git a/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java
index c51ba6652..2900d0979 100644
--- a/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java
+++ b/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java
@@ -96,6 +96,16 @@ public class TripStatisticsUpdater {
currentSegment = init(startTime);
}
+ /**
+ * Creates a new trip statistics updater with a trip statistics already existed.
+ *
+ * @param tripStatistics a trip statistics.
+ */
+ public TripStatisticsUpdater(TripStatistics tripStatistics) {
+ this.tripStatistics = tripStatistics;
+ currentSegment = init(System.currentTimeMillis());
+ }
+
public void updateTime(long time) {
currentSegment.setStopTime(time);
currentSegment.setTotalTime(time - currentSegment.getStartTime());
diff --git a/src/main/res/drawable/ic_play_circle_24dp.xml b/src/main/res/drawable/ic_play_circle_24dp.xml
new file mode 100644
index 000000000..930ee0ed5
--- /dev/null
+++ b/src/main/res/drawable/ic_play_circle_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/main/res/menu/track_detail.xml b/src/main/res/menu/track_detail.xml
index b3ae34f7e..3fd5d24a1 100644
--- a/src/main/res/menu/track_detail.xml
+++ b/src/main/res/menu/track_detail.xml
@@ -48,6 +48,11 @@ limitations under the License.
android:icon="@drawable/ic_delete_forever_24dp"
android:orderInCategory="10"
android:title="@string/menu_delete" />
+
- Detener GPS
Ver foto
Frecuencia de voz
+ Reanudar ruta
OpenTracks
Servicio de grabación
Recorridos y marcadores
@@ -299,6 +300,7 @@
Eliminando…
Gráfico
Estadísticas
+ Grabando una nueva ruta
Tipo de actividad (p. ej., senderismo)
Tipo de actividad
Nuevo recorrido
diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml
index 0031dc5f8..7496c2245 100644
--- a/src/main/res/values-es/strings.xml
+++ b/src/main/res/values-es/strings.xml
@@ -211,6 +211,7 @@
Detener GPS
Ver foto
Frecuencia de voz
+ Reanudar ruta
OpenTracks
Servicio de grabación
Recorridos y marcadores
@@ -303,6 +304,7 @@
Eliminando…
Gráfico
Estadísticas
+ Grabando una nueva ruta
Tipo de actividad (p. ej., senderismo…)
Tipo de actividad
Nueva pista
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 7a2a264fc..d97edbf73 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -321,6 +321,7 @@ limitations under the License.
Stop GPS
View photo
Voice frequency
+ Resume track
OpenTracks
Recording service
@@ -440,6 +441,8 @@ limitations under the License.
Chart
Stats
+ Now recording a new track
+ Now resuming the track
Activity type (e.g. hiking)
Activity type