Compare commits

...

6 Commits

Author SHA1 Message Date
Dennis Guse 6656c9ab92 Release: v4.19.3 2025-05-27 22:31:14 +02:00
Peter Storch af6baeab9f fix #2104 csv export altitude above 1000m 2025-05-27 22:29:57 +02:00
dependabot[bot] 9b4d3a4718 Bump org.mockito:mockito-android from 5.17.0 to 5.18.0
Bumps [org.mockito:mockito-android](https://github.com/mockito/mockito) from 5.17.0 to 5.18.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.17.0...v5.18.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-android
  dependency-version: 5.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-21 06:19:44 +02:00
Morag S. 942b29aa25 Update README.md
Added example command, and some minor copyedit
2025-05-18 11:22:27 +02:00
dependabot[bot] 18e18353e7 Bump androidx.documentfile:documentfile from 1.0.1 to 1.1.0
Bumps androidx.documentfile:documentfile from 1.0.1 to 1.1.0.

---
updated-dependencies:
- dependency-name: androidx.documentfile:documentfile
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-08 08:42:31 +02:00
dependabot[bot] 8c8fe9f22d Bump com.android.tools.build:gradle from 8.9.2 to 8.10.0
Bumps com.android.tools.build:gradle from 8.9.2 to 8.10.0.

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-07 06:21:29 +02:00
6 changed files with 95 additions and 60 deletions
+12 -4
View File
@@ -100,8 +100,8 @@ __Only required permissions:__
### Public API
OpenTracks includes an API for starting/stopping recording by another installed application (e.g., [Automate](https://llamalab.com/automate/), [Tasker](https://tasker.joaoapps.com), or [Easer](https://github.com/renyuneyun/Easer)).
The API can be invoked by sending an explicit Intent to start an activity.
OpenTracks includes an API for starting/stopping recording by another installed application (e.g., [Automate](https://llamalab.com/automate/), [Tasker](https://tasker.joaoapps.com), or [Easer](https://github.com/renyuneyun/Easer)).
The API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings. Once enabled, the API can be invoked by sending an explicit Intent to start an activity.
`Package` (depends on the variant installed):
* F-Droid: `de.dennisguse.opentracks`
@@ -121,9 +121,17 @@ The API can be invoked by sending an explicit Intent to start an activity.
* **Stop a recording:** `de.dennisguse.opentracks.publicapi.StopRecording`
* **Create a marker:** `de.dennisguse.opentracks.publicapi.CreateMarker`
For testing via adb: `adb shell am start -e someParameter someValue -n "package/class"`
For testing the API using adb, the general command syntax is:
The Public API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings.
```shell
adb shell am start -e someParameter someValue -n "package/class"
```
Depending on the package and class, a complete command could look something like this:
```shell
adb shell am start -n "de.dennisguse.opentracks.playstore/de.dennisguse.opentracks.publicapi.StartRecording"
```
## File formats compatibility with open-source software
| | [GPX 1.1](https://www.topografix.com/GPX/1/1/) | [KML 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html) | [KMZ 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html) |
+5 -5
View File
@@ -6,7 +6,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.2'
classpath 'com.android.tools.build:gradle:8.10.0'
}
}
@@ -46,8 +46,8 @@ android {
defaultConfig {
applicationId 'de.dennisguse.opentracks'
versionCode 6124
versionName "v4.19.2"
versionCode 6130
versionName "v4.19.3"
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
@@ -144,7 +144,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.documentfile:documentfile:1.1.0'
implementation 'androidx.gridlayout:gridlayout:1.1.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
@@ -158,7 +158,7 @@ dependencies {
androidTestImplementation 'androidx.test:rules:1.6.1'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'org.mockito:mockito-android:5.17.0'
androidTestImplementation 'org.mockito:mockito-android:5.18.0'
androidTestUtil 'androidx.test:orchestrator:1.5.1'
}
@@ -0,0 +1,5 @@
v4.19.3: OpenTracks
Bugfix:
- Fix CSV export for altitude (was cut at 1000m)
@@ -18,6 +18,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.GrantPermissionRule;
import androidx.test.rule.ServiceTestRule;
import org.junit.After;
@@ -45,6 +46,7 @@ import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TestUtil;
import de.dennisguse.opentracks.TimezoneRule;
import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.data.ContentProviderUtils;
@@ -87,6 +89,9 @@ public class ExportImportTest {
@Rule
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
@Rule
public GrantPermissionRule mGrantPermissionRule = TestUtil.createGrantPermissionRule();
//For csv_export_only() as we the timezone is hardcoded in the expectation.
@Rule
public TimezoneRule timezoneRule = new TimezoneRule(TimeZone.getTimeZone("Europe/Berlin"));
@@ -144,7 +149,7 @@ public class ExportImportTest {
Distance sensorDistance = Distance.of(10); // recording distance interval
sendLocation(trackPointCreator, "2020-02-02T02:02:03Z", 3, 14, 10, 13, 15, 10, 1f);
sendLocation(trackPointCreator, "2020-02-02T02:02:03Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 1f);
contentProviderUtils.insertMarker(new Marker(trackId, service.getLastStoredTrackPointWithLocation(), "Marker 1", "Marker 1 desc", "Marker 1 category", null, null));
// A sensor-only TrackPoint
@@ -155,11 +160,10 @@ public class ExportImportTest {
mockSensorData(trackPointCreator, 15f, null, 67f, 3f, 50f, null);
trackPointCreator.setClock("2020-02-02T02:02:15Z");
mockSensorData(trackPointCreator, null, null, 68f, 3f, 50f, null);
trackPointCreator.setClock("2020-02-02T02:02:16Z");
mockSensorData(trackPointCreator, 5f, Distance.of(2), 69f, 3f, 50f, null); // Distance will be added to next TrackPoint
sendLocation(trackPointCreator, "2020-02-02T02:02:17Z", 3, 14.001, 10, 13, 15, 10, 0f);
sendLocation(trackPointCreator, "2020-02-02T02:02:17Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 0f);
contentProviderUtils.insertMarker(new Marker(trackId, service.getLastStoredTrackPointWithLocation(), "Marker 2", "Marker 2 desc", "Marker 2 category", null, null));
trackPointCreator.setClock("2020-02-02T02:02:18Z");
@@ -169,14 +173,14 @@ public class ExportImportTest {
trackPointCreator.setClock("2020-02-02T02:03:20Z");
service.resumeTrack(trackId);
sendLocation(trackPointCreator, "2020-02-02T02:03:21Z", 3, 14.002, 10, 13, 15, 10, 0f);
sendLocation(trackPointCreator, "2020-02-02T02:03:21Z", 3.1234567, 14.0024567, 10, 13, 15, 999.123, 0f);
sendLocation(trackPointCreator, "2020-02-02T02:03:22Z", 3, 16, 10, 13, 15, 10, 0f);
sendLocation(trackPointCreator, "2020-02-02T02:03:22Z", 3.1234567, 16, 10, 13, 15, 999.123, 0f);
trackPointCreator.setClock("2020-02-02T02:03:30Z");
service.getTrackRecordingManager().onIdle();
sendLocation(trackPointCreator, "2020-02-02T02:03:50Z", 3, 16.001, 10, 27, 15, 10, 0f);
sendLocation(trackPointCreator, "2020-02-02T02:03:50Z", 3.1234567, 16.001, 10, 27, 15, 999.123, 0f);
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator);
trackPointCreator.setClock("2020-02-02T02:04:00Z");
@@ -209,16 +213,16 @@ public class ExportImportTest {
assertEquals(Duration.ofSeconds(26), trackStatistics.getMovingTime()); //TODO Likely too low
// Distance
assertEquals(222125.53125, trackStatistics.getTotalDistance().toM(), 0.01); //TODO Too low
assertEquals(222049.34375, trackStatistics.getTotalDistance().toM(), 0.01); //TODO Too low
// Speed
assertEquals(8543.29, trackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(3966.52, trackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(8543.28, trackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
assertEquals(8540.359, trackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(3965.166, trackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(8540.359, trackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
// Altitude
assertEquals(10, trackStatistics.getMinAltitude(), 0.01);
assertEquals(10, trackStatistics.getMaxAltitude(), 0.01);
assertEquals(999.122, trackStatistics.getMinAltitude(), 0.01);
assertEquals(1020.25, trackStatistics.getMaxAltitude(), 0.01);
assertEquals(2, trackStatistics.getTotalAltitudeGain(), 0.01);
assertEquals(2, trackStatistics.getTotalAltitudeLoss(), 0.01);
@@ -229,8 +233,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:02:03Z"),
3d, 14d, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.001456, Distance.of(10),
Altitude.WGS84.of(1020.25), null,
null,
Speed.of(15)))
.setAltitudeLoss(1f)
@@ -251,8 +255,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:02:17Z"),
3d, 14.001, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.001456, Distance.of(10),
Altitude.WGS84.of(1020.25), null,
null,
Speed.of(5)))
.setSensorDistance(Distance.of(2))
@@ -266,16 +270,16 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:03:21Z"),
3d, 14.002d, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.002456, Distance.of(10),
Altitude.WGS84.of(999.1229858398438), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
.setAltitudeGain(0f),
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(Instant.parse("2020-02-02T02:03:22Z"),
3d, 16d, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 16d, Distance.of(10),
Altitude.WGS84.of(999.1229858398438), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
@@ -286,8 +290,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:03:50Z"),
3d, 16.001, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 16.001, Distance.of(10),
Altitude.WGS84.of(999.1229858398438), null,
null, Speed.of(15)))
.setAltitudeLoss(0f)
.setAltitudeGain(0f),
@@ -334,7 +338,26 @@ public class ExportImportTest {
// Time
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset());
assertEquals(track.getTrackStatistics(), importedTrackStatistics);
assertEquals(Instant.parse("2020-02-02T02:02:02Z"), importedTrackStatistics.getStartTime());
assertEquals(Instant.parse("2020-02-02T02:04:00Z"), importedTrackStatistics.getStopTime());
assertEquals(Duration.ofSeconds(56), importedTrackStatistics.getTotalTime());
assertEquals(Duration.ofSeconds(26), importedTrackStatistics.getMovingTime());
// Distance
assertEquals(222049.421, importedTrackStatistics.getTotalDistance().toM(), 0.01);
// Speed
assertEquals(8540.362, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(3965.168, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(8540.362, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
// Altitude
assertEquals(999.122, importedTrackStatistics.getMinAltitude(), 0.01);
assertEquals(1020.25, importedTrackStatistics.getMaxAltitude(), 0.01);
assertEquals(2, importedTrackStatistics.getTotalAltitudeGain(), 0.01);
assertEquals(2, importedTrackStatistics.getTotalAltitudeLoss(), 0.01);
// 4. markers
assertMarkers();
@@ -406,8 +429,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:02:03Z"),
3d, 14d, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.001456d, Distance.of(10),
Altitude.WGS84.of(1020.2), null,
null,
Speed.of(15)))
.setAltitudeLoss(1f)
@@ -415,8 +438,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:02:17Z"),
3d, 14.001, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.001456, Distance.of(10),
Altitude.WGS84.of(1020.2), null,
null,
Speed.of(5)))
.setAltitudeLoss(1f)
@@ -428,8 +451,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:03:21Z"),
3d, 14.002, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 14.002456, Distance.of(10),
Altitude.WGS84.of(999.0999755859375), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
@@ -437,8 +460,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:03:22Z"),
3d, 16d, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 16d, Distance.of(10),
Altitude.WGS84.of(999.0999755859375), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
@@ -446,8 +469,8 @@ public class ExportImportTest {
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:03:50Z"),
3d, 16.001, Distance.of(10),
Altitude.WGS84.of(10), null,
3.123456, 16.001, Distance.of(10),
Altitude.WGS84.of(999.0999755859375), null,
null,
Speed.of(10)))
.setAltitudeLoss(0f)
@@ -467,16 +490,16 @@ public class ExportImportTest {
assertEquals(Duration.ofSeconds(107), importedTrackStatistics.getMovingTime());
// Distance
assertEquals(222347.85, importedTrackStatistics.getTotalDistance().toM(), 0.01);
assertEquals(222271.734, importedTrackStatistics.getTotalDistance().toM(), 0.01);
// Speed
assertEquals(2078.01, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(2078.01, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(2078.01, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
assertEquals(2077.305, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(2077.305, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(2077.305, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
// Altitude
assertEquals(10, importedTrackStatistics.getMinAltitude(), 0.01);
assertEquals(10, importedTrackStatistics.getMaxAltitude(), 0.01);
assertEquals(999.099, importedTrackStatistics.getMinAltitude(), 0.01);
assertEquals(1020.2, importedTrackStatistics.getMaxAltitude(), 0.01);
assertEquals(2, importedTrackStatistics.getTotalAltitudeGain(), 0.01);
assertEquals(2, importedTrackStatistics.getTotalAltitudeLoss(), 0.01);
@@ -614,7 +637,7 @@ public class ExportImportTest {
}
}
private void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, float altitude, Float altitudeGain) {
private void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
Location location = new Location("mock");
location.setLatitude(latitude);
location.setLongitude(longitude);
+5 -5
View File
@@ -1,13 +1,13 @@
#time,trackpoint_type,latitude,longitude,altitude,accuracy_horizontal,accuracy_vertical,speed,altitude_gain,altitude_loss,sensor_distance,heartrate,cadence,power
"2020-02-02T03:02:02+01:00","SEGMENT_START_MANUAL",,,,,,,,,,,,
"2020-02-02T03:02:03+01:00","TRACKPOINT",3,14,10,10,,54,1,1,,,,
"2020-02-02T03:02:03+01:00","TRACKPOINT",3.123456,14.001456,1020.2,10,,54,1,1,,,,
"2020-02-02T03:02:04+01:00","TRACKPOINT",,,,,,54,1,1,10,66,3,50
"2020-02-02T03:02:15+01:00","TRACKPOINT",,,,,,,,,,68,3,50
"2020-02-02T03:02:17+01:00","TRACKPOINT",3,14.001,10,10,,18,0,0,2,69,3,50
"2020-02-02T03:02:17+01:00","TRACKPOINT",3.123456,14.001456,1020.2,10,,18,0,0,2,69,3,50
"2020-02-02T03:02:18+01:00","SEGMENT_END_MANUAL",,,,,,,,,,,,
"2020-02-02T03:03:20+01:00","SEGMENT_START_MANUAL",,,,,,,,,,,,
"2020-02-02T03:03:21+01:00","TRACKPOINT",3,14.002,10,10,,54,0,0,,,,
"2020-02-02T03:03:22+01:00","SEGMENT_START_AUTOMATIC",3,16,10,10,,54,0,0,,,,
"2020-02-02T03:03:21+01:00","TRACKPOINT",3.123456,14.002456,999.1,10,,54,0,0,,,,
"2020-02-02T03:03:22+01:00","SEGMENT_START_AUTOMATIC",3.123456,16,999.1,10,,54,0,0,,,,
"2020-02-02T03:03:30+01:00","IDLE",,,,,,,0,0,,,,
"2020-02-02T03:03:50+01:00","TRACKPOINT",3,16.001,10,10,,54,0,0,,,,
"2020-02-02T03:03:50+01:00","TRACKPOINT",3.123456,16.001,999.1,10,,54,0,0,,,,
"2020-02-02T03:04:00+01:00","SEGMENT_END_MANUAL",,,,,,,,,,,,
1 #time trackpoint_type latitude longitude altitude accuracy_horizontal accuracy_vertical speed altitude_gain altitude_loss sensor_distance heartrate cadence power
2 2020-02-02T03:02:02+01:00 SEGMENT_START_MANUAL
3 2020-02-02T03:02:03+01:00 TRACKPOINT 3 3.123456 14 14.001456 10 1020.2 10 54 1 1
4 2020-02-02T03:02:04+01:00 TRACKPOINT 54 1 1 10 66 3 50
5 2020-02-02T03:02:15+01:00 TRACKPOINT 68 3 50
6 2020-02-02T03:02:17+01:00 TRACKPOINT 3 3.123456 14.001 14.001456 10 1020.2 10 18 0 0 2 69 3 50
7 2020-02-02T03:02:18+01:00 SEGMENT_END_MANUAL
8 2020-02-02T03:03:20+01:00 SEGMENT_START_MANUAL
9 2020-02-02T03:03:21+01:00 TRACKPOINT 3 3.123456 14.002 14.002456 10 999.1 10 54 0 0
10 2020-02-02T03:03:22+01:00 SEGMENT_START_AUTOMATIC 3 3.123456 16 10 999.1 10 54 0 0
11 2020-02-02T03:03:30+01:00 IDLE 0 0
12 2020-02-02T03:03:50+01:00 TRACKPOINT 3 3.123456 16.001 10 999.1 10 54 0 0
13 2020-02-02T03:04:00+01:00 SEGMENT_END_MANUAL
@@ -60,7 +60,6 @@ public class CSVTrackExporter implements TrackExporter {
ALTITUDE_FORMAT.setGroupingUsed(false);
COORDINATE_FORMAT.setMaximumFractionDigits(6);
COORDINATE_FORMAT.setMaximumIntegerDigits(3);
COORDINATE_FORMAT.setGroupingUsed(false);
SPEED_FORMAT.setMaximumFractionDigits(2);
@@ -94,17 +93,17 @@ public class CSVTrackExporter implements TrackExporter {
new Column("trackpoint_type", t -> quote(t.getType().name())),
new Column("latitude", t -> t.hasLocation() ? COORDINATE_FORMAT.format(t.getLatitude()) : ""),
new Column("longitude", t -> t.hasLocation() ? COORDINATE_FORMAT.format(t.getLongitude()) : ""),
new Column("altitude", t -> t.hasAltitude() ? COORDINATE_FORMAT.format(t.getAltitude().toM()) : ""),
new Column("altitude", t -> t.hasAltitude() ? ALTITUDE_FORMAT.format(t.getAltitude().toM()) : ""),
new Column("accuracy_horizontal", t -> t.hasHorizontalAccuracy() ? DISTANCE_FORMAT.format(t.getHorizontalAccuracy().toM()) : ""),
new Column("accuracy_vertical", t -> t.hasVerticalAccuracy() ? DISTANCE_FORMAT.format(t.getVerticalAccuracy().toM()) : ""),
new Column("speed", t -> t.hasSpeed() ? SPEED_FORMAT.format(t.getSpeed().toKMH()) : ""),
new Column("altitude_gain", t -> t.hasAltitudeGain() ? DISTANCE_FORMAT.format(t.getAltitudeGain()) : ""),
new Column("altitude_loss", t -> t.hasAltitudeLoss() ? DISTANCE_FORMAT.format(t.getAltitudeLoss()) : ""),
new Column("altitude_gain", t -> t.hasAltitudeGain() ? ALTITUDE_FORMAT.format(t.getAltitudeGain()) : ""),
new Column("altitude_loss", t -> t.hasAltitudeLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeLoss()) : ""),
new Column("sensor_distance", t -> t.hasSensorDistance() ? DISTANCE_FORMAT.format(t.getSensorDistance().toM()) : ""),
new Column("heartrate", t -> t.hasHeartRate() ? HEARTRATE_FORMAT.format(t.getHeartRate().getBPM()) : ""),
new Column("cadence", t -> t.hasCadence() ? CADENCE_FORMAT.format(t.getCadence().getRPM()) : ""),
new Column("power", t -> t.hasPower() ? ALTITUDE_FORMAT.format(t.getPower().getW()) : ""));
new Column("power", t -> t.hasPower() ? POWER_FORMAT.format(t.getPower().getW()) : ""));
try {
prepare(outputStream);
@@ -136,7 +135,7 @@ public class CSVTrackExporter implements TrackExporter {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
writeTrackPoint(columns, trackPointIterator.next());
writeTrackPoint(columns, trackPointIterator.next());
}
}
}