forked from upstream-mirrors/OpenTracks
+7
-6
@@ -24,6 +24,7 @@ import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
|
||||
@@ -42,7 +43,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
|
||||
private boolean previousLocationWasAccurate = true;
|
||||
|
||||
private Boolean metricUnits = null;
|
||||
private UnitSystem unitSystem = null;
|
||||
|
||||
TrackRecordingServiceNotificationManager(Context context) {
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||
@@ -85,7 +86,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
String formattedAccuracy = context.getString(R.string.value_none);
|
||||
|
||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||
.setMetricUnits(metricUnits)
|
||||
.setUnit(unitSystem)
|
||||
.build(context);
|
||||
if (trackPoint.hasHorizontalAccuracy()) {
|
||||
formattedAccuracy = formatter.formatDistance(trackPoint.getHorizontalAccuracy());
|
||||
@@ -97,7 +98,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
}
|
||||
|
||||
notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance())));
|
||||
String formattedSpeed = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed());
|
||||
String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed());
|
||||
notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed));
|
||||
notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy));
|
||||
updateNotification();
|
||||
@@ -149,8 +150,8 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
notificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
void setMetricUnits(boolean metricUnits) {
|
||||
this.metricUnits = metricUnits;
|
||||
void setUnitSystem(UnitSystem unitSystem) {
|
||||
this.unitSystem = unitSystem;
|
||||
}
|
||||
|
||||
private void updateNotification() {
|
||||
@@ -164,7 +165,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||
setMetricUnits(PreferencesUtils.isMetricUnits());
|
||||
setUnitSystem(PreferencesUtils.getUnitSystem());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||
@@ -165,12 +166,12 @@ public class VoiceAnnouncement {
|
||||
}
|
||||
|
||||
|
||||
boolean isMetricUnits = PreferencesUtils.isMetricUnits();
|
||||
UnitSystem unitSystem = PreferencesUtils.getUnitSystem();
|
||||
boolean isReportSpeed = PreferencesUtils.isReportSpeed(track.getCategory());
|
||||
|
||||
//TODO Do not load all trackpoints for every announcement
|
||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(unitSystem));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
||||
SensorStatistics sensorStatistics = null;
|
||||
@@ -178,7 +179,7 @@ public class VoiceAnnouncement {
|
||||
sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
|
||||
}
|
||||
|
||||
Spannable announcement = VoiceAnnouncementUtils.getAnnouncement(context, track.getTrackStatistics(), isMetricUnits, isReportSpeed, lastInterval, sensorStatistics);
|
||||
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");
|
||||
|
||||
+34
-12
@@ -16,6 +16,7 @@ import java.time.Duration;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||
@@ -25,15 +26,37 @@ class VoiceAnnouncementUtils {
|
||||
private VoiceAnnouncementUtils() {
|
||||
}
|
||||
|
||||
static Spannable getAnnouncement(Context context, TrackStatistics trackStatistics, boolean isMetricUnits, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
||||
static Spannable getAnnouncement(Context context, TrackStatistics trackStatistics, UnitSystem unitSystem, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
Distance distance = trackStatistics.getTotalDistance();
|
||||
Speed distancePerTime = trackStatistics.getAverageMovingSpeed();
|
||||
Speed currentDistancePerTime = currentInterval != null ? currentInterval.getSpeed() : null;
|
||||
int perUnitStringId = isMetricUnits ? R.string.voice_per_kilometer : R.string.voice_per_mile;
|
||||
|
||||
double distanceInUnit = distance.toKM_Miles(isMetricUnits);
|
||||
int distanceId = isMetricUnits ? R.plurals.voiceDistanceKilometers : R.plurals.voiceDistanceMiles;
|
||||
int perUnitStringId;
|
||||
int distanceId;
|
||||
int speedId;
|
||||
String unitDistanceTTS;
|
||||
String unitSpeedTTS;
|
||||
switch (unitSystem) {
|
||||
case METRIC:
|
||||
perUnitStringId = R.string.voice_per_kilometer;
|
||||
distanceId = R.plurals.voiceDistanceKilometers;
|
||||
speedId = R.plurals.voiceSpeedKilometersPerHour;
|
||||
unitDistanceTTS = "kilometer";
|
||||
unitSpeedTTS = "kilometer per hour";
|
||||
break;
|
||||
case IMPERIAL:
|
||||
perUnitStringId = R.string.voice_per_mile;
|
||||
distanceId = R.plurals.voiceDistanceMiles;
|
||||
speedId = R.plurals.voiceSpeedMilesPerHour;
|
||||
unitDistanceTTS = "mile";
|
||||
unitSpeedTTS = "mile per hour";
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
double distanceInUnit = distance.toKM_Miles(unitSystem);
|
||||
|
||||
builder.append(context.getString(R.string.total_distance));
|
||||
long distanceIntegerPart = (long) distanceInUnit;
|
||||
@@ -41,7 +64,7 @@ class VoiceAnnouncementUtils {
|
||||
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, isMetricUnits ? "kilometer" : "mile");
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(distanceId, getQuantityCount(distanceInUnit), distanceInUnit), distanceIntegerPart, distanceFractionalPart, unitDistanceTTS);
|
||||
// Punctuation helps introduce natural pauses in TTS
|
||||
builder.append(".");
|
||||
if (distance.isZero()) {
|
||||
@@ -56,19 +79,18 @@ class VoiceAnnouncementUtils {
|
||||
}
|
||||
|
||||
if (isReportSpeed) {
|
||||
int speedId = isMetricUnits ? R.plurals.voiceSpeedKilometersPerHour : R.plurals.voiceSpeedMilesPerHour;
|
||||
double speedInUnit = distancePerTime.to(isMetricUnits);
|
||||
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, isMetricUnits ? "kilometer per hour" : "mile per hour");
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(speedInUnit), speedInUnit), speedIntegerPart, speedFractionalPart, unitSpeedTTS);
|
||||
builder.append(".");
|
||||
|
||||
if (currentDistancePerTime != null) {
|
||||
double currentDistancePerTimeInUnit = currentDistancePerTime.to(isMetricUnits);
|
||||
double currentDistancePerTimeInUnit = currentDistancePerTime.to(unitSystem);
|
||||
|
||||
if (currentDistancePerTimeInUnit > 0) {
|
||||
|
||||
@@ -77,12 +99,12 @@ class VoiceAnnouncementUtils {
|
||||
long currentDistanceIntegerPart = (long) currentDistancePerTimeInUnit;
|
||||
// Extract the decimal part
|
||||
String currentDistanceFractionalPart = String.format("%.1f", (currentDistancePerTimeInUnit - currentDistanceIntegerPart)).substring(2);
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(currentDistancePerTimeInUnit), currentDistancePerTimeInUnit), currentDistanceIntegerPart, currentDistanceFractionalPart, isMetricUnits ? "kilometer per hour" : "mile per hour");
|
||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(currentDistancePerTimeInUnit), currentDistancePerTimeInUnit), currentDistanceIntegerPart, currentDistanceFractionalPart, unitSpeedTTS);
|
||||
builder.append(".");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Duration time = distancePerTime.toPace(isMetricUnits);
|
||||
Duration time = distancePerTime.toPace(unitSystem);
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.pace));
|
||||
appendDuration(context, builder, time);
|
||||
@@ -90,7 +112,7 @@ class VoiceAnnouncementUtils {
|
||||
.append(context.getString(perUnitStringId))
|
||||
.append(".");
|
||||
|
||||
Duration currentTime = currentDistancePerTime != null ? currentDistancePerTime.toPace(isMetricUnits) : Duration.ofMillis(0);
|
||||
Duration currentTime = currentDistancePerTime != null ? currentDistancePerTime.toPace(unitSystem) : Duration.ofMillis(0);
|
||||
if (!currentTime.isZero()) {
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.lap_time));
|
||||
|
||||
Reference in New Issue
Block a user