forked from upstream-mirrors/OpenTracks
Voice announcements are now triggered by the TrackRecordingService's timer that is also used for UI updates.
This commit is contained in:
+6
-6
@@ -25,7 +25,7 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class PeriodicTaskExecutorTest {
|
public class VoiceAnnouncementManagerTest {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
|
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
|
||||||
@@ -53,17 +53,17 @@ public class PeriodicTaskExecutorTest {
|
|||||||
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
||||||
.getService();
|
.getService();
|
||||||
|
|
||||||
PeriodicTaskExecutor periodicTaskExecutor = new PeriodicTaskExecutor(service, new AnnouncementPeriodicTask.Factory());
|
VoiceAnnouncementManager voiceAnnouncementManager = new VoiceAnnouncementManager(service);
|
||||||
periodicTaskExecutor.setMetricUnits(true);
|
voiceAnnouncementManager.setMetricUnits(true);
|
||||||
periodicTaskExecutor.setTaskFrequency(-5);
|
voiceAnnouncementManager.setTaskFrequency(-5);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
statistics.setTotalDistance(Distance.of(13000));
|
statistics.setTotalDistance(Distance.of(13000));
|
||||||
assertEquals(Distance.of(15000), periodicTaskExecutor.calculateNextTaskDistance(statistics));
|
assertEquals(Distance.of(15000), voiceAnnouncementManager.calculateNextTaskDistance(statistics));
|
||||||
|
|
||||||
statistics.setTotalDistance(Distance.of(15100));
|
statistics.setTotalDistance(Distance.of(15100));
|
||||||
assertEquals(Distance.of(20000), periodicTaskExecutor.calculateNextTaskDistance(statistics));
|
assertEquals(Distance.of(20000), voiceAnnouncementManager.calculateNextTaskDistance(statistics));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -49,9 +49,7 @@ import de.dennisguse.opentracks.io.file.exporter.ExportServiceResultReceiver;
|
|||||||
import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
|
import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
|
||||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||||
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTask;
|
import de.dennisguse.opentracks.services.tasks.VoiceAnnouncementManager;
|
||||||
import de.dennisguse.opentracks.services.tasks.PeriodicTaskExecutor;
|
|
||||||
import de.dennisguse.opentracks.services.tasks.PeriodicTaskFactory;
|
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.ExportUtils;
|
import de.dennisguse.opentracks.util.ExportUtils;
|
||||||
@@ -76,7 +74,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
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:
|
||||||
private PeriodicTaskExecutor voiceExecutor;
|
private VoiceAnnouncementManager voiceAnnouncementManager;
|
||||||
private TrackRecordingServiceNotificationManager notificationManager;
|
private TrackRecordingServiceNotificationManager notificationManager;
|
||||||
|
|
||||||
private TrackRecordingManager trackRecordingManager;
|
private TrackRecordingManager trackRecordingManager;
|
||||||
@@ -106,11 +104,11 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
Context context = TrackRecordingService.this;
|
Context context = TrackRecordingService.this;
|
||||||
if (PreferencesUtils.isKey(context, R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(context, R.string.stats_units_key, key)) {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, context);
|
boolean metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, context);
|
||||||
voiceExecutor.setMetricUnits(metricUnits);
|
voiceAnnouncementManager.setMetricUnits(metricUnits);
|
||||||
notificationManager.setMetricUnits(metricUnits);
|
notificationManager.setMetricUnits(metricUnits);
|
||||||
}
|
}
|
||||||
if (PreferencesUtils.isKey(context, R.string.voice_frequency_key, key)) {
|
if (PreferencesUtils.isKey(context, R.string.voice_frequency_key, key)) {
|
||||||
voiceExecutor.setTaskFrequency(PreferencesUtils.getVoiceFrequency(sharedPreferences, context));
|
voiceAnnouncementManager.setTaskFrequency(PreferencesUtils.getVoiceFrequency(sharedPreferences, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -145,7 +143,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
trackRecordingManager = new TrackRecordingManager(this);
|
trackRecordingManager = new TrackRecordingManager(this);
|
||||||
handlerServer = new TrackPointCreator(this);
|
handlerServer = new TrackPointCreator(this);
|
||||||
|
|
||||||
voiceExecutor = new PeriodicTaskExecutor(this, new AnnouncementPeriodicTask.Factory());
|
voiceAnnouncementManager = new VoiceAnnouncementManager(this);
|
||||||
|
|
||||||
notificationManager = new TrackRecordingServiceNotificationManager(this);
|
notificationManager = new TrackRecordingServiceNotificationManager(this);
|
||||||
|
|
||||||
@@ -178,9 +176,9 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
sharedPreferences = null;
|
sharedPreferences = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
voiceExecutor.shutdown();
|
voiceAnnouncementManager.shutdown();
|
||||||
} finally {
|
} finally {
|
||||||
voiceExecutor = null;
|
voiceAnnouncementManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be the next to last operation
|
// This should be the next to last operation
|
||||||
@@ -209,10 +207,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
return trackRecordingManager.insertMarker(name, category, description, photoUrl);
|
return trackRecordingManager.insertMarker(name, category, description, photoUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(@NonNull PeriodicTaskFactory.Task periodicTask) {
|
|
||||||
periodicTask.run(recordingStatus.getTrackId(), trackRecordingManager.getTrackStatistics());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a new track.
|
* Starts a new track.
|
||||||
*
|
*
|
||||||
@@ -267,8 +261,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
|
|
||||||
startGps();
|
startGps();
|
||||||
|
|
||||||
// Restore periodic tasks
|
voiceAnnouncementManager.restore(trackRecordingManager.getTrackStatistics());
|
||||||
voiceExecutor.restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tryStartGps() {
|
public void tryStartGps() {
|
||||||
@@ -337,7 +330,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown periodic tasks
|
// Shutdown periodic tasks
|
||||||
voiceExecutor.shutdown();
|
voiceAnnouncementManager.shutdown();
|
||||||
|
|
||||||
// Update instance variables
|
// Update instance variables
|
||||||
handlerServer.stop();
|
handlerServer.stop();
|
||||||
@@ -374,7 +367,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
|
|
||||||
trackRecordingManager.onNewTrackPoint(trackPoint, thresholdHorizontalAccuracy);
|
trackRecordingManager.onNewTrackPoint(trackPoint, thresholdHorizontalAccuracy);
|
||||||
notificationManager.updateTrackPoint(this, trackRecordingManager.getTrackStatistics(), trackPoint, thresholdHorizontalAccuracy);
|
notificationManager.updateTrackPoint(this, trackRecordingManager.getTrackStatistics(), trackPoint, thresholdHorizontalAccuracy);
|
||||||
voiceExecutor.update(recordingStatus.getTrackId(), trackRecordingManager.getTrackStatistics());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -416,10 +408,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Duration getTotalTime() {
|
|
||||||
return trackRecordingManager.getTrackStatistics().getTotalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public TrackPointCreator getHandlerServer() {
|
public TrackPointCreator getHandlerServer() {
|
||||||
@@ -430,7 +418,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
return gpsStatusObservable;
|
return gpsStatusObservable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<RecordingData> getRecordingDataObservable() {
|
public LiveData<RecordingData> getRecordingDataObservable() {
|
||||||
return recordingDataObservable;
|
return recordingDataObservable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,6 +445,8 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
|||||||
TrackPoint trackPoint = data.second.first;
|
TrackPoint trackPoint = data.second.first;
|
||||||
egm2008CorrectionManager.correctAltitude(this, trackPoint);
|
egm2008CorrectionManager.correctAltitude(this, trackPoint);
|
||||||
|
|
||||||
|
voiceAnnouncementManager.update(data.first);
|
||||||
|
|
||||||
recordingDataObservable.postValue(new RecordingData(data.first, trackPoint, data.second.second));
|
recordingDataObservable.postValue(new RecordingData(data.first, trackPoint, data.second.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.services.tasks;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for classes that can create {@link Task}.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
public interface PeriodicTaskFactory {
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
Task create(Context context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is interface for a task that will be executed on some schedule.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
interface Task {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up this task for subsequent calls to the run method.
|
|
||||||
*/
|
|
||||||
void start();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will be called periodically.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
void run(@NonNull Track.Id trackId, @NonNull TrackStatistics trackStatistics);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shuts down this task and clean up resources.
|
|
||||||
*/
|
|
||||||
void shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-31
@@ -38,13 +38,13 @@ import de.dennisguse.opentracks.util.PreferencesUtils;
|
|||||||
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
|
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will periodically announce the user's {@link TrackStatistics}.
|
* This class will announce the user's {@link TrackStatistics}.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
public class AnnouncementPeriodicTask implements PeriodicTaskFactory.Task {
|
public class VoiceAnnouncement {
|
||||||
|
|
||||||
private static final String TAG = AnnouncementPeriodicTask.class.getSimpleName();
|
private static final String TAG = VoiceAnnouncement.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
@@ -107,14 +107,13 @@ public class AnnouncementPeriodicTask implements PeriodicTaskFactory.Task {
|
|||||||
|
|
||||||
private boolean ttsReady = false;
|
private boolean ttsReady = false;
|
||||||
|
|
||||||
AnnouncementPeriodicTask(Context context) {
|
VoiceAnnouncement(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
contentProviderUtils = new ContentProviderUtils(context);
|
contentProviderUtils = new ContentProviderUtils(context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
public void start() {
|
||||||
Log.d(TAG, "Start");
|
Log.d(TAG, "Start");
|
||||||
|
|
||||||
@@ -128,8 +127,7 @@ public class AnnouncementPeriodicTask implements PeriodicTaskFactory.Task {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void announce(@NonNull Track track) {
|
||||||
public void run(@NonNull Track.Id trackId, @NonNull TrackStatistics trackStatistics) {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!ttsReady) {
|
if (!ttsReady) {
|
||||||
ttsReady = ttsInitStatus == TextToSpeech.SUCCESS;
|
ttsReady = ttsInitStatus == TextToSpeech.SUCCESS;
|
||||||
@@ -149,27 +147,20 @@ public class AnnouncementPeriodicTask implements PeriodicTaskFactory.Task {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
|
||||||
if (track == null) {
|
|
||||||
Log.i(TAG, "It doesn't exists a track with trackid = " + track);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String category = track.getCategory();
|
|
||||||
|
|
||||||
boolean isMetricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, context);
|
boolean isMetricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, context);
|
||||||
boolean isReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, context, category);
|
boolean isReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, context, track.getCategory());
|
||||||
Distance minGPSDistance = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context);
|
Distance minGPSDistance = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context);
|
||||||
|
|
||||||
|
//TODO Do not load all trackpoints for every announcement
|
||||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits), minGPSDistance);
|
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits), minGPSDistance);
|
||||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||||
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
||||||
|
|
||||||
String announcement = AnnouncementUtils.getAnnouncement(context, trackStatistics, isMetricUnits, isReportSpeed, lastInterval);
|
String announcement = AnnouncementUtils.getAnnouncement(context, track.getTrackStatistics(), isMetricUnits, isReportSpeed, lastInterval);
|
||||||
speakAnnouncement(announcement);
|
speakAnnouncement(announcement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (tts != null) {
|
if (tts != null) {
|
||||||
tts.shutdown();
|
tts.shutdown();
|
||||||
@@ -199,18 +190,4 @@ public class AnnouncementPeriodicTask implements PeriodicTaskFactory.Task {
|
|||||||
// We don't care about the utterance id. It is supplied here to force onUtteranceCompleted to be called.
|
// We don't care about the utterance id. It is supplied here to force onUtteranceCompleted to be called.
|
||||||
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null, "not used");
|
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null, "not used");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link PeriodicTaskFactory} for text-to-speech announcement periodic task.
|
|
||||||
*
|
|
||||||
* @author Rodrigo Damazio
|
|
||||||
*/
|
|
||||||
public static class Factory implements PeriodicTaskFactory {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NonNull
|
|
||||||
public Task create(Context context) {
|
|
||||||
return new AnnouncementPeriodicTask(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+46
-74
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package de.dennisguse.opentracks.services.tasks;
|
package de.dennisguse.opentracks.services.tasks;
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -34,12 +33,11 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
|||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
public class PeriodicTaskExecutor {
|
public class VoiceAnnouncementManager {
|
||||||
|
|
||||||
private static final String TAG = PeriodicTaskExecutor.class.getSimpleName();
|
private static final String TAG = VoiceAnnouncementManager.class.getSimpleName();
|
||||||
|
|
||||||
private final TrackRecordingService trackRecordingService;
|
private final TrackRecordingService trackRecordingService;
|
||||||
private final PeriodicTaskFactory periodicTaskFactory;
|
|
||||||
|
|
||||||
private final int TASK_FREQUENCY_OFF;
|
private final int TASK_FREQUENCY_OFF;
|
||||||
/**
|
/**
|
||||||
@@ -50,102 +48,76 @@ public class PeriodicTaskExecutor {
|
|||||||
*/
|
*/
|
||||||
private int taskFrequency;
|
private int taskFrequency;
|
||||||
|
|
||||||
private PeriodicTaskFactory.Task periodicTask;
|
private VoiceAnnouncement voiceAnnouncement;
|
||||||
|
|
||||||
private Handler handler;
|
|
||||||
|
|
||||||
private boolean metricUnits;
|
private boolean metricUnits;
|
||||||
|
|
||||||
private TrackStatistics trackStatistics;
|
private TrackStatistics trackStatistics;
|
||||||
private Distance nextTaskDistance = Distance.of(Double.MAX_VALUE);
|
private Distance nextTotalDistance = Distance.of(Double.MAX_VALUE);
|
||||||
|
private Duration nextTotalTime = Duration.ofSeconds(Long.MAX_VALUE);
|
||||||
|
|
||||||
private final Runnable timer = new Runnable() {
|
public VoiceAnnouncementManager(@NonNull TrackRecordingService trackRecordingService) {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (trackRecordingService != null && periodicTask != null) {
|
|
||||||
trackRecordingService.run(periodicTask);
|
|
||||||
handler.postDelayed(this, getNextDuration());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public PeriodicTaskExecutor(@NonNull TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
|
|
||||||
this.trackRecordingService = trackRecordingService;
|
this.trackRecordingService = trackRecordingService;
|
||||||
this.periodicTaskFactory = periodicTaskFactory;
|
|
||||||
|
|
||||||
TASK_FREQUENCY_OFF = Integer.parseInt(trackRecordingService.getString(R.string.frequency_off));
|
TASK_FREQUENCY_OFF = Integer.parseInt(trackRecordingService.getString(R.string.frequency_off));
|
||||||
taskFrequency = TASK_FREQUENCY_OFF;
|
taskFrequency = TASK_FREQUENCY_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore() {
|
public void restore(TrackStatistics trackStatistics) {
|
||||||
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()) {
|
|
||||||
Log.d(TAG, "Not recording or paused.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isTimeFrequency() && handler != null) {
|
|
||||||
handler.removeCallbacks(timer);
|
|
||||||
handler = null;
|
|
||||||
}
|
|
||||||
if (taskFrequency == TASK_FREQUENCY_OFF) {
|
if (taskFrequency == TASK_FREQUENCY_OFF) {
|
||||||
Log.d(TAG, "Task frequency is off.");
|
Log.d(TAG, "Task frequency is off.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
periodicTask = periodicTaskFactory.create(trackRecordingService);
|
voiceAnnouncement = new VoiceAnnouncement(trackRecordingService);
|
||||||
periodicTask.start();
|
voiceAnnouncement.start();
|
||||||
|
|
||||||
if (isTimeFrequency()) {
|
if (isTimeFrequency()) {
|
||||||
if (handler == null) {
|
nextTotalTime = calculateNextDuration(trackStatistics);
|
||||||
handler = new Handler();
|
|
||||||
}
|
|
||||||
handler.postDelayed(timer, getNextDuration());
|
|
||||||
} else {
|
} else {
|
||||||
// For distance periodic task
|
// For distance periodic task
|
||||||
updateNextTaskDistance();
|
updateNextTaskDistance(trackStatistics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(@NonNull Track track) {
|
||||||
|
boolean announce = false;
|
||||||
|
this.trackStatistics = track.getTrackStatistics();
|
||||||
|
if (trackStatistics.getTotalDistance().greaterThan(nextTotalDistance)) {
|
||||||
|
updateNextTaskDistance(trackStatistics);
|
||||||
|
announce = true;
|
||||||
|
}
|
||||||
|
if (!trackStatistics.getTotalTime().minus(nextTotalTime).isNegative()) {
|
||||||
|
nextTotalTime = calculateNextDuration(trackStatistics);
|
||||||
|
announce = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (announce) {
|
||||||
|
this.trackStatistics = track.getTrackStatistics();
|
||||||
|
voiceAnnouncement.announce(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (periodicTask != null) {
|
if (voiceAnnouncement != null) {
|
||||||
periodicTask.shutdown();
|
voiceAnnouncement.shutdown();
|
||||||
periodicTask = null;
|
voiceAnnouncement = null;
|
||||||
}
|
|
||||||
if (handler != null) {
|
|
||||||
handler.removeCallbacks(timer);
|
|
||||||
handler = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(@NonNull Track.Id trackId, @NonNull TrackStatistics trackStatistics) {
|
|
||||||
if (!isDistanceFrequency() || periodicTask == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trackStatistics.getTotalDistance().greaterThan(nextTaskDistance)) {
|
|
||||||
periodicTask.run(trackId, trackStatistics);
|
|
||||||
this.trackStatistics = trackStatistics;
|
|
||||||
updateNextTaskDistance();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTaskFrequency(int taskFrequency) {
|
public void setTaskFrequency(int taskFrequency) {
|
||||||
this.taskFrequency = taskFrequency;
|
this.taskFrequency = taskFrequency;
|
||||||
restore();
|
restore(this.trackStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMetricUnits(boolean metricUnits) {
|
public void setMetricUnits(boolean metricUnits) {
|
||||||
this.metricUnits = metricUnits;
|
this.metricUnits = metricUnits;
|
||||||
updateNextTaskDistance();
|
updateNextTaskDistance(this.trackStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNextTaskDistance() {
|
private void updateNextTaskDistance(TrackStatistics trackStatistics) {
|
||||||
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused() || periodicTask == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDistanceFrequency()) {
|
if (!isDistanceFrequency()) {
|
||||||
nextTaskDistance = Distance.of(Double.MAX_VALUE);
|
nextTotalDistance = Distance.of(Double.MAX_VALUE);
|
||||||
Log.d(TAG, "SplitManager: Distance splits disabled.");
|
Log.d(TAG, "SplitManager: Distance splits disabled.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -154,11 +126,11 @@ public class PeriodicTaskExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTaskDistance = calculateNextTaskDistance(trackStatistics);
|
nextTotalDistance = calculateNextTaskDistance(trackStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Distance calculateNextTaskDistance(TrackStatistics trackStatistics) {
|
public Distance calculateNextTaskDistance(@NonNull TrackStatistics trackStatistics) {
|
||||||
Distance distance = trackStatistics.getTotalDistance();
|
Distance distance = trackStatistics.getTotalDistance();
|
||||||
|
|
||||||
Distance announcementInterval = Distance.one(metricUnits).multipliedBy(Math.abs(taskFrequency));
|
Distance announcementInterval = Distance.one(metricUnits).multipliedBy(Math.abs(taskFrequency));
|
||||||
@@ -166,6 +138,14 @@ public class PeriodicTaskExecutor {
|
|||||||
return announcementInterval.multipliedBy(index + 1);
|
return announcementInterval.multipliedBy(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Duration calculateNextDuration(@NonNull TrackStatistics trackStatistics) {
|
||||||
|
if (!isTimeFrequency()) {
|
||||||
|
throw new RuntimeException("Using distance frequency as time frequency is impossible.");
|
||||||
|
}
|
||||||
|
Duration interval = Duration.ofMinutes(taskFrequency);
|
||||||
|
return interval.minus(Duration.ofMillis(trackStatistics.getTotalTime().toMillis() % interval.toMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isTimeFrequency() {
|
private boolean isTimeFrequency() {
|
||||||
return taskFrequency > 0;
|
return taskFrequency > 0;
|
||||||
}
|
}
|
||||||
@@ -173,12 +153,4 @@ public class PeriodicTaskExecutor {
|
|||||||
private boolean isDistanceFrequency() {
|
private boolean isDistanceFrequency() {
|
||||||
return taskFrequency < 0;
|
return taskFrequency < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getNextDuration() {
|
|
||||||
if (!isTimeFrequency()) {
|
|
||||||
throw new RuntimeException("Using distance frequency as time frequency is impossible.");
|
|
||||||
}
|
|
||||||
Duration interval = Duration.ofMinutes(taskFrequency);
|
|
||||||
return interval.toMillis() - (trackRecordingService.getTotalTime().toMillis() % interval.toMillis());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user