mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 09:33:06 +02:00
TrackDetailActivity starts an actual recording and a stopped recording can be resumed. Fixes #103 and #11.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,16.5v-9l6,4.5 -6,4.5z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
||||
@@ -48,6 +48,11 @@ limitations under the License.
|
||||
android:icon="@drawable/ic_delete_forever_24dp"
|
||||
android:orderInCategory="10"
|
||||
android:title="@string/menu_delete" />
|
||||
<item
|
||||
android:id="@+id/track_detail_resume_track"
|
||||
android:icon="@drawable/ic_play_circle_24dp"
|
||||
android:orderInCategory="10"
|
||||
android:title="@string/menu_resume_track" />
|
||||
<item
|
||||
android:id="@+id/track_detail_settings"
|
||||
android:icon="@drawable/ic_settings_24dp"
|
||||
|
||||
@@ -207,6 +207,7 @@
|
||||
<string name="menu_stop_gps">Detener GPS</string>
|
||||
<string name="menu_view_photo">Ver foto</string>
|
||||
<string name="menu_voice_frequency">Frecuencia de voz</string>
|
||||
<string name="menu_resume_track">Reanudar ruta</string>
|
||||
<string name="app_name">OpenTracks</string>
|
||||
<string name="recording_service">Servicio de grabación</string>
|
||||
<string name="search_global_description">Recorridos y marcadores</string>
|
||||
@@ -299,6 +300,7 @@
|
||||
<string name="track_delete_progress_message">Eliminando…</string>
|
||||
<string name="track_detail_chart_tab">Gráfico</string>
|
||||
<string name="track_detail_stats_tab">Estadísticas</string>
|
||||
<string name="track_detail_record_success">Grabando una nueva ruta</string>
|
||||
<string name="track_edit_activity_type">Tipo de actividad (p. ej., senderismo)</string>
|
||||
<string name="track_edit_activity_type_hint">Tipo de actividad</string>
|
||||
<string name="track_edit_new_track_title">Nuevo recorrido</string>
|
||||
|
||||
@@ -211,6 +211,7 @@
|
||||
<string name="menu_stop_gps">Detener GPS</string>
|
||||
<string name="menu_view_photo">Ver foto</string>
|
||||
<string name="menu_voice_frequency">Frecuencia de voz</string>
|
||||
<string name="menu_resume_track">Reanudar ruta</string>
|
||||
<string name="app_name">OpenTracks</string>
|
||||
<string name="recording_service">Servicio de grabación</string>
|
||||
<string name="search_global_description">Recorridos y marcadores</string>
|
||||
@@ -303,6 +304,7 @@
|
||||
<string name="track_delete_progress_message">Eliminando…</string>
|
||||
<string name="track_detail_chart_tab">Gráfico</string>
|
||||
<string name="track_detail_stats_tab">Estadísticas</string>
|
||||
<string name="track_detail_record_success">Grabando una nueva ruta</string>
|
||||
<string name="track_edit_activity_type">Tipo de actividad (p. ej., senderismo…)</string>
|
||||
<string name="track_edit_activity_type_hint">Tipo de actividad</string>
|
||||
<string name="track_edit_new_track_title">Nueva pista</string>
|
||||
|
||||
@@ -321,6 +321,7 @@ limitations under the License.
|
||||
<string name="menu_stop_gps">Stop GPS</string>
|
||||
<string name="menu_view_photo">View photo</string>
|
||||
<string name="menu_voice_frequency">Voice frequency</string>
|
||||
<string name="menu_resume_track">Resume track</string>
|
||||
<!-- OpenTracks -->
|
||||
<string name="app_name">OpenTracks</string>
|
||||
<string name="recording_service">Recording service</string>
|
||||
@@ -440,6 +441,8 @@ limitations under the License.
|
||||
<!-- Track Detail -->
|
||||
<string name="track_detail_chart_tab">Chart</string>
|
||||
<string name="track_detail_stats_tab">Stats</string>
|
||||
<string name="track_detail_record_success">Now recording a new track</string>
|
||||
<string name="track_detail_resume_success">Now resuming the track</string>
|
||||
<!-- Track Edit -->
|
||||
<string name="track_edit_activity_type">Activity type (e.g. hiking)</string>
|
||||
<string name="track_edit_activity_type_hint">Activity type</string>
|
||||
|
||||
Reference in New Issue
Block a user