forked from upstream-mirrors/OpenTracks
Voice announcements: added settings for what to announce
This commit is contained in:
committed by
Dennis Guse
parent
14b705b43e
commit
00351136f2
@@ -181,8 +181,10 @@ public class VoiceAnnouncement {
|
||||
|
||||
Spannable announcement = VoiceAnnouncementUtils.getAnnouncement(context, track.getTrackStatistics(), unitSystem, isReportSpeed, lastInterval, sensorStatistics);
|
||||
|
||||
// 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");
|
||||
if (announcement.length() > 0) {
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
||||
+53
-45
@@ -1,7 +1,12 @@
|
||||
package de.dennisguse.opentracks.services.announcement;
|
||||
|
||||
import static android.text.Spanned.SPAN_INCLUSIVE_EXCLUSIVE;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceHeartRate;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceAverageHeartRate;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceAverageSpeedPace;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceLapHeartRate;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceLapSpeedPace;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceTotalDistance;
|
||||
import static de.dennisguse.opentracks.settings.PreferencesUtils.shouldVoiceAnnounceTotalTime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spannable;
|
||||
@@ -58,38 +63,42 @@ class VoiceAnnouncementUtils {
|
||||
|
||||
double distanceInUnit = distance.toKM_Miles(unitSystem);
|
||||
|
||||
builder.append(context.getString(R.string.total_distance));
|
||||
long distanceIntegerPart = (long) distanceInUnit;
|
||||
// Extract the decimal part
|
||||
String distanceFractionalPart = String.format("%.2f", (distanceInUnit - distanceIntegerPart)).substring(2);
|
||||
// Units should always be english singular for TTS.
|
||||
// See https://developer.android.com/reference/android/text/style/TtsSpan?hl=en#TYPE_MEASURE
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(distanceId, getQuantityCount(distanceInUnit), distanceInUnit), distanceIntegerPart, distanceFractionalPart, unitDistanceTTS);
|
||||
// Punctuation helps introduce natural pauses in TTS
|
||||
builder.append(".");
|
||||
if (shouldVoiceAnnounceTotalDistance()) {
|
||||
builder.append(context.getString(R.string.total_distance));
|
||||
long distanceIntegerPart = (long) distanceInUnit;
|
||||
// Extract the decimal part
|
||||
String distanceFractionalPart = String.format("%.2f", (distanceInUnit - distanceIntegerPart)).substring(2);
|
||||
// Units should always be english singular for TTS.
|
||||
// See https://developer.android.com/reference/android/text/style/TtsSpan?hl=en#TYPE_MEASURE
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(distanceId, getQuantityCount(distanceInUnit), distanceInUnit), distanceIntegerPart, distanceFractionalPart, unitDistanceTTS);
|
||||
// Punctuation helps introduce natural pauses in TTS
|
||||
builder.append(".");
|
||||
}
|
||||
if (distance.isZero()) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
// Announce time
|
||||
Duration movingTime = trackStatistics.getMovingTime();
|
||||
if (!movingTime.isZero()) {
|
||||
if (shouldVoiceAnnounceTotalTime() && !movingTime.isZero()) {
|
||||
appendDuration(context, builder, movingTime);
|
||||
builder.append(".");
|
||||
}
|
||||
|
||||
if (isReportSpeed) {
|
||||
double speedInUnit = distancePerTime.to(unitSystem);
|
||||
if (shouldVoiceAnnounceAverageSpeedPace()) {
|
||||
double speedInUnit = distancePerTime.to(unitSystem);
|
||||
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.speed));
|
||||
long speedIntegerPart = (long) speedInUnit;
|
||||
// Extract the decimal part
|
||||
String speedFractionalPart = String.format("%.1f", (speedInUnit - speedIntegerPart)).substring(2);
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(speedInUnit), speedInUnit), speedIntegerPart, speedFractionalPart, unitSpeedTTS);
|
||||
builder.append(".");
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.speed));
|
||||
long speedIntegerPart = (long) speedInUnit;
|
||||
// Extract the decimal part
|
||||
String speedFractionalPart = String.format("%.1f", (speedInUnit - speedIntegerPart)).substring(2);
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(speedInUnit), speedInUnit), speedIntegerPart, speedFractionalPart, unitSpeedTTS);
|
||||
builder.append(".");
|
||||
}
|
||||
|
||||
if (currentDistancePerTime != null) {
|
||||
if (shouldVoiceAnnounceLapSpeedPace() && currentDistancePerTime != null) {
|
||||
double currentDistancePerTimeInUnit = currentDistancePerTime.to(unitSystem);
|
||||
|
||||
if (currentDistancePerTimeInUnit > 0) {
|
||||
@@ -104,16 +113,18 @@ class VoiceAnnouncementUtils {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Duration time = distancePerTime.toPace(unitSystem);
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.pace));
|
||||
appendDuration(context, builder, time);
|
||||
builder.append(" ")
|
||||
.append(context.getString(perUnitStringId))
|
||||
.append(".");
|
||||
if (shouldVoiceAnnounceAverageSpeedPace()) {
|
||||
Duration time = distancePerTime.toPace(unitSystem);
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.pace));
|
||||
appendDuration(context, builder, time);
|
||||
builder.append(" ")
|
||||
.append(context.getString(perUnitStringId))
|
||||
.append(".");
|
||||
}
|
||||
|
||||
Duration currentTime = currentDistancePerTime != null ? currentDistancePerTime.toPace(unitSystem) : Duration.ofMillis(0);
|
||||
if (!currentTime.isZero()) {
|
||||
if (shouldVoiceAnnounceLapSpeedPace() && currentDistancePerTime != null) {
|
||||
Duration currentTime = currentDistancePerTime.toPace(unitSystem);
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.lap_time));
|
||||
appendDuration(context, builder, currentTime);
|
||||
@@ -123,24 +134,21 @@ class VoiceAnnouncementUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldVoiceAnnounceHeartRate()) {
|
||||
if (sensorStatistics != null && sensorStatistics.hasHeartRate()) {
|
||||
int averageHeartRate = Math.round(sensorStatistics.getAvgHeartRate().getBPM());
|
||||
if (shouldVoiceAnnounceAverageHeartRate() && sensorStatistics != null && sensorStatistics.hasHeartRate()) {
|
||||
int averageHeartRate = Math.round(sensorStatistics.getAvgHeartRate().getBPM());
|
||||
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.average_heart_rate));
|
||||
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, averageHeartRate), averageHeartRate);
|
||||
builder.append(".");
|
||||
}
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.average_heart_rate));
|
||||
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, averageHeartRate), averageHeartRate);
|
||||
builder.append(".");
|
||||
}
|
||||
if (shouldVoiceAnnounceLapHeartRate() && currentInterval != null && currentInterval.hasAverageHeartRate()) {
|
||||
int currentHeartRate = Math.round(currentInterval.getAverageHeartRate().getBPM());
|
||||
|
||||
if (currentInterval != null && currentInterval.hasAverageHeartRate()) {
|
||||
int currentHeartRate = Math.round(currentInterval.getAverageHeartRate().getBPM());
|
||||
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.current_heart_rate));
|
||||
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, currentHeartRate), currentHeartRate);
|
||||
builder.append(".");
|
||||
}
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.current_heart_rate));
|
||||
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, currentHeartRate), currentHeartRate);
|
||||
builder.append(".");
|
||||
}
|
||||
|
||||
return builder;
|
||||
|
||||
@@ -343,13 +343,58 @@ public class PreferencesUtils {
|
||||
return getFloat(R.string.voice_speed_rate_key, DEFAULT);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceHeartRate() {
|
||||
return getBoolean(R.string.voice_announce_heart_rate_key, false);
|
||||
public static boolean shouldVoiceAnnounceTotalDistance() {
|
||||
return getBoolean(R.string.voice_announce_total_distance_key, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceHeartRate(boolean value) {
|
||||
setBoolean(R.string.voice_announce_heart_rate_key, value);
|
||||
public static void setVoiceAnnounceTotalDistance(boolean value) {
|
||||
setBoolean(R.string.voice_announce_total_distance_key, value);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceTotalTime() {
|
||||
return getBoolean(R.string.voice_announce_total_time_key, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceTotalTime(boolean value) {
|
||||
setBoolean(R.string.voice_announce_total_time_key, value);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceAverageSpeedPace() {
|
||||
return getBoolean(R.string.voice_announce_average_speed_pace_key, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceAverageSpeedPace(boolean value) {
|
||||
setBoolean(R.string.voice_announce_average_speed_pace_key, value);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceLapSpeedPace() {
|
||||
return getBoolean(R.string.voice_announce_lap_speed_pace_key, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceLapSpeedPace(boolean value) {
|
||||
setBoolean(R.string.voice_announce_lap_speed_pace_key, value);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceLapHeartRate() {
|
||||
return getBoolean(R.string.voice_announce_lap_heart_rate_key, false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceLapHeartRate(boolean value) {
|
||||
setBoolean(R.string.voice_announce_lap_heart_rate_key, value);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnounceAverageHeartRate() {
|
||||
return getBoolean(R.string.voice_announce_average_heart_rate_key, false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setVoiceAnnounceAverageHeartRate(boolean value) {
|
||||
setBoolean(R.string.voice_announce_average_heart_rate_key, value);
|
||||
}
|
||||
|
||||
public static Distance getRecordingDistanceInterval() {
|
||||
|
||||
Reference in New Issue
Block a user