TrackDetailActivity starts an actual recording and a stopped recording can be resumed. Fixes #103 and #11.

This commit is contained in:
Román
2020-03-25 14:07:48 +01:00
committed by Dennis Guse
parent 306522863a
commit d93c2ec5f3
12 changed files with 164 additions and 46 deletions
@@ -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>
+5
View File
@@ -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"
+2
View File
@@ -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>
+2
View File
@@ -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>
+3
View File
@@ -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>