Compare commits

...

22 Commits

Author SHA1 Message Date
Dennis Guse 648c106f7f Release: v4.19.2 2025-05-05 09:23:40 +02:00
Dennis Guse bb86ab927c Merge pull request #2098 from quazgar/fix-values-de-crash
Fix crash in overeager translations
2025-05-05 08:19:26 +02:00
Quazgar 9150318ef9 Bugfix: Fixed overeager translations to French, Gaelic, Tamil.
See #2097
2025-05-05 00:26:21 +02:00
Quazgar b98a0a0283 Bugfix: Fixed overeager translation to German. 2025-05-04 23:54:37 +02:00
Dennis Guse 71f1049642 Release: v4.19.1 2025-04-23 22:25:57 +02:00
dependabot[bot] 6185154af9 Bump com.android.tools.build:gradle from 8.9.1 to 8.9.2
Bumps com.android.tools.build:gradle from 8.9.1 to 8.9.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-22 07:21:22 +02:00
Dennis Guse b4ccdcf4a2 Bugfix: GPX exporter missed schemaLocation for TrackStatsExtension/v1
Fixes #2093.
2025-04-21 22:15:17 +02:00
Dennis Guse 681b987927 Cleanup: export/import renaming. 2025-04-21 22:05:28 +02:00
Dennis Guse ed163b2083 Target SDK 36. 2025-04-10 07:54:44 +02:00
dependabot[bot] 77ccbe7004 Bump androidx.gridlayout:gridlayout from 1.0.0 to 1.1.0
Bumps androidx.gridlayout:gridlayout from 1.0.0 to 1.1.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-10 07:33:53 +02:00
dependabot[bot] 247a5f342a Bump androidx.core:core from 1.15.0 to 1.16.0
Bumps androidx.core:core from 1.15.0 to 1.16.0.

---
updated-dependencies:
- dependency-name: androidx.core:core
  dependency-version: 1.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-10 07:33:41 +02:00
