Announcements: can be triggered by time and distance (instead of either).

Fixes #921.
This commit is contained in:
Dennis Guse
2021-08-29 20:22:31 +02:00
parent 9cb3d8c1bb
commit 8f2d1722ad
65 changed files with 169 additions and 205 deletions
@@ -73,7 +73,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null);
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
// The following variables are set in onCreate:
// The following variables are setFrequency in onCreate:
private VoiceAnnouncementManager voiceAnnouncementManager;
private TrackRecordingServiceNotificationManager notificationManager;
@@ -104,20 +104,21 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
Context context = TrackRecordingService.this;
if (PreferencesUtils.isKey(context, R.string.stats_units_key, key)) {
boolean metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, context);
voiceAnnouncementManager.setMetricUnits(metricUnits);
notificationManager.setMetricUnits(metricUnits);
}
if (PreferencesUtils.isKey(context, R.string.voice_frequency_key, key)) {
voiceAnnouncementManager.setTaskFrequency(PreferencesUtils.getVoiceFrequency(sharedPreferences, context));
if (PreferencesUtils.isKey(context, R.string.voice_announcement_frequency_key, key)) {
voiceAnnouncementManager.setFrequency(PreferencesUtils.getVoiceAnnouncementFrequency(sharedPreferences, context));
}
if (PreferencesUtils.isKey(context, new int[]{R.string.voice_announcement_distance_key, R.string.stats_units_key}, key)) {
voiceAnnouncementManager.setFrequency(PreferencesUtils.getVoiceAnnouncementDistance(sharedPreferences, context));
}
trackPointCreator.onSharedPreferenceChanged(sharedPreferences, key);
trackRecordingManager.onSharedPreferenceChanged(sharedPreferences, key);
}
};
// The following variables are set when recording:
// The following variables are setFrequency when recording:
private WakeLock wakeLock;
private final Binder binder = new Binder();
@@ -40,48 +40,35 @@ public class VoiceAnnouncementManager {
private final TrackRecordingService trackRecordingService;
private final int TASK_FREQUENCY_OFF;
/**
* The task frequency.
* A positive value is a time frequency (minutes).
* A negative value is a distance frequency (km or mi).
* A zero value is to turn off periodic task.
*/
private int taskFrequency;
private VoiceAnnouncement voiceAnnouncement;
private boolean metricUnits;
private TrackStatistics trackStatistics;
private static final Distance DISTANCE_OFF = Distance.of(Double.MAX_VALUE);
private Distance distanceFrequency = DISTANCE_OFF;
@NonNull
private Distance nextTotalDistance = DISTANCE_OFF;
private static final Duration TOTALTIME_OFF = Duration.ofMillis(Long.MAX_VALUE);
private Duration totalTimeFrequency = TOTALTIME_OFF;
@NonNull
private Duration nextTotalTime = TOTALTIME_OFF;
public VoiceAnnouncementManager(@NonNull TrackRecordingService trackRecordingService) {
this.trackRecordingService = trackRecordingService;
TASK_FREQUENCY_OFF = Integer.parseInt(trackRecordingService.getString(R.string.frequency_off));
taskFrequency = TASK_FREQUENCY_OFF;
}
public void restore(@Nullable TrackStatistics trackStatistics) {
if (taskFrequency == TASK_FREQUENCY_OFF) {
Log.d(TAG, "Task frequency is off.");
return;
}
voiceAnnouncement = new VoiceAnnouncement(trackRecordingService);
voiceAnnouncement.start();
if (isTimeFrequency()) {
nextTotalTime = trackStatistics != null ? calculateNextDuration(trackStatistics) : TOTALTIME_OFF;
} else {
// For distance periodic task
updateNextTaskDistance(trackStatistics);
this.trackStatistics = trackStatistics;
if (!totalTimeFrequency.isZero()) {
nextTotalTime = calculateNextDuration();
}
if (!distanceFrequency.isZero()) {
nextTotalDistance = calculateNextTaskDistance();
}
}
@@ -90,14 +77,15 @@ public class VoiceAnnouncementManager {
Log.e(TAG, "Cannot update when in status shutdown.");
return;
}
boolean announce = false;
this.trackStatistics = track.getTrackStatistics();
if (trackStatistics.getTotalDistance().greaterThan(nextTotalDistance)) {
updateNextTaskDistance(trackStatistics);
nextTotalDistance = calculateNextTaskDistance();
announce = true;
}
if (!trackStatistics.getTotalTime().minus(nextTotalTime).isNegative()) {
nextTotalTime = calculateNextDuration(trackStatistics);
nextTotalTime = calculateNextDuration();
announce = true;
}
@@ -113,59 +101,48 @@ public class VoiceAnnouncementManager {
}
}
public void setTaskFrequency(int taskFrequency) {
this.taskFrequency = taskFrequency;
public void setFrequency(Duration frequency) {
this.totalTimeFrequency = frequency;
restore(this.trackStatistics);
}
public void setMetricUnits(boolean metricUnits) {
this.metricUnits = metricUnits;
updateNextTaskDistance(this.trackStatistics);
}
private void updateNextTaskDistance(TrackStatistics trackStatistics) {
if (!isDistanceFrequency()) {
nextTotalDistance = DISTANCE_OFF;
Log.d(TAG, "SplitManager: Distance splits disabled.");
return;
}
if (trackStatistics == null) {
return;
}
nextTotalDistance = calculateNextTaskDistance(trackStatistics);
public void setFrequency(Distance frequency) {
this.distanceFrequency = frequency;
restore(this.trackStatistics);
}
@VisibleForTesting
public Distance calculateNextTaskDistance(@NonNull TrackStatistics trackStatistics) {
public Distance calculateNextTaskDistance() {
if (trackStatistics == null) {
return DISTANCE_OFF;
}
Distance distance = trackStatistics.getTotalDistance();
Distance announcementInterval = Distance.one(metricUnits).multipliedBy(Math.abs(taskFrequency));
int index = (int) (distance.dividedBy(announcementInterval));
return announcementInterval.multipliedBy(index + 1);
int index = (int) (distance.dividedBy(distanceFrequency));
return distanceFrequency.multipliedBy(index + 1);
}
private Duration calculateNextDuration(@Nullable TrackStatistics trackStatistics) {
private Duration calculateNextDuration() {
if (trackStatistics == null) {
return null;
return TOTALTIME_OFF;
}
if (!isTimeFrequency()) {
throw new RuntimeException("Using distance frequency as time frequency is impossible.");
}
Duration totalTime = trackStatistics.getTotalTime();
Duration interval = Duration.ofMinutes(taskFrequency);
Duration intervalMod = Duration.ofMillis(trackStatistics.getTotalTime().toMillis() % interval.toMillis());
Duration intervalMod = Duration.ofMillis(trackStatistics.getTotalTime().toMillis() % totalTimeFrequency.toMillis());
return totalTime.plus(interval.minus(intervalMod));
return totalTime.plus(totalTimeFrequency.minus(intervalMod));
}
private boolean isTimeFrequency() {
return taskFrequency > 0;
@VisibleForTesting
@NonNull
public Duration getNextTotalTime() {
return nextTotalTime;
}
private boolean isDistanceFrequency() {
return taskFrequency < 0;
@VisibleForTesting
@NonNull
public Distance getNextTotalDistance() {
return nextTotalDistance;
}
}