forked from upstream-mirrors/OpenTracks
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cab43d558 | |||
| 13f2a09652 | |||
| 7d4072c0d8 | |||
| 310b35713d | |||
| 7e6237de3a | |||
| 772dad4837 | |||
| 99126fa357 | |||
| b2c91d7592 | |||
| 3c5a1be16b |
+2
-2
@@ -51,8 +51,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 3981
|
||||
versionName "v3.17.0"
|
||||
versionCode 3990
|
||||
versionName "v3.17.2"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
v3.17.1: OpenTracks
|
||||
|
||||
|
||||
Bugfix:
|
||||
- Interval length in meters instead of kilometers (introduced in v3.17.0)
|
||||
- Elevation gain/loss not recorded (introduced in v3.17.0)
|
||||
- Announcements not working on Android 11
|
||||
@@ -0,0 +1,8 @@
|
||||
v3.17.2: OpenTracks
|
||||
|
||||
WARNING: The v3.17.0+ releases contain a memory leak.
|
||||
This issues is NOT FIXED by this release.
|
||||
It is recommended to not upgrade if you still use a release before v3.17.0
|
||||
|
||||
Bugfix:
|
||||
- Crash while using voice announcements
|
||||
@@ -44,7 +44,7 @@ public class ChartValueSeriesTest {
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
Integer.MIN_VALUE,
|
||||
Integer.MAX_VALUE,
|
||||
new int[]{100, 1000},
|
||||
new int[]{1, 100, 1000},
|
||||
R.string.description_altitude_metric,
|
||||
R.string.description_altitude_imperial,
|
||||
R.color.chart_altitude_fill,
|
||||
@@ -52,7 +52,7 @@ public class ChartValueSeriesTest {
|
||||
15,
|
||||
18) {
|
||||
@Override
|
||||
double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getAltitude();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,17 @@ public class ChartValueSeriesTest {
|
||||
assertFalse(series.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerySmallUpdates() {
|
||||
series.update(new ChartPoint(1f));
|
||||
series.update(new ChartPoint(2f));
|
||||
series.update(new ChartPoint(3f));
|
||||
series.updateDimension();
|
||||
assertEquals(1, series.getInterval());
|
||||
assertEquals(1, series.getMinMarkerValue());
|
||||
assertEquals(6, series.getMaxMarkerValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmallUpdates() {
|
||||
series.update(new ChartPoint(0));
|
||||
|
||||
@@ -39,6 +39,7 @@ import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Tests {@link ChartFragment}.
|
||||
@@ -83,9 +84,9 @@ public class ChartFragmentTest {
|
||||
ChartPoint point = chartFragment.createPendingPoint(trackPoint);
|
||||
|
||||
// then
|
||||
assertEquals(Float.NaN, point.getHeartRate(), 0.01);
|
||||
assertEquals(Float.NaN, point.getCadence(), 0.01);
|
||||
assertEquals(Float.NaN, point.getPower(), 0.01);
|
||||
assertNull(point.getHeartRate());
|
||||
assertNull(point.getCadence());
|
||||
assertNull(point.getPower());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -351,4 +351,10 @@ limitations under the License.
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.TTS_SERVICE" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
||||
@@ -14,11 +14,11 @@ public class ChartPoint {
|
||||
|
||||
//Y-axis
|
||||
private double altitude;
|
||||
private double speed;
|
||||
private double pace;
|
||||
private double heartRate = Double.NaN;
|
||||
private double cadence = Double.NaN;
|
||||
private double power = Double.NaN;
|
||||
private Double speed;
|
||||
private Double pace;
|
||||
private Double heartRate;
|
||||
private Double cadence;
|
||||
private Double power;
|
||||
|
||||
@VisibleForTesting
|
||||
ChartPoint(double altitude) {
|
||||
@@ -43,13 +43,13 @@ public class ChartPoint {
|
||||
pace = trackStatisticsUpdater.getSmoothedSpeed().toPace(metricUnits).toMillis() * UnitConversions.MS_TO_S * UnitConversions.S_TO_MIN;
|
||||
if (trackPoint != null) {
|
||||
if (trackPoint.hasHeartRate()) {
|
||||
heartRate = trackPoint.getHeartRate_bpm();
|
||||
heartRate = (double) trackPoint.getHeartRate_bpm();
|
||||
}
|
||||
if (trackPoint.hasCyclingCadence()) {
|
||||
cadence = trackPoint.getCyclingCadence_rpm();
|
||||
cadence = (double) trackPoint.getCyclingCadence_rpm();
|
||||
}
|
||||
if (trackPoint.hasPower()) {
|
||||
power = trackPoint.getPower();
|
||||
power = (double) trackPoint.getPower();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,39 +58,27 @@ public class ChartPoint {
|
||||
return timeOrDistance;
|
||||
}
|
||||
|
||||
public double getAltitude() {
|
||||
public Double getAltitude() {
|
||||
return altitude;
|
||||
}
|
||||
|
||||
public double getSpeed() {
|
||||
public Double getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public double getPace() {
|
||||
public Double getPace() {
|
||||
return pace;
|
||||
}
|
||||
|
||||
public boolean hasHeartRate() {
|
||||
return Double.isNaN(heartRate);
|
||||
}
|
||||
|
||||
public double getHeartRate() {
|
||||
public Double getHeartRate() {
|
||||
return heartRate;
|
||||
}
|
||||
|
||||
public boolean hasCadence() {
|
||||
return Double.isNaN(cadence);
|
||||
}
|
||||
|
||||
public double getCadence() {
|
||||
public Double getCadence() {
|
||||
return cadence;
|
||||
}
|
||||
|
||||
public boolean hasPower() {
|
||||
return Double.isNaN(power);
|
||||
}
|
||||
|
||||
public double getPower() {
|
||||
public Double getPower() {
|
||||
return power;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,10 +132,10 @@ abstract class ChartValueSeries {
|
||||
}
|
||||
}
|
||||
|
||||
abstract double extractDataFromChartPoint(@NonNull ChartPoint chartPoint);
|
||||
abstract Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint);
|
||||
|
||||
boolean isChartPointValid(@NonNull ChartPoint chartPoint) {
|
||||
return !Double.isNaN(extractDataFromChartPoint(chartPoint));
|
||||
return extractDataFromChartPoint(chartPoint) != null;
|
||||
}
|
||||
|
||||
protected abstract boolean drawIfChartPointHasNoData();
|
||||
|
||||
@@ -206,7 +206,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getAltitude();
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getSpeed();
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getPace();
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getHeartRate();
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getCadence();
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ public class ChartView extends View {
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getPower();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,13 @@ public class Distance {
|
||||
return of(distance_mile * UnitConversions.MI_TO_M);
|
||||
}
|
||||
|
||||
public static Distance ofKilometer(double distance_km) {
|
||||
return of(distance_km * UnitConversions.KM_TO_M);
|
||||
}
|
||||
|
||||
public static Distance one(boolean metricUnit) {
|
||||
if (metricUnit) {
|
||||
return Distance.of(1);
|
||||
return Distance.ofKilometer(1);
|
||||
} else {
|
||||
return Distance.ofMile(1);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
return serviceStatus.getRecordingTrackPaused();
|
||||
}
|
||||
|
||||
public Track.Id getRecordingTrackId() {
|
||||
return serviceStatus.getRecordingTrackId();
|
||||
}
|
||||
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
if (trackStatisticsUpdater == null) {
|
||||
return null;
|
||||
@@ -569,6 +573,12 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
serviceStatus.addListener(listener);
|
||||
}
|
||||
|
||||
//TODO Check that this is used everywhere, where addListener is called!
|
||||
//Otherwise, we keep objects in referenced and waste memory until this service instance is terminated.
|
||||
public void removeListener(@NonNull TrackRecordingServiceStatus.Listener listener) {
|
||||
serviceStatus.removeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a trackPoint if this trackPoint is different than lastValidTrackPoint.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@ public class TrackRecordingServiceStatus {
|
||||
|
||||
private final List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
public void addListener(@NonNull Listener listener) {
|
||||
void addListener(@NonNull Listener listener) {
|
||||
if (this.listeners.contains(listener)) {
|
||||
return;
|
||||
}
|
||||
@@ -28,6 +28,10 @@ public class TrackRecordingServiceStatus {
|
||||
listener.onTrackRecordingPaused(recordingTrackPaused);
|
||||
}
|
||||
|
||||
void removeListener(@NonNull Listener listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public boolean getRecordingTrackPaused() {
|
||||
return this.recordingTrackPaused;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AltitudeSumManager implements SensorEventListener {
|
||||
Log.w(TAG, "No pressure sensor available.");
|
||||
isConnected = false;
|
||||
} else {
|
||||
isConnected = sensorManager.registerListener(this, pressureSensor, (int) SAMPLING_RATE.toNanos());
|
||||
isConnected = sensorManager.registerListener(this, pressureSensor, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
}
|
||||
|
||||
lastAcceptedPressureValue_hPa = Float.NaN;
|
||||
|
||||
+12
-14
@@ -24,6 +24,7 @@ import android.speech.tts.UtteranceProgressListener;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Distance;
|
||||
@@ -32,7 +33,6 @@ import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceStatus;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.AnnouncementUtils;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
@@ -58,8 +58,6 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
|
||||
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
|
||||
private Track.Id recordingTrackId;
|
||||
|
||||
private final AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
|
||||
@Override
|
||||
public void onAudioFocusChange(int focusChange) {
|
||||
@@ -142,13 +140,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
|
||||
Log.e(TAG, "TrackRecordingService is null.");
|
||||
return;
|
||||
}
|
||||
trackRecordingService.addListener(new TrackRecordingServiceStatus.Listener() {
|
||||
@Override
|
||||
public void onTrackRecordingId(Track.Id trackId) {
|
||||
recordingTrackId = trackId;
|
||||
}
|
||||
});
|
||||
announce(trackRecordingService.getTrackStatistics());
|
||||
|
||||
announce(trackRecordingService.getRecordingTrackId(), trackRecordingService.getTrackStatistics());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +149,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
|
||||
*
|
||||
* @param trackStatistics the track statistics
|
||||
*/
|
||||
private void announce(TrackStatistics trackStatistics) {
|
||||
private void announce(Track.Id trackId, TrackStatistics trackStatistics) {
|
||||
if (trackStatistics == null) {
|
||||
Log.e(TAG, "TrackStatistics is null.");
|
||||
return;
|
||||
@@ -175,13 +168,18 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
|
||||
}
|
||||
}
|
||||
|
||||
if (audioManager.getMode() == AudioManager.MODE_IN_CALL || audioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
|
||||
if (Arrays.asList(AudioManager.MODE_IN_CALL, AudioManager.MODE_IN_COMMUNICATION)
|
||||
.contains(audioManager.getMode())) {
|
||||
Log.i(TAG, "Speech is not allowed at this time.");
|
||||
return;
|
||||
}
|
||||
|
||||
Track track = contentProviderUtils.getTrack(recordingTrackId);
|
||||
String category = track != null ? track.getCategory() : "";
|
||||
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();
|
||||
|
||||
//TODO Querying all TrackPoints all the time is inefficient; use TrackDataHub or something else.
|
||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||
|
||||
@@ -106,7 +106,7 @@ public class TrackStatisticsUpdater {
|
||||
*/
|
||||
public void addTrackPoint(TrackPoint trackPoint, Distance minGPSDistance) {
|
||||
internalAddTrackPoint(trackPoint, minGPSDistance);
|
||||
Log.d(TAG, this.toString());
|
||||
Log.v(TAG, this.toString());
|
||||
}
|
||||
|
||||
private void internalAddTrackPoint(TrackPoint trackPoint, Distance minGPSDistance) {
|
||||
|
||||
@@ -35,7 +35,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
}
|
||||
|
||||
intervalsLiveData = new MutableLiveData<>();
|
||||
distanceInterval = interval.getValue();
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
loadIntervalStatistics();
|
||||
}
|
||||
return intervalsLiveData;
|
||||
@@ -73,7 +73,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
interval = IntervalOption.OPTION_1;
|
||||
}
|
||||
|
||||
distanceInterval = interval.getValue();
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
loadIntervalStatistics();
|
||||
}
|
||||
}
|
||||
@@ -91,19 +91,21 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
OPTION_20(20),
|
||||
OPTION_50(50);
|
||||
|
||||
private final Distance value;
|
||||
private final int multiplier;
|
||||
|
||||
IntervalOption(int value) {
|
||||
this.value = Distance.of(value);
|
||||
IntervalOption(int multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
public Distance getValue() {
|
||||
return value;
|
||||
public Distance getDistance(boolean metricUnits) {
|
||||
return Distance
|
||||
.one(metricUnits)
|
||||
.multipliedBy(multiplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + (int) value.toM(); //TODO Somehow IntervalsFragment relies on a parsable Integer.
|
||||
return "" + multiplier; //TODO Somehow IntervalsFragment relies on a parsable Integer.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user