forked from upstream-mirrors/OpenTracks
TrackRecordingService uses LiveData to transfer data.
Replaces pull from UI layer. Fixes #173.
This commit is contained in:
@@ -31,8 +31,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
|
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
@@ -49,10 +47,6 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
|
|
||||||
private static final String TAG = ControllerFragment.class.getSimpleName();
|
private static final String TAG = ControllerFragment.class.getSimpleName();
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
//TODO TrackRecordingService should provide LifeData for time (replace internal timer)
|
|
||||||
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
|
||||||
@Deprecated
|
|
||||||
private Handler handlerUpdateTotalTime;
|
private Handler handlerUpdateTotalTime;
|
||||||
|
|
||||||
private Runnable buttonDelay;
|
private Runnable buttonDelay;
|
||||||
@@ -63,7 +57,7 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
|
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private TrackRecordingService.RecordingStatus recordingStatus;
|
private TrackRecordingService.RecordingStatus recordingStatus;
|
||||||
private Duration totalTime;
|
private TrackRecordingService.RecordingData recordingData;
|
||||||
|
|
||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -76,18 +70,9 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
|
|
||||||
service.getRecordingStatusObservable()
|
service.getRecordingStatusObservable()
|
||||||
.observe(ControllerFragment.this, status -> onRecordingStatusChanged(status));
|
.observe(ControllerFragment.this, status -> onRecordingStatusChanged(status));
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// A runnable to update the total time.
|
service.getRecordingDataObservable()
|
||||||
@Deprecated
|
.observe(ControllerFragment.this, recordingData -> onTotalTimeChanged(recordingData));
|
||||||
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
if (isResumed() && recordingStatus.isRecordingAndNotPaused()) {
|
|
||||||
updateTotalTime();
|
|
||||||
setTotalTime();
|
|
||||||
handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,12 +114,6 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
trackRecordingServiceConnection.startConnection(getContext());
|
trackRecordingServiceConnection.startConnection(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
@@ -239,19 +218,6 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
viewBinding.controllerContainer.setVisibility(View.VISIBLE);
|
viewBinding.controllerContainer.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalTime() {
|
|
||||||
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (trackRecordingService != null) {
|
|
||||||
totalTime = trackRecordingService.getTotalTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTotalTime() {
|
|
||||||
if (totalTime != null) {
|
|
||||||
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showStatusSetDefaultText() {
|
private void showStatusSetDefaultText() {
|
||||||
viewBinding.controllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
|
viewBinding.controllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
|
||||||
}
|
}
|
||||||
@@ -271,13 +237,6 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||||
recordingStatus = status;
|
recordingStatus = status;
|
||||||
|
|
||||||
if (!recordingStatus.isRecording()) {
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
}
|
|
||||||
if (recordingStatus.isRecordingAndNotPaused()) {
|
|
||||||
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UI_UPDATE_INTERVAL.toMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
|
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
|
||||||
viewBinding.controllerRecord.setContentDescription(getContext().getString(recordingStatus.isRecordingAndNotPaused() ? R.string.image_pause : R.string.image_record));
|
viewBinding.controllerRecord.setContentDescription(getContext().getString(recordingStatus.isRecordingAndNotPaused() ? R.string.image_pause : R.string.image_record));
|
||||||
|
|
||||||
@@ -290,10 +249,11 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
|
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
if (recordingStatus.isRecording()) {
|
private void onTotalTimeChanged(TrackRecordingService.RecordingData recordingData) {
|
||||||
updateTotalTime();
|
this.recordingData = recordingData;
|
||||||
setTotalTime();
|
|
||||||
}
|
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(this.recordingData.getTrackStatistics().getTotalTime()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class TrackDataHub {
|
|||||||
private EGM2008Utils.EGM2008Correction egm2008Correction;
|
private EGM2008Utils.EGM2008Correction egm2008Correction;
|
||||||
|
|
||||||
private boolean started;
|
private boolean started;
|
||||||
|
//TODO Check if this is needed.
|
||||||
private HandlerThread handlerThread;
|
private HandlerThread handlerThread;
|
||||||
private Handler handler;
|
private Handler handler;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ public class Track {
|
|||||||
public Track() {
|
public Track() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Track(Track track) {
|
||||||
|
this.id = track.id;
|
||||||
|
this.uuid = track.uuid;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.category = category;
|
||||||
|
this.icon = icon;
|
||||||
|
this.trackStatistics = trackStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* May be null if the track was not loaded from the database.
|
* May be null if the track was not loaded from the database.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+89
-248
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks.fragments;
|
|||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -22,10 +21,6 @@ import java.util.List;
|
|||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.TrackRecordingActivity;
|
import de.dennisguse.opentracks.TrackRecordingActivity;
|
||||||
import de.dennisguse.opentracks.adapters.SensorsAdapter;
|
import de.dennisguse.opentracks.adapters.SensorsAdapter;
|
||||||
import de.dennisguse.opentracks.content.TrackDataHub;
|
|
||||||
import de.dennisguse.opentracks.content.TrackDataListener;
|
|
||||||
import de.dennisguse.opentracks.content.data.Distance;
|
|
||||||
import de.dennisguse.opentracks.content.data.Marker;
|
|
||||||
import de.dennisguse.opentracks.content.data.Speed;
|
import de.dennisguse.opentracks.content.data.Speed;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
@@ -34,7 +29,6 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
|||||||
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
|
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
@@ -46,25 +40,17 @@ import de.dennisguse.opentracks.viewmodels.SensorDataModel;
|
|||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class StatisticsRecordingFragment extends Fragment implements TrackDataListener {
|
public class StatisticsRecordingFragment extends Fragment {
|
||||||
|
|
||||||
private static final String TAG = StatisticsRecordingFragment.class.getSimpleName();
|
private static final String TAG = StatisticsRecordingFragment.class.getSimpleName();
|
||||||
|
|
||||||
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
|
||||||
|
|
||||||
public static Fragment newInstance() {
|
public static Fragment newInstance() {
|
||||||
return new StatisticsRecordingFragment();
|
return new StatisticsRecordingFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrackDataHub trackDataHub;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
|
private TrackRecordingService.RecordingData recordingData = TrackRecordingService.NOT_RECORDING;
|
||||||
private Handler handlerUpdateUI;
|
private TrackPoint latestTrackPoint;
|
||||||
|
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
|
||||||
private TrackPoint lastTrackPoint;
|
|
||||||
|
|
||||||
@Nullable // Lazily loaded.
|
|
||||||
private Track track;
|
|
||||||
|
|
||||||
private StatisticsRecordingBinding viewBinding;
|
private StatisticsRecordingBinding viewBinding;
|
||||||
private SensorsAdapter sensorsAdapter;
|
private SensorsAdapter sensorsAdapter;
|
||||||
@@ -83,9 +69,9 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
preferenceMetricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, getContext());
|
preferenceMetricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key) && track != null) {
|
if (PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key) && recordingData != null) {
|
||||||
updateUInecessary = true;
|
updateUInecessary = true;
|
||||||
preferenceReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), track.getCategory());
|
preferenceReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), recordingData.getTrackCategory());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(getContext(), R.string.stats_show_grade_altitude_key, key)) {
|
if (PreferencesUtils.isKey(getContext(), R.string.stats_show_grade_altitude_key, key)) {
|
||||||
@@ -99,39 +85,29 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key != null && updateUInecessary && isResumed()) {
|
if (key != null && updateUInecessary && isResumed()) {
|
||||||
getActivity().runOnUiThread(() -> {
|
getActivity().runOnUiThread(this::updateUI);
|
||||||
if (isResumed()) {
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Runnable updateUIeachSecond = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isResumed() && isSelectedTrackRecording()) {
|
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
if (!isSelectedTrackPaused() && track != null) {
|
if (service == null) {
|
||||||
synchronized (this) {
|
Log.w(TAG, "could not get TrackRecordingService");
|
||||||
if (lastTrackPoint != null && lastTrackPoint.hasLocation() && !lastTrackPoint.isRecent()) {
|
return;
|
||||||
lastTrackPoint = null;
|
|
||||||
setLocationValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateTotalTime();
|
|
||||||
updateSensorDataUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerUpdateUI.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service.getRecordingDataObservable()
|
||||||
|
.observe(StatisticsRecordingFragment.this, recordingData -> onRecordingDataChanged(recordingData));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
handlerUpdateUI = new Handler();
|
|
||||||
|
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(getContext());
|
sharedPreferences = PreferencesUtils.getSharedPreferences(getContext());
|
||||||
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||||
|
|
||||||
sensorsAdapter = new SensorsAdapter(getContext());
|
sensorsAdapter = new SensorsAdapter(getContext());
|
||||||
}
|
}
|
||||||
@@ -139,7 +115,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
viewBinding = StatisticsRecordingBinding.inflate(inflater, container, false);
|
viewBinding = StatisticsRecordingBinding.inflate(inflater, container, false);
|
||||||
viewBinding.statsActivityTypeIcon.setOnClickListener(v -> ((TrackRecordingActivity) getActivity()).chooseActivityType(track != null ? track.getCategory() : "")); //TODO "" would be useless as Track was not yet loaded.
|
viewBinding.statsActivityTypeIcon.setOnClickListener(v -> ((TrackRecordingActivity) getActivity()).chooseActivityType(recordingData.getTrackCategory()));
|
||||||
|
|
||||||
RecyclerView sensorsRecyclerView = viewBinding.statsSensorsRecyclerView;
|
RecyclerView sensorsRecyclerView = viewBinding.statsSensorsRecyclerView;
|
||||||
sensorsRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
sensorsRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||||
@@ -151,25 +127,18 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
resumeTrackDataHub();
|
|
||||||
|
|
||||||
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
|
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
|
||||||
|
|
||||||
trackRecordingServiceConnection.startConnection(getContext());
|
trackRecordingServiceConnection.startConnection(getContext());
|
||||||
|
|
||||||
updateUIeachSecond.run();
|
|
||||||
handlerUpdateUI.post(updateUIeachSecond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
pauseTrackDataHub();
|
|
||||||
|
|
||||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
|
|
||||||
handlerUpdateUI.removeCallbacks(updateUIeachSecond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -191,101 +160,12 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
sharedPreferences = null;
|
sharedPreferences = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTrackUpdated(final Track track) {
|
|
||||||
if (isResumed()) {
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
if (isResumed()) {
|
|
||||||
if ((this.track == null && track != null) || (this.track != null && track != null && !this.track.getCategory().equals(track.getCategory()))) {
|
|
||||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, getString(R.string.stats_rate_key));
|
|
||||||
}
|
|
||||||
this.track = track;
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearTrackPoints() {
|
|
||||||
lastTrackPoint = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewTrackPointsDone(@NonNull TrackPoint newLastTrackPoint, @NonNull TrackStatistics trackStatistics) {
|
|
||||||
if (isResumed()) {
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
if (isResumed()) {
|
|
||||||
synchronized (this) {
|
|
||||||
this.lastTrackPoint = newLastTrackPoint;
|
|
||||||
|
|
||||||
if (!isSelectedTrackRecording() || isSelectedTrackPaused()) {
|
|
||||||
this.lastTrackPoint = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.lastTrackPoint != null && this.lastTrackPoint.hasLocation() && !this.lastTrackPoint.isRecent()) {
|
|
||||||
this.lastTrackPoint = null;
|
|
||||||
}
|
|
||||||
setLocationValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearMarkers() {
|
|
||||||
// We don't care.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewMarker(Marker marker) {
|
|
||||||
// We don't care.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewMarkersDone() {
|
|
||||||
// We don't care.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resumes the trackDataHub.
|
|
||||||
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
|
||||||
*/
|
|
||||||
private synchronized void resumeTrackDataHub() {
|
|
||||||
trackDataHub = ((TrackRecordingActivity) getActivity()).getTrackDataHub();
|
|
||||||
trackDataHub.registerTrackDataListener(this, true, false, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pauses the trackDataHub.
|
|
||||||
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
|
||||||
*/
|
|
||||||
private synchronized void pauseTrackDataHub() {
|
|
||||||
trackDataHub.unregisterTrackDataListener(this);
|
|
||||||
trackDataHub = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the selected track is recording.
|
|
||||||
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
|
||||||
*/
|
|
||||||
private synchronized boolean isSelectedTrackRecording() {
|
|
||||||
return trackDataHub != null && trackDataHub.isSelectedTrackRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the selected track is paused.
|
|
||||||
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
|
||||||
*/
|
|
||||||
private synchronized boolean isSelectedTrackPaused() {
|
|
||||||
return trackDataHub != null && trackDataHub.isSelectedTrackPaused();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUI() {
|
private void updateUI() {
|
||||||
updateStats();
|
if (isResumed()) {
|
||||||
setLocationValues();
|
updateStats();
|
||||||
updateSensorDataUI();
|
setLocationValues();
|
||||||
|
updateSensorDataUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,100 +173,45 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
* Also sets altitude gain and loss.
|
* Also sets altitude gain and loss.
|
||||||
*/
|
*/
|
||||||
private void updateSensorDataUI() {
|
private void updateSensorDataUI() {
|
||||||
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||||
|
if (sensorDataSet != null) {
|
||||||
if (trackRecordingService == null) {
|
List<SensorDataModel> sensorDataList = new ArrayList<>();
|
||||||
Log.d(TAG, "Cannot get the track recording service.");
|
if (sensorDataSet.getHeartRate() != null) {
|
||||||
} else {
|
sensorDataList.add(new SensorDataModel(sensorDataSet.getHeartRate()));
|
||||||
SensorDataSet sensorDataSet = trackRecordingService.getSensorDataSet();
|
|
||||||
if (sensorDataSet != null) {
|
|
||||||
List<SensorDataModel> sensorDataList = new ArrayList<>();
|
|
||||||
if (sensorDataSet.getHeartRate() != null) {
|
|
||||||
sensorDataList.add(new SensorDataModel(sensorDataSet.getHeartRate()));
|
|
||||||
}
|
|
||||||
if (sensorDataSet.getCyclingCadence() != null) {
|
|
||||||
sensorDataList.add(new SensorDataModel(sensorDataSet.getCyclingCadence()));
|
|
||||||
}
|
|
||||||
if (sensorDataSet.getCyclingPower() != null) {
|
|
||||||
sensorDataList.add(new SensorDataModel(sensorDataSet.getCyclingPower()));
|
|
||||||
}
|
|
||||||
sensorsAdapter.swapData(sensorDataList);
|
|
||||||
setSpeedSensorData(sensorDataSet);
|
|
||||||
}
|
}
|
||||||
//TODO Check if we can get the total altitude gain and loss via trackStatistics instead of doing some computation in the UI layer.
|
if (sensorDataSet.getCyclingCadence() != null) {
|
||||||
setTotalAltitudeGain(trackRecordingService.getAltitudeGain_m());
|
sensorDataList.add(new SensorDataModel(sensorDataSet.getCyclingCadence()));
|
||||||
setTotalAltitudeLoss(trackRecordingService.getAltitudeLoss_m());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set altitude gain
|
|
||||||
private void setTotalAltitudeGain(Float altitudeGain_m) {
|
|
||||||
Float totalAltitudeGain = altitudeGain_m;
|
|
||||||
|
|
||||||
if (track != null && track.getTrackStatistics().hasTotalAltitudeGain()) {
|
|
||||||
if (altitudeGain_m == null) {
|
|
||||||
totalAltitudeGain = 0f;
|
|
||||||
}
|
}
|
||||||
|
if (sensorDataSet.getCyclingPower() != null) {
|
||||||
totalAltitudeGain += track.getTrackStatistics().getTotalAltitudeGain();
|
sensorDataList.add(new SensorDataModel(sensorDataSet.getCyclingPower()));
|
||||||
|
}
|
||||||
|
sensorsAdapter.swapData(sensorDataList);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), totalAltitudeGain, preferenceMetricUnits);
|
{
|
||||||
viewBinding.statsAltitudeGainValue.setText(parts.first);
|
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), recordingData.getTrackStatistics().getTotalAltitudeGain(), preferenceMetricUnits);
|
||||||
viewBinding.statsAltitudeGainUnit.setText(parts.second);
|
viewBinding.statsAltitudeGainValue.setText(parts.first);
|
||||||
}
|
viewBinding.statsAltitudeGainUnit.setText(parts.second);
|
||||||
|
|
||||||
// Set altitude loss
|
|
||||||
private void setTotalAltitudeLoss(Float altitudeLoss_m) {
|
|
||||||
Float totalAltitudeLoss = altitudeLoss_m;
|
|
||||||
|
|
||||||
if (track != null && track.getTrackStatistics().hasTotalAltitudeLoss()) {
|
|
||||||
if (altitudeLoss_m == null) {
|
|
||||||
totalAltitudeLoss = track.getTrackStatistics().getTotalAltitudeLoss();
|
|
||||||
} else {
|
|
||||||
totalAltitudeLoss += track.getTrackStatistics().getTotalAltitudeLoss();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), totalAltitudeLoss, preferenceMetricUnits);
|
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), recordingData.getTrackStatistics().getTotalAltitudeLoss(), preferenceMetricUnits);
|
||||||
viewBinding.statsAltitudeLossValue.setText(parts.first);
|
viewBinding.statsAltitudeLossValue.setText(parts.first);
|
||||||
viewBinding.statsAltitudeLossUnit.setText(parts.second);
|
viewBinding.statsAltitudeLossUnit.setText(parts.second);
|
||||||
}
|
|
||||||
|
|
||||||
private void setSpeedSensorData(SensorDataSet sensorDataSet) {
|
|
||||||
if (sensorDataSet != null && sensorDataSet.getCyclingDistanceSpeed() != null) {
|
|
||||||
SensorDataCycling.DistanceSpeed data = sensorDataSet.getCyclingDistanceSpeed();
|
|
||||||
|
|
||||||
if (data.hasValue() && data.isRecent()) {
|
|
||||||
setTotalDistance(data.getValue().distanceOverall);
|
|
||||||
setSpeed(data.getValue().speed);
|
|
||||||
}
|
|
||||||
if (data.hasValue() && data.isRecent()) {
|
|
||||||
setSpeed(data.getValue().speed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStats() {
|
private void updateStats() {
|
||||||
|
|
||||||
setTotalDistance(Distance.of(0)); //TODO Why?
|
|
||||||
|
|
||||||
// Set activity type
|
// Set activity type
|
||||||
if (track != null) {
|
String trackIconValue = TrackIconUtils.getIconValue(getContext(), recordingData.getTrackCategory());
|
||||||
String trackIconValue = TrackIconUtils.getIconValue(getContext(), track.getCategory());
|
viewBinding.statsActivityTypeIcon.setImageResource(TrackIconUtils.getIconDrawable(trackIconValue));
|
||||||
viewBinding.statsActivityTypeIcon.setEnabled(isSelectedTrackRecording());
|
|
||||||
viewBinding.statsActivityTypeIcon.setImageResource(TrackIconUtils.getIconDrawable(trackIconValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set time
|
// Set time
|
||||||
if (track != null) {
|
viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(recordingData.getTrackStatistics().getMovingTime()));
|
||||||
viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(track.getTrackStatistics().getMovingTime()));
|
updateTotalTime();
|
||||||
updateTotalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set average speed/pace
|
// Set average speed/pace
|
||||||
{
|
{
|
||||||
Speed speed = track != null ? track.getTrackStatistics().getAverageSpeed() : null;
|
Speed speed = recordingData.getTrackStatistics().getAverageSpeed();
|
||||||
viewBinding.statsAverageSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
|
viewBinding.statsAverageSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
|
||||||
|
|
||||||
Pair<String, String> parts = StringUtils.getSpeedParts(getContext(), speed, preferenceMetricUnits, preferenceReportSpeed);
|
Pair<String, String> parts = StringUtils.getSpeedParts(getContext(), speed, preferenceMetricUnits, preferenceReportSpeed);
|
||||||
@@ -396,7 +221,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
|
|
||||||
// Set max speed/pace
|
// Set max speed/pace
|
||||||
{
|
{
|
||||||
Speed speed = track != null ? track.getTrackStatistics().getMaxSpeed() : null;
|
Speed speed = recordingData.getTrackStatistics().getMaxSpeed();
|
||||||
|
|
||||||
viewBinding.statsMaxSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace);
|
viewBinding.statsMaxSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace);
|
||||||
|
|
||||||
@@ -407,7 +232,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
|
|
||||||
// Set moving speed/pace
|
// Set moving speed/pace
|
||||||
{
|
{
|
||||||
Speed speed = track != null ? track.getTrackStatistics().getAverageMovingSpeed() : null;
|
Speed speed = recordingData.getTrackStatistics().getAverageMovingSpeed();
|
||||||
|
|
||||||
viewBinding.statsMovingSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace);
|
viewBinding.statsMovingSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace);
|
||||||
|
|
||||||
@@ -417,34 +242,41 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set altitude gain and loss
|
// Set altitude gain and loss
|
||||||
{
|
viewBinding.statsAltitudeGroup.setVisibility(preferenceShowAltitude ? View.VISIBLE : View.GONE);
|
||||||
viewBinding.statsAltitudeGroup.setVisibility(preferenceShowAltitude ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalTime() {
|
private void updateTotalTime() {
|
||||||
Duration totalTime = track.getTrackStatistics().getTotalTime();
|
Duration totalTime = recordingData.getTrackStatistics().getTotalTime();
|
||||||
if (isSelectedTrackRecording()) {
|
|
||||||
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (trackRecordingService != null) {
|
|
||||||
totalTime = trackRecordingService.getTotalTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
|
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLocationValues() {
|
private void setLocationValues() {
|
||||||
// Set speed/pace
|
// Set speed/pace
|
||||||
Speed speed = lastTrackPoint != null && lastTrackPoint.hasSpeed() ? lastTrackPoint.getSpeed() : null;
|
Speed speed = latestTrackPoint != null && latestTrackPoint.hasSpeed() ? latestTrackPoint.getSpeed() : null;
|
||||||
|
|
||||||
|
SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||||
|
if (sensorDataSet != null && sensorDataSet.getCyclingDistanceSpeed() != null) {
|
||||||
|
SensorDataCycling.DistanceSpeed data = sensorDataSet.getCyclingDistanceSpeed();
|
||||||
|
if (data.hasValue() && data.isRecent()) {
|
||||||
|
speed = data.getValue().speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setSpeed(speed);
|
setSpeed(speed);
|
||||||
|
|
||||||
|
// Set distance
|
||||||
|
{
|
||||||
|
Pair<String, String> parts = StringUtils.getDistanceParts(getContext(), recordingData.getTrackStatistics().getTotalDistance(), preferenceMetricUnits);
|
||||||
|
|
||||||
|
viewBinding.statsDistanceValue.setText(parts.first);
|
||||||
|
viewBinding.statsDistanceUnit.setText(parts.second);
|
||||||
|
}
|
||||||
// Set altitude
|
// Set altitude
|
||||||
viewBinding.statsAltitudeGroup.setVisibility(preferenceShowAltitude ? View.VISIBLE : View.GONE);
|
viewBinding.statsAltitudeGroup.setVisibility(preferenceShowAltitude ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if (preferenceShowAltitude) {
|
if (preferenceShowAltitude) {
|
||||||
// Current altitude
|
// Current altitude
|
||||||
Float altitude = lastTrackPoint != null && lastTrackPoint.hasAltitude() ? (float) lastTrackPoint.getAltitude().toM() : null;
|
Float altitude = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? (float) latestTrackPoint.getAltitude().toM() : null;
|
||||||
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), altitude, preferenceMetricUnits);
|
Pair<String, String> parts = StringUtils.formatAltitude(getContext(), altitude, preferenceMetricUnits);
|
||||||
viewBinding.statsAltitudeCurrentValue.setText(parts.first);
|
viewBinding.statsAltitudeCurrentValue.setText(parts.first);
|
||||||
viewBinding.statsAltitudeCurrentUnit.setText(parts.second);
|
viewBinding.statsAltitudeCurrentUnit.setText(parts.second);
|
||||||
@@ -455,23 +287,15 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
if (preferenceShowCoordinate) {
|
if (preferenceShowCoordinate) {
|
||||||
String latitudeText = getContext().getString(R.string.value_unknown);
|
String latitudeText = getContext().getString(R.string.value_unknown);
|
||||||
String longitudeText = getContext().getString(R.string.value_unknown);
|
String longitudeText = getContext().getString(R.string.value_unknown);
|
||||||
if (lastTrackPoint != null && lastTrackPoint.hasLocation()) {
|
if (latestTrackPoint != null && latestTrackPoint.hasLocation()) {
|
||||||
latitudeText = StringUtils.formatCoordinate(lastTrackPoint.getLatitude());
|
latitudeText = StringUtils.formatCoordinate(latestTrackPoint.getLatitude());
|
||||||
longitudeText = StringUtils.formatCoordinate(lastTrackPoint.getLongitude());
|
longitudeText = StringUtils.formatCoordinate(latestTrackPoint.getLongitude());
|
||||||
}
|
}
|
||||||
viewBinding.statsLatitudeValue.setText(latitudeText);
|
viewBinding.statsLatitudeValue.setText(latitudeText);
|
||||||
viewBinding.statsLongitudeValue.setText(longitudeText);
|
viewBinding.statsLongitudeValue.setText(longitudeText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTotalDistance(Distance sensorDistanceSinceLastTrackpoint) {
|
|
||||||
Distance totalDistance = track != null ? (track.getTrackStatistics().getTotalDistance().plus(sensorDistanceSinceLastTrackpoint)) : Distance.invalid();
|
|
||||||
Pair<String, String> parts = StringUtils.getDistanceParts(getContext(), totalDistance, preferenceMetricUnits);
|
|
||||||
|
|
||||||
viewBinding.statsDistanceValue.setText(parts.first);
|
|
||||||
viewBinding.statsDistanceUnit.setText(parts.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSpeed(Speed speed) {
|
private void setSpeed(Speed speed) {
|
||||||
viewBinding.statsSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_speed : R.string.stats_pace);
|
viewBinding.statsSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_speed : R.string.stats_pace);
|
||||||
|
|
||||||
@@ -479,4 +303,21 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
|||||||
viewBinding.statsSpeedValue.setText(parts.first);
|
viewBinding.statsSpeedValue.setText(parts.first);
|
||||||
viewBinding.statsSpeedUnit.setText(parts.second);
|
viewBinding.statsSpeedUnit.setText(parts.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onRecordingDataChanged(TrackRecordingService.RecordingData recordingData) {
|
||||||
|
String oldCategory = this.recordingData.getTrackCategory();
|
||||||
|
String newCategory = recordingData.getTrackCategory();
|
||||||
|
|
||||||
|
if (!oldCategory.equals(newCategory)) {
|
||||||
|
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, getString(R.string.stats_rate_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.recordingData = recordingData;
|
||||||
|
this.latestTrackPoint = recordingData.getLatestTrackPoint();
|
||||||
|
if (latestTrackPoint != null && latestTrackPoint.hasLocation() && !latestTrackPoint.isRecent()) {
|
||||||
|
latestTrackPoint = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
|
|
||||||
private static final String TAG = TrackRecordingService.class.getSimpleName();
|
private static final String TAG = TrackRecordingService.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
||||||
|
|
||||||
public static final RecordingStatus STATUS_DEFAULT = new RecordingStatus(null, false);
|
public static final RecordingStatus STATUS_DEFAULT = new RecordingStatus(null, false);
|
||||||
|
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null);
|
||||||
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
|
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
|
||||||
|
|
||||||
// The following variables are set in onCreate:
|
// The following variables are set in onCreate:
|
||||||
@@ -84,6 +87,19 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
private PeriodicTaskExecutor voiceExecutor;
|
private PeriodicTaskExecutor voiceExecutor;
|
||||||
private TrackRecordingServiceNotificationManager notificationManager;
|
private TrackRecordingServiceNotificationManager notificationManager;
|
||||||
|
|
||||||
|
private Handler handler;
|
||||||
|
private final Runnable updateRecordingData = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Track track = contentProviderUtils.getTrack(recordingStatus.getTrackId());
|
||||||
|
track.getTrackStatistics().setTotalTime(TrackRecordingService.this.getTotalTime());
|
||||||
|
|
||||||
|
SensorDataSet sensorDataSet = fillWithSensorDataSet(lastTrackPoint);
|
||||||
|
recordingDataObservable.postValue(new RecordingData(track, lastTrackPoint, sensorDataSet));
|
||||||
|
handler.postDelayed(this, RECORDING_DATA_UPDATE_INTERVAL.toMillis());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
private Distance recordingDistanceInterval;
|
private Distance recordingDistanceInterval;
|
||||||
@@ -127,14 +143,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
private RecordingStatus recordingStatus;
|
private RecordingStatus recordingStatus;
|
||||||
private MutableLiveData<RecordingStatus> recordingStatusObservable;
|
private MutableLiveData<RecordingStatus> recordingStatusObservable;
|
||||||
private MutableLiveData<GpsStatusValue> gpsStatusObservable;
|
private MutableLiveData<GpsStatusValue> gpsStatusObservable;
|
||||||
|
private MutableLiveData<RecordingData> recordingDataObservable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
|
handler = new Handler();
|
||||||
|
|
||||||
recordingStatusObservable = new MutableLiveData<>();
|
recordingStatusObservable = new MutableLiveData<>();
|
||||||
updateRecordingStatus(STATUS_DEFAULT);
|
updateRecordingStatus(STATUS_DEFAULT);
|
||||||
gpsStatusObservable = new MutableLiveData<>(STATUS_GPS_DEFAULT);
|
gpsStatusObservable = new MutableLiveData<>(STATUS_GPS_DEFAULT);
|
||||||
|
recordingDataObservable = new MutableLiveData<>(NOT_RECORDING);
|
||||||
|
|
||||||
handlerServer = new HandlerServer(this);
|
handlerServer = new HandlerServer(this);
|
||||||
|
|
||||||
@@ -160,6 +180,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
handler = null;
|
||||||
|
|
||||||
handlerServer.stop(this);
|
handlerServer.stop(this);
|
||||||
handlerServer = null;
|
handlerServer = null;
|
||||||
|
|
||||||
@@ -192,6 +214,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
|
|
||||||
recordingStatusObservable = null;
|
recordingStatusObservable = null;
|
||||||
gpsStatusObservable = null;
|
gpsStatusObservable = null;
|
||||||
|
recordingDataObservable = null;
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
@@ -208,6 +231,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
return recordingStatus.getTrackId();
|
return recordingStatus.getTrackId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
public TrackStatistics getTrackStatistics() {
|
public TrackStatistics getTrackStatistics() {
|
||||||
if (trackStatisticsUpdater == null) {
|
if (trackStatisticsUpdater == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -352,6 +376,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
remoteSensorManager = new BluetoothRemoteSensorManager(this);
|
remoteSensorManager = new BluetoothRemoteSensorManager(this);
|
||||||
remoteSensorManager.start();
|
remoteSensorManager.start();
|
||||||
|
|
||||||
|
handler.postDelayed(updateRecordingData, RECORDING_DATA_UPDATE_INTERVAL.toMillis());
|
||||||
|
|
||||||
altitudeSumManager = new AltitudeSumManager();
|
altitudeSumManager = new AltitudeSumManager();
|
||||||
altitudeSumManager.start(this);
|
altitudeSumManager.start(this);
|
||||||
|
|
||||||
@@ -438,6 +464,13 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
* @param trackStopped true if track is stopped, false if track is paused
|
* @param trackStopped true if track is stopped, false if track is paused
|
||||||
*/
|
*/
|
||||||
private void endRecording(boolean trackStopped) {
|
private void endRecording(boolean trackStopped) {
|
||||||
|
if (trackStopped) {
|
||||||
|
recordingDataObservable.postValue(NOT_RECORDING);
|
||||||
|
} else {
|
||||||
|
updateRecordingData.run();
|
||||||
|
}
|
||||||
|
handler.removeCallbacks(updateRecordingData);
|
||||||
|
|
||||||
// Shutdown periodic tasks
|
// Shutdown periodic tasks
|
||||||
voiceExecutor.shutdown();
|
voiceExecutor.shutdown();
|
||||||
|
|
||||||
@@ -613,14 +646,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
trackPoint.setAltitudeLoss(getAltitudeLoss_m());
|
trackPoint.setAltitudeLoss(getAltitudeLoss_m());
|
||||||
altitudeSumManager.reset();
|
altitudeSumManager.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO We need a copy of the SensorDataSet as data will be reset!
|
||||||
|
SensorDataSet sensorDataSet = fillWithSensorDataSet(trackPoint);
|
||||||
if (remoteSensorManager != null) {
|
if (remoteSensorManager != null) {
|
||||||
fillWithSensorDataSet(trackPoint);
|
|
||||||
remoteSensorManager.reset();
|
remoteSensorManager.reset();
|
||||||
}
|
}
|
||||||
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
|
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
|
||||||
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
||||||
|
|
||||||
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||||
|
|
||||||
|
recordingDataObservable.postValue(new RecordingData(track, trackPoint, sensorDataSet));
|
||||||
|
|
||||||
contentProviderUtils.updateTrack(track);
|
contentProviderUtils.updateTrack(track);
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
/*
|
/*
|
||||||
@@ -632,25 +669,26 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
voiceExecutor.update();
|
voiceExecutor.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SensorDataSet getSensorDataSet() {
|
private SensorDataSet fillWithSensorDataSet(TrackPoint trackPoint) {
|
||||||
if (remoteSensorManager == null) {
|
if (remoteSensorManager == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return remoteSensorManager.getSensorData();
|
SensorDataSet sensorData = remoteSensorManager.getSensorData();
|
||||||
}
|
if (sensorData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void fillWithSensorDataSet(TrackPoint trackPoint) {
|
if (trackPoint != null) {
|
||||||
SensorDataSet sensorData = getSensorDataSet();
|
|
||||||
if (sensorData != null) {
|
|
||||||
sensorData.fillTrackPoint(trackPoint);
|
sensorData.fillTrackPoint(trackPoint);
|
||||||
}
|
}
|
||||||
|
return sensorData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the relative altitude gain (since last trackpoint).
|
* Returns the relative altitude gain (since last trackpoint).
|
||||||
*/
|
*/
|
||||||
public Float getAltitudeGain_m() {
|
private Float getAltitudeGain_m() {
|
||||||
if (altitudeSumManager == null || !altitudeSumManager.isConnected()) {
|
if (altitudeSumManager == null || !altitudeSumManager.isConnected()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -661,7 +699,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
/**
|
/**
|
||||||
* Returns the relative altitude loss (since last trackpoint).
|
* Returns the relative altitude loss (since last trackpoint).
|
||||||
*/
|
*/
|
||||||
public Float getAltitudeLoss_m() {
|
private Float getAltitudeLoss_m() {
|
||||||
if (altitudeSumManager == null || !altitudeSumManager.isConnected()) {
|
if (altitudeSumManager == null || !altitudeSumManager.isConnected()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -712,6 +750,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
return gpsStatusObservable;
|
return gpsStatusObservable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MutableLiveData<RecordingData> getRecordingDataObservable() {
|
||||||
|
return recordingDataObservable;
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<RecordingStatus> getRecordingStatusObservable() {
|
public LiveData<RecordingStatus> getRecordingStatusObservable() {
|
||||||
return recordingStatusObservable;
|
return recordingStatusObservable;
|
||||||
}
|
}
|
||||||
@@ -792,4 +834,50 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class RecordingData {
|
||||||
|
|
||||||
|
private final Track track;
|
||||||
|
|
||||||
|
private final TrackPoint latestTrackPoint;
|
||||||
|
|
||||||
|
private final SensorDataSet sensorDataSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
|
||||||
|
*/
|
||||||
|
public RecordingData(Track track, TrackPoint lastTrackPoint, SensorDataSet sensorDataSet) {
|
||||||
|
this.track = track;
|
||||||
|
this.latestTrackPoint = lastTrackPoint;
|
||||||
|
this.sensorDataSet = sensorDataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Track getTrack() {
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrackCategory() {
|
||||||
|
if (track == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return track.getCategory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public TrackStatistics getTrackStatistics() {
|
||||||
|
if (track == null) {
|
||||||
|
return new TrackStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
return track.getTrackStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackPoint getLatestTrackPoint() {
|
||||||
|
return latestTrackPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SensorDataSet getSensorDataSet() {
|
||||||
|
return sensorDataSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,7 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death
|
|||||||
|
|
||||||
private static final String TAG = TrackRecordingServiceConnection.class.getSimpleName();
|
private static final String TAG = TrackRecordingServiceConnection.class.getSimpleName();
|
||||||
|
|
||||||
|
@Deprecated //TODO Implement proper interface that passes the current TrackRecordingService
|
||||||
private final Runnable callback;
|
private final Runnable callback;
|
||||||
|
|
||||||
private TrackRecordingService trackRecordingService;
|
private TrackRecordingService trackRecordingService;
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
|
|||||||
}
|
}
|
||||||
String category = track.getCategory();
|
String category = track.getCategory();
|
||||||
|
|
||||||
//TODO Querying all TrackPoints all the time is inefficient; use TrackDataHub or something else.
|
//TODO Querying all TrackPoints all the time is inefficient; get infos from TrackRecordingService
|
||||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||||
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||||
while (trackPointIterator.hasNext()) {
|
while (trackPointIterator.hasNext()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user