dependabot[bot] 7b9b1d3c95 Bump org.mockito:mockito-android from 5.16.1 to 5.17.0
Bumps [org.mockito:mockito-android](https://github.com/mockito/mockito) from 5.16.1 to 5.17.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.16.1...v5.17.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 07:09:59 +02:00
dependabot[bot] 44fe4f8818 Bump reactivecircus/android-emulator-runner from 2.33.0 to 2.34.0
Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.33.0 to 2.34.0.
- [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases)
- [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md)
- [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/v2.33.0...v2.34.0)

---
updated-dependencies:
- dependency-name: reactivecircus/android-emulator-runner
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 07:19:03 +02:00
Dennis Guse 1f55729b71 README: add wanderer 2025-03-28 23:01:56 +01:00
Dennis Guse 8592375edc Bugfix: settings for recording UI configuration are now edge-2-edge friendly. 2025-03-26 22:04:33 +01:00
dependabot[bot] 2c1ffd5fa1 Bump com.android.tools.build:gradle from 8.9.0 to 8.9.1
Bumps com.android.tools.build:gradle from 8.9.0 to 8.9.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 06:28:53 +01:00
Dennis Guse 2672602a71 Bugfix: diagram x-line was hidden on some devices.
Fixes #2075.
2025-03-17 17:08:21 +01:00
Aindriú Mac Giolla Eoin 9e0553d5d6 Translated using Weblate (Irish)
Currently translated at 100.0% (159 of 159 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/ga/
2025-03-17 05:43:18 +00:00
Poesty Li 5b7bc4ea24 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (159 of 159 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/zh_Hans/
2025-03-17 05:43:17 +00:00
Fjuro f4a477b99d Translated using Weblate (Czech)
Currently translated at 100.0% (159 of 159 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/cs/
2025-03-17 05:43:16 +00:00
Stephan Paternotte c9a2b31866 Translated using Weblate (Dutch)
Currently translated at 100.0% (159 of 159 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/nl/
2025-03-17 05:43:16 +00:00
dependabot[bot] 4412a6a698 Bump org.mockito:mockito-android from 5.16.0 to 5.16.1
Bumps [org.mockito:mockito-android](https://github.com/mockito/mockito) from 5.16.0 to 5.16.1.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.16.0...v5.16.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 06:43:10 +01:00
31 changed files with 177 additions and 127 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
sudo udevadm trigger --name-match=kvm
- name: run tests
uses: reactivecircus/android-emulator-runner@v2.33.0
uses: reactivecircus/android-emulator-runner@v2.34.0
with:
arch: x86_64
api-level: 34
+1
View File
@@ -135,6 +135,7 @@ The Public API is disabled by default to protect the user's privacy, but it can
| [FitTrackee](https://github.com/SamR1/FitTrackee) | yes | n/a | n/a |
| [SportsTracker](https://github.com/ssaring/sportstracker) | yes, [single tracks only](https://github.com/ssaring/sportstracker/issues/260) | no | no |
| [ExifTool](https://exiftool.org) | [yes](https://exiftool.org/forum/index.php?topic=15972.0) | no | no |
| [Wanderer](https://wanderer.to/) | yes | yes | yes |
## Dashboard API (incl. map)
+8 -8
View File
@@ -6,7 +6,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.0'
classpath 'com.android.tools.build:gradle:8.9.2'
}
}
@@ -33,7 +33,7 @@ android {
targetCompatibility JavaVersion.VERSION_17
}
compileSdk = 35
compileSdk = 36
buildFeatures {
viewBinding = true
@@ -46,13 +46,13 @@ android {
defaultConfig {
applicationId 'de.dennisguse.opentracks'
versionCode 6102
versionName "v4.19.0"
versionCode 6124
versionName "v4.19.2"
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
minSdk = 26
targetSdk = 35
targetSdk = 36
testInstrumentationRunner 'de.dennisguse.opentracks.TestRunner'
testInstrumentationRunnerArguments clearPackageData: 'true'
@@ -145,10 +145,10 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.gridlayout:gridlayout:1.1.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
implementation 'androidx.core:core:1.15.0'
implementation 'androidx.core:core:1.16.0'
implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'androidx.mediarouter:mediarouter:1.7.0'
implementation 'androidx.core:core-location-altitude:1.0.0-alpha03'
@@ -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.16.0'
androidTestImplementation 'org.mockito:mockito-android:5.17.0'
androidTestUtil 'androidx.test:orchestrator:1.5.1'
}
@@ -0,0 +1,11 @@
v4.18.0: OpenTracks
Změny:
- Varování o zakázané poloze lze vypnout
Oprava chyby:
- BottomAppBar překrýval obsah
Vývojář:
- Použití zaznamenané pozice namísto polohy systému Android
- Předělány agregátory senzorů
@@ -0,0 +1,4 @@
v4.19.1: OpenTracks
Bugfix:
- Exported GPX files missed one schemaLocation
@@ -0,0 +1,5 @@
v4.19.2: OpenTracks
Bugfix:
- Fix crash due to faulty translations
@@ -0,0 +1,11 @@
v4.18.0: OpenTracks
Athruithe:
- Is féidir rabhadh faoi mhíchumas GPS a dhíchumasú
Ceartúchán Bug:
- Ábhar forluiteach BottomAppBar
Forbróir:
- Úsáid taifead Seasamh in ionad Android suíomh
- Comhbhailitheoirí braite athfhachtóirithe
@@ -0,0 +1,11 @@
v4.18.0: OpenTracks
Wijzigingen:
- GPS uitgeschakeld waarschuwing kan worden uitgeschakeld
Bugfix:
- BottomAppBar overlapte inhoud
Ontwikkelaar:
- Gebruik recordpositie in plaats van Android-locatie
- Gerefactoreerde sensor-aggregators
@@ -0,0 +1,11 @@
v4.18.0: OpenTracks
更改:
- GPS 禁用警告可被禁用
错误修复:
- BottomAppBar 重叠内容
开发相关:
- 使用记录位置代替 Android 位置
- 重构了传感器聚合器
@@ -312,7 +312,7 @@ public class ExportImportTest {
contentProviderUtils.deleteTrack(context, trackId);
// 2. import
KmzTrackImporter importer = new KmzTrackImporter(context, trackImporter);
KMZTrackImporter importer = new KMZTrackImporter(context, trackImporter);
importTrackId = importer.importFile(tmpFileUri).get(0);
// then
@@ -358,7 +358,7 @@ public class ExportImportTest {
// 2. import
InputStream inputStream = context.getContentResolver().openInputStream(tmpFileUri);
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
importTrackId = importer.importFile(inputStream).get(0);
// then
@@ -383,7 +383,7 @@ public class ExportImportTest {
// 2. import
InputStream inputStream = context.getContentResolver().openInputStream(tmpFileUri);
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
importTrackId = importer.importFile(inputStream).get(0);
// then
@@ -503,7 +503,7 @@ public class ExportImportTest {
// 2. import
InputStream inputStream = context.getContentResolver().openInputStream(tmpFileUri);
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
importTrackId = importer.importFile(inputStream).get(0);
// then
@@ -68,7 +68,7 @@ public class GPXTrackImporterTest {
@Test
public void gpx_with_pause_resume() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_gpx_pause_resume);
// when
@@ -132,7 +132,7 @@ public class GPXTrackImporterTest {
@Test
public void gpx_without_speed() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx11_without_speed);
// when
@@ -187,7 +187,7 @@ public class GPXTrackImporterTest {
@Test
public void gpx_speed_no_namespace() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx11_with_speed_no_namespace);
// when
@@ -246,7 +246,7 @@ public class GPXTrackImporterTest {
@Test
public void gpx_legacy_trackpointextension() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_gpx_trackpointextensions_incorrect);
// when
@@ -317,7 +317,7 @@ public class GPXTrackImporterTest {
@Test
public void importExportTest_timezone() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new GPXTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx_timezone);
InputStream inputStreamExpected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx_timezone);
@@ -62,7 +62,7 @@ public class KMLTrackImporterTest {
@Test
public void kml22_order_location_and_when() throws IOException {
// given
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_order_location_and_when);
// when
@@ -118,7 +118,7 @@ public class KMLTrackImporterTest {
@Test
public void kml22_time_decreases() throws IOException {
// given
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_time_decreases);
// when
@@ -159,7 +159,7 @@ public class KMLTrackImporterTest {
@Test
public void kml22_with_statistics_marker() throws IOException {
// given
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_kml22_statistics_marker);
// when
@@ -243,7 +243,7 @@ public class KMLTrackImporterTest {
@Test(expected = ImportParserException.class)
public void kml_without_locations() throws IOException {
// given
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_without_locations);
// when
@@ -254,7 +254,7 @@ public class KMLTrackImporterTest {
@Test(expected = ImportParserException.class)
public void kml_when_locations_different() throws IOException {
// given
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter importer = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_when_locations_different);
// when
+1 -1
View File
@@ -10,7 +10,7 @@ xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
xmlns:cluetrust="http://www.cluetrust.com/Schemas/"
xmlns:pwr="http://www.garmin.com/xmlschemas/PowerExtension/v1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 https://www8.garmin.com/xmlschemas/TrackStatsExtension.xsd http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
<wpt lat="3" lon="14">
<ele>10</ele>
<time>2021-01-07T21:51:59.179+01:15</time>
@@ -15,7 +15,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.io.file.exporter.CSVTrackExporter;
import de.dennisguse.opentracks.io.file.exporter.GPXTrackExporter;
import de.dennisguse.opentracks.io.file.exporter.KMLTrackExporter;
import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter;
import de.dennisguse.opentracks.io.file.exporter.KMZTrackExporter;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
/**
@@ -33,7 +33,7 @@ public enum TrackFileFormat {
@Override
public String getMimeType() {
return MIME_KML;
return "application/vnd.google-earth.kml+xml";
}
public String getExtension() {
@@ -49,12 +49,12 @@ public enum TrackFileFormat {
@Override
public TrackExporter createTrackExporter(@NonNull Context context, @NonNull ContentProviderUtils contentProviderUtils) {
KMLTrackExporter exporter = new KMLTrackExporter(context, contentProviderUtils, exportPhotos);
return new KmzTrackExporter(context, contentProviderUtils, exporter, exportPhotos);
return new KMZTrackExporter(context, contentProviderUtils, exporter, exportPhotos);
}
@Override
public String getMimeType() {
return MIME_KMZ;
return "application/vnd.google-earth.kmz";
}
public String getExtension() {
@@ -74,12 +74,12 @@ public enum TrackFileFormat {
@Override
public TrackExporter createTrackExporter(@NonNull Context context, @NonNull ContentProviderUtils contentProviderUtils) {
KMLTrackExporter exporter = new KMLTrackExporter(context, contentProviderUtils, exportPhotos);
return new KmzTrackExporter(context, contentProviderUtils, exporter, exportPhotos);
return new KMZTrackExporter(context, contentProviderUtils, exporter, exportPhotos);
}
@Override
public String getMimeType() {
return MIME_KMZ;
return KMZ_WITH_TRACKDETAIL_AND_SENSORDATA.getMimeType();
}
public String getExtension() {
@@ -126,17 +126,13 @@ public enum TrackFileFormat {
}
};
private static final String MIME_KMZ = "application/vnd.google-earth.kmz";
private static final String MIME_KML = "application/vnd.google-earth.kml+xml";
private final String preferenceId;
TrackFileFormat(String preferenceId) {
this.preferenceId = preferenceId;
}
public static Map<String, String> toPreferenceIdLabelMap(final Resources resources, final TrackFileFormat ... trackFileFormats) {
public static Map<String, String> toPreferenceIdLabelMap(final Resources resources, final TrackFileFormat... trackFileFormats) {
Map<String, String> preferenceIdLabelMap = new LinkedHashMap<>(trackFileFormats.length);
for (TrackFileFormat trackFileFormat : trackFileFormats) {
String trackFileFormatUpperCase = trackFileFormat.getExtension().toUpperCase(Locale.US); //ASCII upper case
@@ -102,7 +102,6 @@ public class GPXTrackExporter implements TrackExporter {
try {
prepare(outputStream);
writeHeader();
for (Track track : tracks) {
writeMarkers(track);
}
@@ -200,17 +199,17 @@ public class GPXTrackExporter implements TrackExporter {
}
}
public void prepare(OutputStream outputStream) {
private void prepare(OutputStream outputStream) {
this.printWriter = new PrintWriter(outputStream);
}
public void close() {
private void close() {
printWriter.flush();
printWriter = null;
}
public void writeHeader() {
private void writeHeader() {
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printWriter.println("<gpx");
printWriter.println("version=\"1.1\"");
@@ -228,12 +227,12 @@ public class GPXTrackExporter implements TrackExporter {
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd"
+ " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd"
+ " http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd"
+ " http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
+ " http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 https://www8.garmin.com/xmlschemas/TrackStatsExtension.xsd"
+ " http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd"
+ " http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd\">");
}
public void writeFooter() {
private void writeFooter() {
printWriter.println("</gpx>");
}
@@ -253,7 +252,7 @@ public class GPXTrackExporter implements TrackExporter {
}
}
public void writeMarker(ZoneOffset zoneOffset, Marker marker) {
private void writeMarker(ZoneOffset zoneOffset, Marker marker) {
printWriter.println("<wpt " + formatLocation(marker.getLatitude(), marker.getLongitude()) + ">");
if (marker.hasAltitude()) {
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(marker.getAltitude().toM()) + "</ele>");
@@ -265,7 +264,7 @@ public class GPXTrackExporter implements TrackExporter {
printWriter.println("</wpt>");
}
public void writeBeginTrack(Track track) {
private void writeBeginTrack(Track track) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
@@ -297,19 +296,19 @@ public class GPXTrackExporter implements TrackExporter {
printWriter.println("</extensions>");
}
public void writeEndTrack() {
private void writeEndTrack() {
printWriter.println("</trk>");
}
public void writeOpenSegment() {
private void writeOpenSegment() {
printWriter.println("<trkseg>");
}
public void writeCloseSegment() {
private void writeCloseSegment() {
printWriter.println("</trkseg>");
}
public Distance writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint, List<TrackPoint> sensorPoints, Distance trackDistance) {
private Distance writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint, List<TrackPoint> sensorPoints, Distance trackDistance) {
Distance cumulativeDistance;
printWriter.println("<trkpt " + formatLocation(trackPoint.getLatitude(), trackPoint.getLongitude()) + ">");
@@ -107,6 +107,7 @@ public class KMLTrackExporter implements TrackExporter {
this.contentProviderUtils = contentProviderUtils;
}
@Override
public boolean writeTrack(List<Track> tracks, @NonNull OutputStream outputStream) {
try {
prepare(outputStream);
@@ -444,7 +445,7 @@ public class KMLTrackExporter implements TrackExporter {
writeTypeLocalized(marker.getCategory());
if (exportPhotos) {
printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(marker) + "</href></Icon>");
printWriter.println("<Icon><href>" + KMZTrackExporter.buildKmzImageFilePath(marker) + "</href></Icon>");
}
printWriter.print("<ViewVolume>");
@@ -43,12 +43,12 @@ import de.dennisguse.opentracks.util.FileUtils;
*
* @author Jimmy Shih
*/
public class KmzTrackExporter implements TrackExporter {
public class KMZTrackExporter implements TrackExporter {
private static final String KMZ_IMAGES_DIR = "images";
public static final String KMZ_KML_FILE = "doc.kml";
private static final String TAG = KmzTrackExporter.class.getSimpleName();
private static final String TAG = KMZTrackExporter.class.getSimpleName();
private static final int BUFFER_SIZE = 4096;
private final ContentProviderUtils contentProviderUtils;
@@ -57,7 +57,7 @@ public class KmzTrackExporter implements TrackExporter {
private final boolean exportPhotos;
private final Context context;
public KmzTrackExporter(Context context, ContentProviderUtils contentProviderUtils, KMLTrackExporter trackExporter, boolean exportPhotos) {
public KMZTrackExporter(Context context, ContentProviderUtils contentProviderUtils, KMLTrackExporter trackExporter, boolean exportPhotos) {
this.context = context;
this.contentProviderUtils = contentProviderUtils;
this.fileTrackExporter = trackExporter;
@@ -52,9 +52,9 @@ import de.dennisguse.opentracks.util.StringUtils;
*
* @author Jimmy Shih
*/
public class GpxTrackImporter extends DefaultHandler implements XMLImporter.TrackParser {
public class GPXTrackImporter extends DefaultHandler implements XMLImporter.TrackParser {
private static final String TAG = GpxTrackImporter.class.getSimpleName();
private static final String TAG = GPXTrackImporter.class.getSimpleName();
private static final String TAG_DESCRIPTION = "desc";
private static final String TAG_ALTITUDE = "ele";
@@ -123,7 +123,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private final TrackImporter trackImporter;
public GpxTrackImporter(Context context, TrackImporter trackImporter) {
public GPXTrackImporter(Context context, TrackImporter trackImporter) {
this.context = context;
this.trackImporter = trackImporter;
}
@@ -54,17 +54,16 @@ public class ImportService extends JobIntentService {
String fileExtension = FileUtils.getExtension(file);
try {
Distance maxRecordingDistance = PreferencesUtils.getMaxRecordingDistance();
Distance recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval();
boolean preventReimport = PreferencesUtils.getPreventReimportTracks();
TrackImporter trackImporter = new TrackImporter(this, new ContentProviderUtils(this), maxRecordingDistance, preventReimport);
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
trackIds.addAll(new XMLImporter(new GpxTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
trackIds.addAll(new XMLImporter(new GPXTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
} else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
trackIds.addAll(new XMLImporter(new KmlTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
trackIds.addAll(new XMLImporter(new KMLTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
} else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
trackIds.addAll(new KmzTrackImporter(this, trackImporter).importFile(file.getUri()));
trackIds.addAll(new KMZTrackImporter(this, trackImporter).importFile(file.getUri()));
} else {
Log.d(TAG, "Unsupported file format.");
sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, null, file, getString(R.string.import_unsupported_format));
@@ -47,9 +47,9 @@ import de.dennisguse.opentracks.util.StringUtils;
*
* @author Jimmy Shih
*/
public class KmlTrackImporter extends DefaultHandler implements XMLImporter.TrackParser {
public class KMLTrackImporter extends DefaultHandler implements XMLImporter.TrackParser {
private static final String TAG = KmlTrackImporter.class.getSimpleName();
private static final String TAG = KMLTrackImporter.class.getSimpleName();
private static final String MARKER_STYLE = "#" + KMLTrackExporter.MARKER_STYLE;
@@ -128,7 +128,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private final TrackImporter trackImporter;
public KmlTrackImporter(Context context, TrackImporter trackImporter) {
public KMLTrackImporter(Context context, TrackImporter trackImporter) {
this.context = context;
this.trackImporter = trackImporter;
}
@@ -44,9 +44,9 @@ import de.dennisguse.opentracks.util.FileUtils;
*
* @author Jimmy Shih
*/
public class KmzTrackImporter {
public class KMZTrackImporter {
private static final String TAG = KmzTrackImporter.class.getSimpleName();
private static final String TAG = KMZTrackImporter.class.getSimpleName();
private static final String KML_FILE_EXTENSION = ".kml";
@@ -55,7 +55,7 @@ public class KmzTrackImporter {
private final Context context;
private final TrackImporter trackImporter;
public KmzTrackImporter(Context context, TrackImporter trackImporter) {
public KMZTrackImporter(Context context, TrackImporter trackImporter) {
this.context = context;
this.trackImporter = trackImporter;
}
@@ -211,7 +211,7 @@ public class KmzTrackImporter {
}
private List<Track.Id> parseKml(ZipInputStream zipInputStream) throws IOException {
XMLImporter kmlFileTrackImporter = new XMLImporter(new KmlTrackImporter(context, trackImporter));
XMLImporter kmlFileTrackImporter = new XMLImporter(new KMLTrackImporter(context, trackImporter));
InputStream nonClosableInputStream = new FilterInputStream(zipInputStream) {
@Override
@@ -233,7 +233,7 @@ public class TrackImporter {
* @param externalPhotoUrl the file name
*/
private Uri getInternalPhotoUrl(@NonNull Track.Id trackId, @NonNull Uri externalPhotoUrl) {
String importFileName = KmzTrackImporter.importNameForFilename(externalPhotoUrl.toString());
String importFileName = KMZTrackImporter.importNameForFilename(externalPhotoUrl.toString());
File file = MarkerUtils.buildInternalPhotoFile(context, trackId, Uri.parse(importFileName));
if (file != null) {
return FileUtils.getUriForFile(context, file);
@@ -47,7 +47,7 @@ public class XMLImporter {
return parser.getImportTrackIds();
} catch (SAXException | ParserConfigurationException | ParsingException e) {
Log.e(TAG, "Unable to import file", e);
if (parser.getImportTrackIds().size() > 0) {
if (!parser.getImportTrackIds().isEmpty()) {
parser.cleanImport();
}
throw new ImportParserException(e);
@@ -3,24 +3,14 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/export_activity_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/custom_layout_list_title" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="60dp">
android:paddingBottom="?attr/actionBarSize">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/rows_options_layout"
@@ -50,16 +40,16 @@
android:id="@+id/recycler_view_visible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/recycler_view_not_visible" />
app:layout_constraintBottom_toTopOf="@id/recycler_view_not_visible"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_not_visible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@id/recycler_view_visible"
app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/recycler_view_visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,16 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/export_activity_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/custom_layout_list_title" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
android:paddingTop="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:paddingBottom="60dp">
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/custom_layout_list_add_linear_layout"
@@ -18,25 +30,24 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
android:layout_marginBottom="50dp"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/custom_layout_list_input_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
app:errorEnabled="true"
android:layout_margin="16dp">
android:layout_margin="16dp"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/custom_layout_list_edit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences"
android:hint="@string/custom_layout_list_edit_name"
android:imeOptions="actionDone"
android:hint="@string/custom_layout_list_edit_name" />
android:inputType="textCapSentences" />
</com.google.android.material.textfield.TextInputLayout>
@@ -50,9 +61,9 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/custom_layout_list_cancel_button"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.TextButton"
android:text="@android:string/cancel" />
<com.google.android.material.button.MaterialButton
+1 -1
View File
@@ -21,7 +21,6 @@ limitations under the License.
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="90dp"
android:fitsSystemWindows="true">
<com.google.android.material.tabs.TabLayout
@@ -32,6 +31,7 @@ limitations under the License.
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/track_detail_activity_view_pager"
android:layout_width="match_parent"
android:paddingBottom="?attr/actionBarSize"
android:layout_height="0dp"
android:layout_weight="1" />
+1 -1
View File
@@ -9,7 +9,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="90dp"
android:fitsSystemWindows="true">
<com.google.android.material.tabs.TabLayout
@@ -20,6 +19,7 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/track_recording_coordinator_layout"
android:layout_width="match_parent"
android:paddingBottom="?attr/actionBarSize"
android:layout_height="0dp"
android:layout_weight="1">
+1 -1
View File
@@ -637,7 +637,7 @@ Meldet das GPS-Gerät ungenaue Daten (z.B. Standort, Geschwindigkeit, Höhe), ka
<string name="settings_announcements_unit">Distanz/Geschwindigkeits Einheit</string>
<string name="power_x_watt">Leistung {x, plural, =1 {1 Watt} other {# Watt} }</string>
<string name="power">Leistung</string>
<string name="voiceDistance">{n, plural, =1 {1 } anderes {{n,number,#.0}} }</string>
<string name="voiceDistance">{n, plural, =1 {1 } other {{n,number,#.0}} }</string>
<string name="settings_recording_min_sampling_interval_title">Abtastzeitintervall</string>
<string name="voiceIdle">Untätig werden.</string>
<string name="voice_announce_lap_power_key">StimmeAnkündigungLapPower</string>
+3 -3
View File
@@ -657,11 +657,11 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
<string name="permission_recording_failed">OpenTracks a besoin de la permission d\'accéder à votre localisation ainsi qu\'aux appareils à proximité.</string>
<string name="create_marker_error">Impossible de créer un marqueur. Veuillez réessayer.</string>
<string name="power">Puissance</string>
<string name="power_x_watt">Puissance {x, plural, =1 {1 watt} autres {# watt} }</string>
<string name="power_x_watt">Puissance {x, plural, =1 {1 watt} other {# watt} }</string>
<string name="settings_announcements_lap_power">Puissance par tour</string>
<string name="activity_type_kickscooter">trottinette</string>
<string name="voiceSpeed">{n, plural, =1 {1} autres {{n,number,#.0}} }</string>
<string name="voiceDistance">{n, plural, =1 {1 } autres {{n,number,#.0}} }</string>
<string name="voiceSpeed">{n, plural, =1 {1} other {{n,number,#.0}} }</string>
<string name="voiceDistance">{n, plural, =1 {1 } other {{n,number,#.0}} }</string>
<string name="settings_locale_system_default">Paramètres par défaut du système</string>
<string name="settings_locale_title">Langue</string>
<string name="stats_gain_loss">Gain et perte</string>
+12 -12
View File
@@ -507,11 +507,11 @@
<string name="settings_announcements_unit">Aonad faid/luas</string>
<string name="value_internal_sensor">Braiteoir inmheánach</string>
<string name="voiceIdle">Ag éirí díomhaoin.</string>
<string name="voiceSecondsPlural">{n, iolra, =1 {1 soicind} eile {{ n,uimhir} soicind} }</string>
<string name="voiceSpeedKilometersPerHourPlural">{n, iolra, =1 {1 chiliméadar in aghaidh na huaire} eile {{ n,uimhir, #.0} ciliméadar san uair} }</string>
<string name="voiceSpeedMKnotsPlural">{n, iolra, =1 {1 snaidhm} eile {{ n,uimhir, #.0} snaidhm} }</string>
<string name="voiceDistanceNauticalMilesPlural">{n, iolra, =1 {1 mhuirmhíle} eile {{ n,uimhir, #.0} muirmhíle} }</string>
<string name="voiceDistance">{n, iolra, =1 {1 } eile {{ n,uimhir, #.0}} }</string>
<string name="voiceSecondsPlural">{n, plural, =1 {1 soicind} other {{ n,number} soicind} }</string>
<string name="voiceSpeedKilometersPerHourPlural">{n, plural, =1 {1 chiliméadar in aghaidh na huaire} other {{ n,number, #.0} ciliméadar san uair} }</string>
<string name="voiceSpeedMKnotsPlural">{n, plural, =1 {1 snaidhm} other {{ n,number, #.0} snaidhm} }</string>
<string name="voiceDistanceNauticalMilesPlural">{n, plural, =1 {1 mhuirmhíle} other {{ n,number, #.0} muirmhíle} }</string>
<string name="voiceDistance">{n, plural, =1 {1 } other {{ n,number, #.0}} }</string>
<string name="settings_recording_min_sampling_interval_title">Eatramh ama samplála</string>
<string name="sensor_state_cadence_unit">rpm</string>
<string name="sensor_state_heart_rate_unit">bpm</string>
@@ -527,20 +527,20 @@
<string name="settings_api_summary">Cianrialú agus staitisticí API le haghaidh aipeanna eile</string>
<string name="create_marker_error">Ní féidir marcóir a chruthú. Déan iarracht arís.</string>
<string name="sensor_state_power_unit">W</string>
<string name="voiceMinutesPlural">{n, iolra, =1 {1 nóiméad} eile {{ n,uimhir} nóiméad} }</string>
<string name="voiceDistanceKilometersPlural">{n, iolra, =1 {1 chiliméadar} eile {{ n,uimhir, #.0} ciliméadar} }</string>
<string name="voiceMinutesPlural">{n, plural, =1 {1 nóiméad} other {{ n,number} nóiméad} }</string>
<string name="voiceDistanceKilometersPlural">{n, plural, =1 {1 chiliméadar} other {{ n,number, #.0} ciliméadar} }</string>
<string name="sensor_state_power_max">Cumhacht Max</string>
<string name="bluetooth_sensor_summary">%1$s (%2$s)</string>
<string name="voiceHoursPlural">{n, iolra, =1 {1 uair} eile {{ n,uimhir} uair an chloig} }</string>
<string name="voiceDistanceMilesPlural">{n, iolra, =1 {1 mhíle} eile {{ n,uimhir, #.0} míle} }</string>
<string name="voiceHoursPlural">{n, plural, =1 {1 uair} other {{ n,number} uair an chloig} }</string>
<string name="voiceDistanceMilesPlural">{n, plural, =1 {1 mhíle} other {{ n,number, #.0} míle} }</string>
<string name="no_compatible_camera_installed">Níl feidhmchlár ceamara comhoiriúnach suiteáilte</string>
<string name="voiceSpeedMilesPerHourPlural">{n, iolra, =1 {1 mhíle san uair} eile {{ n,uimhir, #.0} míle san uair} }</string>
<string name="voiceSpeed">{n, iolra, =1 {1} eile {{ n,uimhir, #.0}} }</string>
<string name="voiceSpeedMilesPerHourPlural">{n, plural, =1 {1 mhíle san uair} other {{ n,number, #.0} míle san uair} }</string>
<string name="voiceSpeed">{n, plural, =1 {1} other {{ n,number, #.0}} }</string>
<string name="voice_on_device_speaker_title">Úsáid cainteoir an ghléis</string>
<string name="no_compatible_gallery_installed">Níl feidhmchlár gailearaí íomhá comhoiriúnach suiteáilte</string>
<string name="settings_recording_location_distance_summary">%1$s idir suíomhanna taifeadta</string>
<string name="settings_announcements_lap_power">Cumhacht glúine</string>
<string name="power_x_watt">Cumhacht {x, iolra, = 1 {1 vata} eile {# vata} }</string>
<string name="power_x_watt">Cumhacht {x, plural, = 1 {1 vata} other {# vata} }</string>
<string name="empty">" "</string>
<string name="settings_locale_system_default">Réamhshocrú córais</string>
<string name="settings_locale_title">Teanga</string>
+12 -12
View File
@@ -65,7 +65,7 @@
<string name="settings_recording_location_distance_summary">பதிவுசெய்யப்பட்ட இடங்களுக்கு இடையில் %1$s</string>
<string name="voice_announce_lap_power_key">VoiceAnnouncelappower</string>
<string name="settings_announcements_lap_power">மடியில் ஆற்றல்</string>
<string name="power_x_watt">ஆற்றல் {x, பன்மை, = 1 {1 watt} பிற {# வாட்ச்}}</string>
<string name="power_x_watt">ஆற்றல் {x, plural, = 1 {1 watt} other {# வாட்ச்}}</string>
<string name="power">விசை</string>
<string name="help_feature_content">* சி.பி.எச் தடங்களை உருவாக்கவும்\n * இதய துடிப்பு சென்சார் பயன்படுத்தவும் (புளூடூத் லு மட்டும்)\n * குரல் அறிவிப்புகள் (நேரம் அல்லது தூரத்தின் அடிப்படையில்)\n * குறிப்பான்களை உருவாக்கு (படங்கள் உள்ளிட்டவை)\n * முற்றிலும் ஆஃப்லைனில் வேலை செய்கிறது\n * வரைபடத்தில் தடங்களைக் காண்பி (கீழே காண்க)</string>
<string name="help_track_map_title">வரைபடத்தில் ஒரு பாதையை எவ்வாறு காண்பிப்பது?</string>
@@ -411,13 +411,13 @@
<string name="value_smallest_recommended">சிறியது (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_int_seconds">%1$d கள் (பரிந்துரைக்கப்படுகிறது)</string>
<string name="voiceIdle">சும்மா ஆக.</string>
<string name="voiceHoursPlural">{n, பன்மை, = 1 {1 hour} பிற {{n, எண்} மணிநேரம்}}</string>
<string name="voiceMinutesPlural">{n, பன்மை, = 1 {1 minute} பிற {{n, எண்} நிமிடங்கள்}}</string>
<string name="voiceSecondsPlural">{n, பன்மை, = 1 {1 second} பிற {{n, எண்} விநாடிகள்}}</string>
<string name="voiceSpeedKilometersPerHourPlural">{n, பன்மை, = 1 {1 kilometer per hour} பிற {{n, எண்,#. 0} ஒரு மணி நேரத்திற்கு கிலோமீட்டர்}}</string>
<string name="voiceSpeedMKnotsPlural">{n, பன்மை, = 1 {1 knot} பிற {{n, எண்,#. 0} முடிச்சுகள்}}</string>
<string name="voiceSpeedMilesPerHourPlural">{n, பன்மை, = 1 {1 mile per hour} பிற {{n, எண்,#. 0} ஒரு மணி நேரத்திற்கு மைல்கள்}}</string>
<string name="voiceSpeed">{n, பன்மை, = 1 {1} பிற {{n, எண்,#. 0}}}</string>
<string name="voiceHoursPlural">{n, plural, = 1 {1 hour} other {{n,number} மணிநேரம்}}</string>
<string name="voiceMinutesPlural">{n, plural, = 1 {1 minute} other {{n,number} நிமிடங்கள்}}</string>
<string name="voiceSecondsPlural">{n, plural, = 1 {1 second} other {{n,number} விநாடிகள்}}</string>
<string name="voiceSpeedKilometersPerHourPlural">{n, plural, = 1 {1 kilometer per hour} other {{n,number,#. 0} ஒரு மணி நேரத்திற்கு கிலோமீட்டர்}}</string>
<string name="voiceSpeedMKnotsPlural">{n, plural, = 1 {1 knot} other {{n,number,#. 0} முடிச்சுகள்}}</string>
<string name="voiceSpeedMilesPerHourPlural">{n, plural, = 1 {1 mile per hour} other {{n,number,#. 0} ஒரு மணி நேரத்திற்கு மைல்கள்}}</string>
<string name="voiceSpeed">{n, plural, = 1 {1} other {{n,number,#. 0}}}</string>
<string name="voice_on_device_speaker_title">சாதனத்தின் ச்பீக்கரைப் பயன்படுத்தவும்</string>
<string name="voice_per_kilometer">ஒரு கிலோமீட்டருக்கு</string>
<string name="voice_per_nautical_mile">ஒரு கடல் மைலுக்கு</string>
@@ -426,10 +426,10 @@
<string name="lap_speed">மடியில் விரைவு</string>
<string name="speed">சராசரி நகரும் விரைவு</string>
<string name="total_distance">மொத்த தூரம்</string>
<string name="voiceDistanceKilometersPlural">{n, பன்மை, = 1 {1 kilometer} பிற {{n, எண்,#. 0} கிலோமீட்டர்}}</string>
<string name="voiceDistanceMilesPlural">{n, பன்மை, = 1 {1 mile} பிற {{n, எண்,#. 0} மைல்கள்}}</string>
<string name="voiceDistanceNauticalMilesPlural">{n, பன்மை, = 1 {1 nautical mile} பிற {{n, எண்,#. 0} கடல் மைல்கள்}}</string>
<string name="voiceDistance">{n, பன்மை, = 1 {1 } பிற {{n, எண்,#. 0}}}</string>
<string name="voiceDistanceKilometersPlural">{n, plural, = 1 {1 kilometer} other {{n,number,#. 0} கிலோமீட்டர்}}</string>
<string name="voiceDistanceMilesPlural">{n, plural, = 1 {1 mile} other {{n,number,#. 0} மைல்கள்}}</string>
<string name="voiceDistanceNauticalMilesPlural">{n, plural, = 1 {1 nautical mile} other {{n,number,#. 0} கடல் மைல்கள்}}</string>
<string name="voiceDistance">{n, plural, = 1 {1 } other {{n,number,#. 0}}}</string>
<string name="average_heart_rate">சராசரி இதய துடிப்பு</string>
<string name="current_heart_rate">தற்போதைய இதய துடிப்பு</string>
<string name="lap_heart_rate">மடியில் இதய துடிப்பு</string>