forked from upstream-mirrors/OpenTracks
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 52226c8ef4 | |||
| c254a6ec75 | |||
| 0ecf4863a7 | |||
| 325196159d | |||
| 6adbf39e52 | |||
| db1a37f015 | |||
| 7ca9423fbf | |||
| 11c5ec43e2 | |||
| 3f891f7fb4 | |||
| 49260a0517 | |||
| 1392c5d92a | |||
| c641b436ce | |||
| 6948c2db41 | |||
| fb904f4a0b | |||
| 6c006cc9c7 | |||
| 7a73757ab1 | |||
| 9725cca2bf | |||
| 252f71e75f | |||
| fc2341515c | |||
| 77719f5bcd | |||
| 565ef7f12b | |||
| f4208e2f6b | |||
| 4b3ff45609 | |||
| 6dd9630bae | |||
| a4ec68def6 | |||
| d80be8b2a9 | |||
| 7d7ab5778a |
+33
-11
@@ -59,16 +59,38 @@ We do not support type of movement (i.e., walking vs running).
|
||||
|
||||
## Tested Barometric Sensor Smartphones
|
||||
|
||||
There are smartphones that have a barometric sensor that OpenTracks uses to compute altitude gain and loss.
|
||||
OpenTracks derives the altitude gain and altitude loss using the internal barometric sensor of a device (if present).
|
||||
However, barometric sensor seem to be prone to a lot of noise.
|
||||
This may either be a malfunctioning sensor, a case that prevents the device from measuring, or something else.
|
||||
|
||||
In our tests there are smartphones whose barometric sensor works well and others don't. Here is a list of the smartphones tested:
|
||||
To check if the barometric sensor of a device is working with OpenTracks:
|
||||
1. Record a track (ca. 1min) with the device stationary.
|
||||
Expectation: 0m gain and 0m loss should.
|
||||
2. Record a track (ca. 1min) while shaking the device.
|
||||
Expectation: 0m gain and 0m loss should.
|
||||
3. Record a track (ca. 1min) while moving the device up (less than 3m difference between highest and lowest point).
|
||||
Expectation: 0m gain and 0m loss should.
|
||||
4. Record a track walking up some stairs or taking an elevator.
|
||||
Expectation: some gain and some loss is recorded that seems realistic.
|
||||
|
||||
| Brand | Model | Android Version | Tests |
|
||||
|--------|--------------------|-----------------|--------------------------------------------------------------------------------|
|
||||
| Google | Pixel | LineageOS 17.1 | Ok |
|
||||
| Google | Pixel 2 XL | LineageOS 17.1 | Ok on the bike handlebars but it fails when I carry it in a pocket or backpack |
|
||||
| Google | Pixel 3 | Android 11 | Failure |
|
||||
| Google | Pixel 3a | Android 11 | Ok |
|
||||
| Google | Pixel 3a | Lineage 18.1 | Ok |
|
||||
| Google | Pixel 4a | Android 11 | Ok |
|
||||
| Sony | Xperia XZ1 Compact | LineageOS 16.1 | Failure |
|
||||
If any of these tests do **not** show expected values for gain/loss, OpenTracks will not show useful values.
|
||||
|
||||
Please note that OpenTracks:
|
||||
* only records gain/loss if +/- 3m to the initial/previous of are measured to the previous
|
||||
* solely uses the barometric sensor for gain/loss; GPS is not used for this.
|
||||
|
||||
In our tests there are smartphones whose barometric sensor works well and others don't.
|
||||
|
||||
Here is a list of the smartphones tested:
|
||||
|
||||
| Brand | Model | Android Version | Tests |
|
||||
|---------|--------------------|-----------------|--------------------------------------------------------------------------------|
|
||||
| Google | Pixel | LineageOS 17.1 | Ok |
|
||||
| Google | Pixel 2 XL | LineageOS 17.1 | Ok on the bike handlebars but it fails when I carry it in a pocket or backpack |
|
||||
| Google | Pixel 3 | Android 11 | Failure |
|
||||
| Google | Pixel 3a | Android 11 | Ok |
|
||||
| Google | Pixel 3a | Lineage 18.1 | Ok |
|
||||
| Google | Pixel 4a | Android 11 | Ok |
|
||||
| Google | Nexus 4 | LineageOS 18.1 | Ok |
|
||||
| Samsung | S4 | Android 11 | Ok |
|
||||
| Sony | Xperia XZ1 Compact | LineageOS 16.1 | Failure |
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.1.0-rc01'
|
||||
classpath 'com.android.tools.build:gradle:8.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 5286
|
||||
versionName "v4.6.0"
|
||||
versionCode 5313
|
||||
versionName "v4.7.0"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
@@ -128,7 +128,7 @@ dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.9.0'
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.6.1: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- Re-added aggregated statistics per selected tracks
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.6.2: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- Crash on voice annoucement for imperial+meter
|
||||
- Crash on settings for imperial+meter
|
||||
- Fixed clipping of charts (Material3 upgrade)
|
||||
- Bluetooth settings handle missing permission
|
||||
- Aggregated stats didn't show imperial units for avg speed
|
||||
@@ -0,0 +1,11 @@
|
||||
v4.7.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Statistics: distance, total time, and moving time are included between automatic segments (created due to distance too previous location too long)
|
||||
- Recorded tracks show sensor statistics again
|
||||
|
||||
Bugfix:
|
||||
- GPX exporter: for automatic segments their might be no location
|
||||
- CSV exporter: distance didn't use decimal grouping
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
v4.6.0: OpenTracks
|
||||
|
||||
Cambios:
|
||||
- Anuncios por voz usando o formato de plurais ICU (en, es, pt, zh, dr, de) debido ás cantidades en fraccións #1584
|
||||
- Require Android 7.0 / SDK24+ debido aos plurais ICU
|
||||
- En Android 14+: usar o conversor AltitudeConverter de Android no lugar do interno EGM2008
|
||||
|
||||
Arrranxo:
|
||||
- Non se podía escoller unha imaxe da galería en Android 13
|
||||
|
||||
Desenvolvemento:
|
||||
- Separamos ActivityType e ActivityIcon
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.6.1: OpenTracks
|
||||
|
||||
Arranxo:
|
||||
- Volvemos a engadir estatísticas conxuntas para as rutas seleccionadas
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -85,9 +85,6 @@ done
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
|
||||
+13
-13
@@ -202,7 +202,7 @@ public class ExportImportTest {
|
||||
// given
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
TrackExporter trackExporter = TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA.createTrackExporter(context, contentProviderUtils);
|
||||
TrackExporter trackExporter = TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.createTrackExporter(context, contentProviderUtils);
|
||||
|
||||
// when
|
||||
// 1. export
|
||||
@@ -238,24 +238,24 @@ public class ExportImportTest {
|
||||
TrackStatistics originalTrackStatistics = track.getTrackStatistics();
|
||||
|
||||
assertEquals(originalTrackStatistics.getTotalTime(), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(19), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(20), importedTrackStatistics.getTotalTime());
|
||||
|
||||
assertEquals(originalTrackStatistics.getMovingTime(), importedTrackStatistics.getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getMovingTime());
|
||||
|
||||
// Distance
|
||||
assertEquals(originalTrackStatistics.getTotalDistance(), importedTrackStatistics.getTotalDistance());
|
||||
assertEquals(125.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(222238.70, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
|
||||
// Speed
|
||||
assertEquals(originalTrackStatistics.getMaxSpeed(), importedTrackStatistics.getMaxSpeed());
|
||||
assertEquals(41.72, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(55559.67, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
|
||||
assertEquals(originalTrackStatistics.getAverageSpeed(), importedTrackStatistics.getAverageSpeed());
|
||||
assertEquals(6.58, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(11111.93, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
|
||||
assertEquals(originalTrackStatistics.getAverageMovingSpeed(), importedTrackStatistics.getAverageMovingSpeed());
|
||||
assertEquals(41.72, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(55559.67, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
|
||||
// Altitude
|
||||
assertEquals(originalTrackStatistics.getMinAltitude(), importedTrackStatistics.getMinAltitude(), 0.01);
|
||||
@@ -394,16 +394,16 @@ public class ExportImportTest {
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.getStartTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:03:23Z"), importedTrackStatistics.getStopTime());
|
||||
|
||||
assertEquals(Duration.ofSeconds(15), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(15), importedTrackStatistics.getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(80), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(80), importedTrackStatistics.getMovingTime());
|
||||
|
||||
// Distance
|
||||
assertEquals(125.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(222349.85, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
|
||||
// Speed
|
||||
assertEquals(8.34, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(8.34, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(8.34, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
assertEquals(2779.37, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(2779.37, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(2779.37, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
|
||||
// Altitude
|
||||
assertEquals(10, importedTrackStatistics.getMinAltitude(), 0.01);
|
||||
|
||||
+2
-3
@@ -765,7 +765,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps2, 0, 1, 0, 0, 0f, 0f), contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new TrackStatistics(startTime, gps2, 11113.275390625, 4, 3, 3704.4251302083335f, 0f, 0f).toString(), contentProviderUtils.getTrack(trackId).getTrackStatistics().toString());
|
||||
|
||||
|
||||
// when
|
||||
@@ -774,8 +774,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 0, 7, 0, 0, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 11113.275390625, 10, 3, 3704.4251302083335f, 0f, 0f).toString(), contentProviderUtils.getTrack(trackId).getTrackStatistics().toString());
|
||||
|
||||
|
||||
// then
|
||||
|
||||
+14
@@ -207,6 +207,20 @@ public class VoiceAnnouncementUtilsTest {
|
||||
assertEquals("Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_meter_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(Distance.ofMile(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL_METER, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
|
||||
@@ -81,9 +81,9 @@ public class TrackStatisticsUpdaterTest {
|
||||
|
||||
// then
|
||||
TrackStatistics statistics = subject.getTrackStatistics();
|
||||
assertEquals(128.03, statistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(13), statistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(9), statistics.getMovingTime());
|
||||
assertEquals(142.26, statistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(14), statistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(10), statistics.getMovingTime());
|
||||
|
||||
assertEquals(2.5, statistics.getMinAltitude(), 0.01);
|
||||
assertEquals(32.5, statistics.getMaxAltitude(), 0.01);
|
||||
@@ -92,8 +92,8 @@ public class TrackStatisticsUpdaterTest {
|
||||
|
||||
assertEquals(14.226, statistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(14.226, statistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
assertEquals(9.84, statistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(106.85f, statistics.getAverageHeartRate().getBPM(), 0.01);
|
||||
assertEquals(10.16, statistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(106.64f, statistics.getAverageHeartRate().getBPM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -49,6 +49,8 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.ActivityType;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
@@ -485,6 +487,13 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
return true;
|
||||
}
|
||||
|
||||
if (itemId == R.id.list_context_menu_aggregated_stats) {
|
||||
Intent intent = IntentUtils.newIntent(this, AggregatedStatisticsActivity.class)
|
||||
.putParcelableArrayListExtra(AggregatedStatisticsActivity.EXTRA_TRACK_IDS, new ArrayList<>(Arrays.asList(trackIds)));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (itemId == R.id.list_context_menu_select_all) {
|
||||
for (int i = 0; i < viewBinding.trackList.getCount(); i++) {
|
||||
viewBinding.trackList.setItemChecked(i, true);
|
||||
|
||||
@@ -946,7 +946,7 @@ public class ChartView extends View {
|
||||
*/
|
||||
private void updateEffectiveDimensions() {
|
||||
effectiveWidth = Math.max(0, width - leftBorder - rightBorder);
|
||||
effectiveHeight = Math.max(0, height - topBorder - bottomBorder);
|
||||
effectiveHeight = Math.max(0, height - topBorder - bottomBorder - spacer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,11 +130,11 @@ public class TrackPoint {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSegmentStart() {
|
||||
return type == Type.SEGMENT_START_AUTOMATIC || type == Type.SEGMENT_START_MANUAL;
|
||||
public boolean isSegmentManualStart() {
|
||||
return type == Type.SEGMENT_START_MANUAL;
|
||||
}
|
||||
|
||||
public boolean isSegmentEnd() {
|
||||
public boolean isSegmentManualEnd() {
|
||||
return type == Type.SEGMENT_END_MANUAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TrackRecordedActivity;
|
||||
@@ -114,10 +112,6 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
viewBinding = StatisticsRecordedBinding.inflate(inflater, container, false);
|
||||
|
||||
RecyclerView sensorsRecyclerView = viewBinding.statsSensorsRecyclerView;
|
||||
sensorsRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
// sensorsRecyclerView.setAdapter(sensorsAdapter);
|
||||
|
||||
return viewBinding.getRoot();
|
||||
}
|
||||
|
||||
@@ -258,6 +252,28 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
if (sensorStatistics == null) {
|
||||
return;
|
||||
}
|
||||
//TODO
|
||||
|
||||
if (sensorStatistics.hasHeartRate()) {
|
||||
String maxBPM = String.valueOf(Math.round(sensorStatistics.getMaxHeartRate().getBPM()));
|
||||
String avgBPM = String.valueOf(Math.round(sensorStatistics.getAvgHeartRate().getBPM()));
|
||||
|
||||
viewBinding.statsHeartRateGroup.setVisibility(View.VISIBLE);
|
||||
viewBinding.statsMaxHeartRateValue.setText(maxBPM);
|
||||
viewBinding.statsAvgHeartRateValue.setText(avgBPM);
|
||||
}
|
||||
if (sensorStatistics.hasCadence()) {
|
||||
String maxRPM = String.valueOf(Math.round(sensorStatistics.getMaxCadence().getRPM()));
|
||||
String avgRPM = String.valueOf(Math.round(sensorStatistics.getAvgCadence().getRPM()));
|
||||
|
||||
viewBinding.statsCadenceGroup.setVisibility(View.VISIBLE);
|
||||
viewBinding.statsMaxCadenceValue.setText(maxRPM);
|
||||
viewBinding.statsAvgCadenceValue.setText(avgRPM);
|
||||
}
|
||||
if (sensorStatistics.hasPower()) {
|
||||
String W = String.valueOf(Math.round(sensorStatistics.getAvgPower().getW()));
|
||||
|
||||
viewBinding.statsPowerGroup.setVisibility(View.VISIBLE);
|
||||
viewBinding.statsPowerValue.setText(W);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ public class CSVTrackExporter implements TrackExporter {
|
||||
SPEED_FORMAT.setMaximumFractionDigits(2);
|
||||
SPEED_FORMAT.setGroupingUsed(false);
|
||||
|
||||
DISTANCE_FORMAT.setMaximumFractionDigits(0);
|
||||
DISTANCE_FORMAT.setGroupingUsed(false);
|
||||
|
||||
HEARTRATE_FORMAT.setMaximumFractionDigits(0);
|
||||
HEARTRATE_FORMAT.setGroupingUsed(false);
|
||||
|
||||
|
||||
@@ -151,8 +151,12 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
if (wroteSegment) writeCloseSegment();
|
||||
writeOpenSegment();
|
||||
wroteSegment = true;
|
||||
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
|
||||
sensorPoints.clear();
|
||||
if (trackPoint.hasLocation()) {
|
||||
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
|
||||
sensorPoints.clear();
|
||||
} else {
|
||||
sensorPoints.add(trackPoint);
|
||||
}
|
||||
}
|
||||
case SENSORPOINT -> sensorPoints.add(trackPoint);
|
||||
case TRACKPOINT -> {
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class VoiceAnnouncementUtils {
|
||||
unitDistanceTTS = "kilometer";
|
||||
unitSpeedTTS = "kilometer per hour";
|
||||
}
|
||||
case IMPERIAL_FEET -> {
|
||||
case IMPERIAL_FEET, IMPERIAL_METER -> {
|
||||
perUnitStringId = R.string.voice_per_mile;
|
||||
distanceId = R.string.voiceDistanceMilesPlural;
|
||||
speedId = R.string.voiceSpeedMilesPerHourPlural;
|
||||
|
||||
@@ -454,7 +454,7 @@ public class PreferencesUtils {
|
||||
|
||||
String displayValue = formatter.formatDistance(distance);
|
||||
switch (unitSystem) {
|
||||
case METRIC -> {
|
||||
case METRIC, IMPERIAL_METER -> {
|
||||
if (value == recordingDistanceIntervalDefault) {
|
||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||
} else {
|
||||
@@ -498,7 +498,7 @@ public class PreferencesUtils {
|
||||
|
||||
String displayValue = formatter.formatDistance(distance);
|
||||
switch (unitSystem) {
|
||||
case METRIC -> {
|
||||
case METRIC, IMPERIAL_METER -> {
|
||||
if (value == maxRecordingDistanceDefault) {
|
||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||
} else {
|
||||
@@ -571,7 +571,7 @@ public class PreferencesUtils {
|
||||
|
||||
String displayValue = formatter.formatDistance(distance);
|
||||
switch (unitSystem) {
|
||||
case METRIC -> {
|
||||
case METRIC, IMPERIAL_METER -> {
|
||||
if (value == recordingGPSAccuracyDefault) {
|
||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||
} else if (value == recordingGPSAccuracyExcellent) {
|
||||
@@ -624,7 +624,7 @@ public class PreferencesUtils {
|
||||
entries[i] = resources.getString(R.string.value_float_kilometer_hour, value);
|
||||
}
|
||||
}
|
||||
case IMPERIAL_FEET -> {
|
||||
case IMPERIAL_FEET, IMPERIAL_METER -> {
|
||||
double valueMPH = Speed.ofKMH(value).toMPH();
|
||||
if (value == idleSpeedDefault) {
|
||||
entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH);
|
||||
|
||||
@@ -2,14 +2,17 @@ package de.dennisguse.opentracks.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.EditTextPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.settings.bluetooth.BluetoothLeSensorPreference;
|
||||
import de.dennisguse.opentracks.util.PermissionRequester;
|
||||
|
||||
public class SensorsSettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
@@ -30,6 +33,13 @@ public class SensorsSettingsFragment extends PreferenceFragmentCompat {
|
||||
@Override
|
||||
public void onDisplayPreferenceDialog(Preference preference) {
|
||||
if (preference instanceof BluetoothLeSensorPreference) {
|
||||
if(!PermissionRequester.BLUETOOTH.hasPermission(preference.getContext())) {
|
||||
// TODO: maybe use requestPermissionsIfNeeded here or disable preferences at all
|
||||
FragmentActivity activity = getActivity();
|
||||
Toast.makeText(activity, getString(R.string.permission_bluetooth_failed), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
DialogFragment dialogFragment = ((BluetoothLeSensorPreference) preference).createInstance();
|
||||
dialogFragment.setTargetFragment(this, 0);
|
||||
dialogFragment.show(getParentFragmentManager(), getClass().getSimpleName());
|
||||
|
||||
@@ -38,6 +38,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
*/
|
||||
//TODO Use null instead of Double.isInfinite
|
||||
//TODO Check that data ranges are valid (not less than zero etc.)
|
||||
//TODO Should be a Java record
|
||||
public class TrackStatistics {
|
||||
|
||||
// The min and max altitude (meters) seen on this track.
|
||||
@@ -261,7 +262,7 @@ public class TrackStatistics {
|
||||
* This calculation only takes into account the displacement until the last point that was accounted for in statistics.
|
||||
*/
|
||||
public Speed getAverageSpeed() {
|
||||
if (totalDistance.isZero() && totalDistance.isZero()) {
|
||||
if (totalTime.isZero()) {
|
||||
return Speed.of(0);
|
||||
}
|
||||
return Speed.of(totalDistance.toM() / totalTime.getSeconds());
|
||||
|
||||
@@ -95,7 +95,7 @@ public class TrackStatisticsUpdater {
|
||||
*
|
||||
*/
|
||||
public void addTrackPoint(TrackPoint trackPoint) {
|
||||
if (trackPoint.isSegmentStart()) {
|
||||
if (trackPoint.isSegmentManualStart()) {
|
||||
reset(trackPoint);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class TrackStatisticsUpdater {
|
||||
updateSpeed(trackPoint, lastTrackPoint);
|
||||
}
|
||||
|
||||
if (trackPoint.isSegmentEnd()) {
|
||||
if (trackPoint.isSegmentManualEnd()) {
|
||||
reset(trackPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -143,9 +143,9 @@ public class AggregatedStatisticsAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
public void setPace(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
|
||||
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(reportSpeed).build(context);
|
||||
|
||||
setCommonValues(aggregatedStatistic);
|
||||
|
||||
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(reportSpeed).build(context);
|
||||
{
|
||||
Pair<String, String> parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed());
|
||||
avgSpeed.setText(parts.first);
|
||||
|
||||
@@ -397,23 +397,249 @@
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="stats_altitude_gain_value,stats_altitude_loss_value" />
|
||||
|
||||
<!-- Horizontal line -->
|
||||
<!-- Heart Rate -->
|
||||
<View
|
||||
android:id="@+id/stats_end_horizontal_line"
|
||||
android:id="@+id/stats_heart_rate_horizontal_line"
|
||||
style="@style/HorizontalLine"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_altitude_barrier" />
|
||||
|
||||
<!-- Sensors data -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/stats_sensors_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/stats_heart_rate_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="stats_heart_rate_horizontal_line,stats_max_heart_rate_label,stats_max_heart_rate_value,stats_max_heart_rate_unit,stats_avg_heart_rate_label,stats_avg_heart_rate_value,stats_avg_heart_rate_unit" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_heart_rate_label"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_heart_rate_max"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_end_horizontal_line" />
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_heart_rate_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_heart_rate_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_max_heart_rate_unit"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_max_heart_rate_label"
|
||||
tools:text="100" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_heart_rate_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_heart_rate_unit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_max_heart_rate_value"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_max_heart_rate_value"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_heart_rate_label"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_heart_rate_avg"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_heart_rate_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_heart_rate_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_avg_heart_rate_unit"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_avg_heart_rate_label"
|
||||
tools:text="100" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_heart_rate_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_heart_rate_unit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_avg_heart_rate_value"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_avg_heart_rate_value"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/stats_heart_rate_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="stats_max_heart_rate_value,stats_avg_heart_rate_value" />
|
||||
|
||||
<!-- Cadence -->
|
||||
<View
|
||||
android:id="@+id/stats_cadence_horizontal_line"
|
||||
style="@style/HorizontalLine"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_heart_rate_barrier" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/stats_cadence_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="stats_cadence_horizontal_line,stats_max_cadence_label,stats_max_cadence_value,stats_max_cadence_unit,stats_avg_cadence_label,stats_avg_cadence_value,stats_avg_cadence_unit" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_cadence_label"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_cadence_max"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_cadence_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_cadence_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_max_cadence_unit"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_max_cadence_label"
|
||||
tools:text="100" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_max_cadence_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_cadence_unit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_max_cadence_value"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_max_cadence_value"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_cadence_label"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_cadence_avg"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_cadence_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_cadence_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_avg_cadence_unit"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_avg_cadence_label"
|
||||
tools:text="100" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_avg_cadence_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_cadence_unit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_avg_cadence_value"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_avg_cadence_value"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/stats_cadence_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="stats_max_cadence_value,stats_avg_cadence_value" />
|
||||
|
||||
<!-- Power -->
|
||||
<View
|
||||
android:id="@+id/stats_power_horizontal_line"
|
||||
style="@style/HorizontalLine"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_cadence_barrier" />
|
||||
|
||||
<!-- Sensors data -->
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/stats_power_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="stats_power_horizontal_line,stats_power_label,stats_power_value,stats_power_unit" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_power_label"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_power_avg"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_power_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_power_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_power_unit"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_power_label"
|
||||
tools:text="100" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_power_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sensor_state_power_unit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_power_value"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_power_value"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline2" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/stats_power_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="stats_power_value" />
|
||||
|
||||
<!-- Horizontal Line -->
|
||||
<View
|
||||
android:id="@+id/stats_end_horizontal_line"
|
||||
style="@style/HorizontalLine"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_power_barrier" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
@@ -35,6 +35,11 @@ limitations under the License.
|
||||
android:icon="@drawable/ic_delete_forever_24dp"
|
||||
android:title="@string/menu_delete"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/list_context_menu_aggregated_stats"
|
||||
android:icon="@drawable/ic_statistics_24dp"
|
||||
android:title="@string/menu_aggregated_statistics"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/list_context_menu_select_all"
|
||||
android:icon="@drawable/ic_select_all_24dp"
|
||||
|
||||
@@ -202,7 +202,7 @@ limitations under the License.
|
||||
<string name="menu_aggregated_statistics">Souhrnná statistika</string>
|
||||
<string name="menu_delete">Smazat</string>
|
||||
<string name="menu_edit">Upravit</string>
|
||||
<string name="menu_export_all">Exportovat vše</string>
|
||||
<string name="menu_export_all">Exportovat vše (jeden soubor na stopu)</string>
|
||||
<string name="menu_help">Nápověda</string>
|
||||
<string name="menu_import_all">Importovat vše</string>
|
||||
<string name="menu_insert_marker">Vložit značku</string>
|
||||
@@ -406,7 +406,7 @@ limitations under the License.
|
||||
<string name="open_track_as_GPX">Otevřít jako GPX</string>
|
||||
<string name="open_track_as_trackfileformat">Otevřít jako %1$s</string>
|
||||
<string name="export_all_do_it_for_all">provést pro všechny konflikty</string>
|
||||
<string name="export_track_errors">Trasa nebyla exportována</string>
|
||||
<string name="export_track_errors">Soubory nebyly exportovány</string>
|
||||
<string name="generic_separator_done_total">/</string>
|
||||
<string name="generic_completed">Ukončeno</string>
|
||||
<string name="gps_disabled_msg">GPS vypnuto</string>
|
||||
@@ -434,7 +434,7 @@ limitations under the License.
|
||||
<string name="description_altitude_loss">Převýšení: %1$d m (%2$d ft)</string>
|
||||
<string name="export_error_post_workout">Export po ukončení aktivity selhal, zkontrolujte prosím adresář pro export.</string>
|
||||
<string name="stats_loss">Ztráta</string>
|
||||
<string name="export_track_already_exists_msg">Trasa %1$s již existuje v cílovém adresáři.</string>
|
||||
<string name="export_track_already_exists_msg">Soubor %1$s již existuje v cílovém adresáři.</string>
|
||||
<string name="generic_overwrite">Přepsat</string>
|
||||
<string name="generic_show_errors">Zobrazit chyby</string>
|
||||
<string name="generic_click_twice_cancel">Opakovaně kliknout zpět pro ukončení</string>
|
||||
@@ -453,9 +453,9 @@ limitations under the License.
|
||||
<string name="import_progress_summary_errors_msg">Chyba</string>
|
||||
<string name="settings_prevent_reimport_tracks_title">Zabraňte opětovnému importu aktivit</string>
|
||||
<string name="export_progress_summary_errors_msg">Chyba</string>
|
||||
<string name="export_progress_summary_skip_msg">Stopy přeskočeny</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Skladby přepsány</string>
|
||||
<string name="export_progress_summary_new_msg">Vyvezeny nové tratě</string>
|
||||
<string name="export_progress_summary_skip_msg">Soubory přeskočeny</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Soubory přepsány</string>
|
||||
<string name="export_progress_summary_new_msg">Nové soubory exportovány</string>
|
||||
<string name="import_progress_summary_exists_msg">Existovat</string>
|
||||
<string name="import_progress_summary_ok_msg">Importované soubory</string>
|
||||
<string name="generic_open_track">Otevřená trať</string>
|
||||
@@ -617,4 +617,12 @@ limitations under the License.
|
||||
<string name="unit_minute_per_nautical_mile">min/NM</string>
|
||||
<string name="value_integer_knots">%1$d uzlů</string>
|
||||
<string name="value_float_knots_recommended">%1$.1f uzlů (doporučeno)</string>
|
||||
<string name="settings_stats_units_imperial_meter">Imperiální (mi, m)</string>
|
||||
<string name="menu_export_all_one_file">Exportovat vše (jeden soubor na všechny stopy)</string>
|
||||
<string name="settings_recording_min_required_accuracy_summary">Poloha bude ignorována, pokud je její přesnost větší než %1$s</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_title">Filtrovat zařízení Bluetooth</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_off">Zobrazit všechna zjistitelná zařízení Bluetooth</string>
|
||||
<string name="no_compatible_camera_installed">Není nainstalována kompatibilní aplikace fotoaparátu</string>
|
||||
<string name="no_compatible_gallery_installed">Není nainstalována kompatibilní aplikace galerie obrázků</string>
|
||||
<string name="show_on_dashboard">API OpenTracks Dashboard</string>
|
||||
</resources>
|
||||
@@ -45,14 +45,14 @@ OpenTracks utilise le capteur GPS de lappareil pour enregistrer la position en c
|
||||
Si le dispositif GPS signale des données inexactes (par exemple, la localisation, la vitesse, laltitude), OpenTracks ne peut rien y faire.</string>
|
||||
<string name="help_data_storage_title">Comment OpenTracks stocke-t-il les données des capteurs \?</string>
|
||||
<string name="help_data_storage_content"> Les données des capteurs sont stockées par emplacement enregistré. Dans le cas dun capteur de fréquence cardiaque, cela signifie que seule la mesure de la fréquence cardiaque <i>one</i> est stockée par emplacement. Si vous êtes à larrêt ou à lintérieur, aucune donnée du capteur ne sera enregistrée (mais elle sera affichée). </string>
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks nenregistre pas les lieux \?</string>
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks n’enregistre pas la position \?</string>
|
||||
<string name="help_gps_troubleshooting_content"> Ce que vous pouvez faire :
|
||||
\n a) vérifier si le GPS est activé,
|
||||
\n b) améliorer la réception GPS (par exemple, aller à lextérieur),
|
||||
\n c) vérifier si avec <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a> app, et
|
||||
\n d) désactiver léconomie dénergie.
|
||||
\n b) améliorer la réception du GPS (p. ex. aller à l\'extérieur),
|
||||
\n c) contrôler avec l\'application <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a>
|
||||
\n d) désactiver l\'économie d\'énergie.
|
||||
\n
|
||||
\n Si tout ne va pas dans le bon sens, veuillez signaler un bug. </string>
|
||||
\n Si le problème persiste, veuillez signaler un bug. </string>
|
||||
<string name="help_support_title">Comment puis-je soutenir OpenTracks \?</string>
|
||||
<string name="help_support_content"> Vous pouvez :
|
||||
\n a) faire connaître OpenTracks,
|
||||
@@ -204,7 +204,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="menu_aggregated_statistics">Statistiques cumulées</string>
|
||||
<string name="menu_delete">Supprimer</string>
|
||||
<string name="menu_edit">Modifier</string>
|
||||
<string name="menu_export_all">Tout exporter</string>
|
||||
<string name="menu_export_all">Tout exporter (Un fichier par tracé)</string>
|
||||
<string name="menu_help">Aide</string>
|
||||
<string name="menu_import_all">Tout importer</string>
|
||||
<string name="menu_insert_marker">Insérer un repère</string>
|
||||
@@ -242,7 +242,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="settings_recording_keep_screen_on_while_recording_summary">Pendant l\'enregistrement, garder l\'écran allumé.</string>
|
||||
<string name="settings_recording_default_activity_title">Type d\'activité par défaut</string>
|
||||
<string name="settings_recording_location_frequency_summary">%1$s entre chaque enregistrement de la position</string>
|
||||
<string name="settings_recording_max_recording_distance_summary">Une nouvelle section est créée si la distance entre deux positions est supérieure à %1$s</string>
|
||||
<string name="settings_recording_max_recording_distance_summary">Un nouveau segment est créé si la distance entre deux positions est supérieure à %1$s</string>
|
||||
<string name="settings_recording_max_recording_distance_title">Distance max</string>
|
||||
<string name="settings_recording_min_recording_distance_title">Intervalle dist. enreg</string>
|
||||
<string name="settings_recording_min_recording_interval_title">Intervalle temps enreg</string>
|
||||
@@ -259,7 +259,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="settings_sensor_bluetooth">Bluetooth</string>
|
||||
<!-- Settings Stats -->
|
||||
<string name="settings_stats_rate_title">Mode de calcul souhaité</string>
|
||||
<string name="settings_stats_units_imperial">Unités impériales (mi, pi)</string>
|
||||
<string name="settings_stats_units_imperial">Unités impériales (miles, pieds)</string>
|
||||
<string name="settings_stats_units_metric">Unités métriques (km, m)</string>
|
||||
<string name="settings_stats_units_title">Unités souhaitées</string>
|
||||
<!-- Share Track -->
|
||||
@@ -437,7 +437,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="settings_sensor_wheel_circumference">Circonférence de la roue (mm)</string>
|
||||
<string name="export_error_post_workout">L\'exportation du post-travail a échoué, veuillez vérifier le répertoire d\'exportation.</string>
|
||||
<string name="export_all_do_it_for_all">le faire pour tous les conflits</string>
|
||||
<string name="export_track_errors">Tracés non exportés</string>
|
||||
<string name="export_track_errors">Fichiers non exportés</string>
|
||||
<string name="import_unable_to_import_file">Impossible d\'importer le fichier : %1$s</string>
|
||||
<string name="import_no_kml_file_found">Pas de doc.fichier kml trouvé dans KMZ</string>
|
||||
<string name="import_error_info">%1$s : %2$s</string>
|
||||
@@ -446,14 +446,14 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="generic_completed">Compléter</string>
|
||||
<string name="sensor_state_cadence_max">Cadence maximale</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_title">Plein écran</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Pendant l\'enregistrement, présent en plein écran.</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Pendant l\'enregistrement, affichage en plein écran.</string>
|
||||
<string name="sensor_state_power_avg">Puissance moyenne</string>
|
||||
<string name="sensor_state_heart_rate_max">Fréquence cardiaque max</string>
|
||||
<string name="sensor_state_heart_rate_avg">Rythme cardiaque moyen</string>
|
||||
<string name="sensor_state_cadence_avg">Cadence moyenne</string>
|
||||
<string name="generic_click_twice_cancel">Cliquez sur retour pour annuler</string>
|
||||
<string name="export_progress_summary_new_msg">Nouveaux tracés exportés</string>
|
||||
<string name="export_progress_summary_skip_msg">Tracés ignorés</string>
|
||||
<string name="export_progress_summary_new_msg">Nouveaux fichiers exportés</string>
|
||||
<string name="export_progress_summary_skip_msg">Fichiers ignorés</string>
|
||||
<string name="export_progress_summary_errors_msg">Erreurs</string>
|
||||
<string name="generic_overwrite">Écraser</string>
|
||||
<string name="generic_show_errors">Afficher les erreurs</string>
|
||||
@@ -477,14 +477,14 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
</plurals>
|
||||
<string name="settings_default_trackfileformat">Format de fichier d\'exportation / partage</string>
|
||||
<string name="description_altitude_loss">Dénivelé négatif : %1$d m (%2$d ft)</string>
|
||||
<string name="export_track_already_exists_msg">Le tracé %1$s existe déjà dans le répertoire de destination.</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Tracés écrasés</string>
|
||||
<string name="export_track_already_exists_msg">Le fichier %1$s existe déjà dans le répertoire de destination.</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Fichiers écrasés</string>
|
||||
<string name="about_third_party_data">Données de tiers</string>
|
||||
<string name="delete_service">Service de suppression</string>
|
||||
<string name="menu_voice_rate">Vitesse vocale</string>
|
||||
<string name="track_delete_not_recording">Cette piste ne peut pas être supprimée car elle est en cours d\'enregistrement.</string>
|
||||
<string name="settings_sensor_cycling_distance_speed">Distance et vitesse</string>
|
||||
<string name="settings_sensor_cycling_cadence">Cadre</string>
|
||||
<string name="settings_sensor_cycling_cadence">Cadence</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">Distance, vitesse et cadence</string>
|
||||
<string name="settings_layout_reset">Réinitialiser la disposition personnalisée</string>
|
||||
<string name="settings_layout_reset_confirm_message">Tous les paramètres de disposition reviendront à leur valeur par défaut. Ceci ne supprimera aucun tracé de l\'appareil.</string>
|
||||
@@ -516,7 +516,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="value_float_kilometer_hour">%1$.1f km/h</string>
|
||||
<string name="settings_generic_sensor">Générique</string>
|
||||
<string name="settings_cycling_sensor">Cyclisme</string>
|
||||
<string name="settings_running_sensor">Courant</string>
|
||||
<string name="settings_running_sensor">Course à pied</string>
|
||||
<string name="settings_import_section">Importer</string>
|
||||
<string name="settings_export_section">Exporter</string>
|
||||
<string name="settings_reset_summary">Réinitialiser les paramètres aux valeurs par défaut</string>
|
||||
@@ -528,7 +528,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="settings_import_export_title">Importez/Exportez</string>
|
||||
<string name="settings_announcements_summary">Temps, distance, vitesse de la voix</string>
|
||||
<string name="settings_announcements_title">Annonces vocales</string>
|
||||
<string name="settings_sensors_title">Intervalle de temps, Intervalle de distance, Distance maximale, Précision</string>
|
||||
<string name="settings_sensors_title">Capteurs Bluetooth</string>
|
||||
<string name="settings_gps_summary">Intervalle de temps, Intervalle de distance, Distance maximale, Précision</string>
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_ui_title">Interface utilisateur</string>
|
||||
@@ -609,7 +609,7 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="description_pace_nautical">Allure (min/MN)</string>
|
||||
<string name="show_on_dashboard_not_installed">Il n\'y a pas d\'application installé supportant l\'API OpenTracks Dashboard.</string>
|
||||
<string name="description_speed_nautical">Vitesse (nœuds)</string>
|
||||
<string name="settings_stats_units_nautical">Nautique (MN, pieds)</string>
|
||||
<string name="settings_stats_units_nautical">Nautique (NM, pieds)</string>
|
||||
<string name="unit_nautical_mile">MN</string>
|
||||
<string name="unit_knots">kn</string>
|
||||
<string name="unit_minute_per_nautical_mile">min/MN</string>
|
||||
@@ -635,4 +635,14 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="track_delete_number_of_tracks">%1$d tracés</string>
|
||||
<string name="introduction_osm_dashboard">OpenTracks ne fournit pas de carte en tant que telle. Veuillez installer OSMDashboard pour visualiser vos tracés sur une carte.</string>
|
||||
<string name="help_data_google_play_services_content">Non</string>
|
||||
<string name="settings_stats_units_imperial_meter">Unités impériales (miles, m)</string>
|
||||
<string name="menu_export_all_one_file">Tout exporter (En un seul fichier)</string>
|
||||
<string name="no_compatible_camera_installed">Aucune application pour l\'appareil photo compatible n\'est installée</string>
|
||||
<string name="settings_recording_min_required_accuracy_summary">La position est ignoré si sa précision est supérieure à %1$s</string>
|
||||
<string name="voice_on_device_speaker_title">Utiliser l\'haut-parleur de l\'appareil</string>
|
||||
<string name="no_compatible_gallery_installed">Aucune application de galerie d\'images compatible n\'est installée</string>
|
||||
<string name="settings_api_summary">API de contrôle et de statistiques pour applications tierces</string>
|
||||
<string name="settings_sensor_heart_rate_max">Zones : fréquence cardiaque maximale (bpm)</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_title">Filtrer les périphériques Bluetooth</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_off">Afficher tout les périphériques Bluetooth découverts</string>
|
||||
</resources>
|
||||
@@ -353,8 +353,8 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<item quantity="other">%1$.1f quilómetros por hora</item>
|
||||
</plurals>
|
||||
<plurals name="voiceSpeedMilesPerHour">
|
||||
<item quantity="one">1 quilómetro por hora</item>
|
||||
<item quantity="other">%1$.1f quilómetros por hora</item>
|
||||
<item quantity="one">1 milla por hora</item>
|
||||
<item quantity="other">%1$.1f millas por hora</item>
|
||||
</plurals>
|
||||
<!-- Waypoint Type -->
|
||||
<string name="waypoint_type_atm">Caixeiro automático</string>
|
||||
|
||||
@@ -410,7 +410,7 @@ limitations under the License.
|
||||
<string name="generic_click_twice_cancel">Trykk tilbake-knappen igjen for å avbryte</string>
|
||||
<string name="help_track_map_content"> Bruk det lille kartikonet.
|
||||
\n a) (sanntidsoppdateringer) Installer <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>. Dette gir nettbaserte eller nettfrakoblede kart via <a href="https://www.openstreetmap.org">OpenStreetMap</a>.
|
||||
\n Egentlig er OSMDashboard et egen program som bare har tilgang (midlertidig) på dataene til spor som skal vises.
|
||||
\n Egentlig er OSMDashboard et eget program som bare har tilgang (midlertidig) på dataene til spor som skal vises.
|
||||
\n b) Via et vanlig kartprogram (f.eks. <a href="http://osmand.net/">OsmAnd</a> og <a href="https://maps.me/">MAPS.ME</a>). Disse programmene må støtte KMZ-filformatet (bare posisjoner og tidsstempler). Faktisk trenger et program å støtte <i>ACTION_VIEW</i> med MIME <i>application/vnd.google-earth.kmz</i>. </string>
|
||||
<string name="help_track_export_title">Hvordan eksportere/dele spor som er tatt opp\?</string>
|
||||
<string name="help_track_export_content"> Spor kan eksporteres fra Innstillinger som KMZ, KML eller GPX. KMZ/KML alle data; GPX bare posisjoner. Spor som deles via <i>deleikonet</i> blir delt som KMZ. </string>
|
||||
@@ -539,7 +539,7 @@ limitations under the License.
|
||||
<string name="settings_public_api_disabled_toast">OpenTracks offentlige API er slått av: Det kan slås på i innstillingene.</string>
|
||||
<string name="activity_type_swimming">svømming</string>
|
||||
<string name="activity_type_swimming_open">svømming i åpent vann</string>
|
||||
<string name="activity_type_workout">styrketrening</string>
|
||||
<string name="activity_type_workout">treningsøkt</string>
|
||||
<string name="generic_dismiss">Avvis</string>
|
||||
<string name="gps_recording_status">%1$s: %2$s</string>
|
||||
<string name="gps_recording_without_signal">OpenTracks gjør opptak uten GPS-data.</string>
|
||||
@@ -608,4 +608,12 @@ limitations under the License.
|
||||
<string name="settings_recording_min_required_accuracy_summary">Posisjonen ignoreres hvis nøyaktigheten er over %1$s</string>
|
||||
<string name="no_compatible_gallery_installed">Ingen kompatibel bildegalleri-app installert</string>
|
||||
<string name="no_compatible_camera_installed">Ingen kompatibel kamera-app installert</string>
|
||||
<string name="settings_stats_units_imperial_meter">Britiske (mi, m)</string>
|
||||
<string name="voiceHoursPlural">{n, plural, =1 {1 time} other {{n,number} timer} }</string>
|
||||
<string name="voiceMinutesPlural">{n, plural, =1 {1 minutt} other {{n,number} minutter} }</string>
|
||||
<string name="voiceSecondsPlural">{n, plural, =1 {1 sekund} other {{n,number} sekunder} }</string>
|
||||
<string name="voiceSpeedKilometersPerHourPlural">{n, plural, =1 {1 kilometer i timen} other {{n,number,#.0} kilometer i timen} }</string>
|
||||
<string name="voiceSpeedMKnotsPlural">{n, plural, =1 {1 knop} other {{n,number,#.0} knop} }</string>
|
||||
<string name="voiceDistanceKilometersPlural">{n, plural, =1 {1 kilometer} other {{n,number,#.0} kilometer} }</string>
|
||||
<string name="voiceDistanceNauticalMilesPlural">{n, plural, =1 {1 nautisk mil} other {{n,number,#.0} nautiske mil} }</string>
|
||||
</resources>
|
||||
@@ -198,12 +198,12 @@ limitations under the License.
|
||||
<string name="export_cannot_write_to_dir">無法寫入匯出目錄。</string>
|
||||
<string name="export_dir_not_writable">" (不可寫入!)"</string>
|
||||
<string name="export_progress_message">正在匯出至 %1$s…</string>
|
||||
<string name="export_track_already_exists_msg">蹤跡 %1$s 已存在於目標目錄之中。</string>
|
||||
<string name="export_track_already_exists_msg">檔案 %1$s 已存在於目標目錄之中。</string>
|
||||
<string name="export_all_do_it_for_all">對所有衝突這麼做</string>
|
||||
<string name="export_track_errors">蹤跡未匯出</string>
|
||||
<string name="export_progress_summary_new_msg">新蹤跡已匯出</string>
|
||||
<string name="export_progress_summary_overwrite_msg">蹤跡覆蓋</string>
|
||||
<string name="export_progress_summary_skip_msg">蹤跡已略過</string>
|
||||
<string name="export_track_errors">檔案未匯出</string>
|
||||
<string name="export_progress_summary_new_msg">新檔案已匯出</string>
|
||||
<string name="export_progress_summary_overwrite_msg">檔案覆蓋</string>
|
||||
<string name="export_progress_summary_skip_msg">檔案已略過</string>
|
||||
<string name="export_progress_summary_errors_msg">錯誤</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Generic -->
|
||||
@@ -285,7 +285,7 @@ limitations under the License.
|
||||
<string name="menu_aggregated_statistics">彙總的統計資料</string>
|
||||
<string name="menu_delete">刪除</string>
|
||||
<string name="menu_edit">編輯</string>
|
||||
<string name="menu_export_all">全部匯出</string>
|
||||
<string name="menu_export_all">全部匯出 (每蹤跡一個檔案)</string>
|
||||
<string name="menu_help">說明</string>
|
||||
<string name="menu_import_all">全部匯入</string>
|
||||
<string name="menu_insert_marker">插入標記</string>
|
||||
@@ -636,4 +636,11 @@ limitations under the License.
|
||||
<string name="always">總是</string>
|
||||
<string name="introduction_osm_dashboard">OpenTracks 本身不提供地圖。請安裝 OSMDashboard 以在地圖上檢視您的紀錄。</string>
|
||||
<string name="voice_on_device_speaker_title">使用裝置的揚聲器</string>
|
||||
<string name="settings_stats_units_imperial_meter">英制 (英里、公尺)</string>
|
||||
<string name="menu_export_all_one_file">全部匯出 (所有蹤跡於單一檔案)</string>
|
||||
<string name="settings_recording_min_required_accuracy_summary">如果定位的精度大於 %1$s,則它將被忽略</string>
|
||||
<string name="no_compatible_gallery_installed">沒有安裝相容的圖片庫應用程式</string>
|
||||
<string name="no_compatible_camera_installed">沒有安裝相容的攝影機應用程式</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_title">篩選藍芽裝置</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_off">顯示所有可發現的藍芽裝置</string>
|
||||
</resources>
|
||||
@@ -328,12 +328,15 @@ limitations under the License.
|
||||
<!-- Sensor State -->
|
||||
<string name="sensor_state_cadence_avg">Avg Cadence</string>
|
||||
<string name="sensor_state_cadence_max">Max Cadence</string>
|
||||
<string name="sensor_state_cadence_unit">rpm</string>
|
||||
<string name="sensor_state_heart_rate">Heart rate</string>
|
||||
<string name="sensor_state_heart_rate_avg">Avg Heart rate</string>
|
||||
<string name="sensor_state_heart_rate_max">Max Heart rate</string>
|
||||
<string name="sensor_state_heart_rate_unit">bpm</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d bpm</string>
|
||||
<string name="sensor_state_power">Power</string>
|
||||
<string name="sensor_state_power_avg">Avg Power</string>
|
||||
<string name="sensor_state_power_unit">W</string>
|
||||
<string name="sensor_could_not_scan">Could not scan for Bluetooth devices (error %1$i).</string>
|
||||
<string name="bluetooth_disabled">Please enable Bluetooth.</string>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user