Compare commits

..

116 Commits

Author SHA1 Message Date
Dennis Guse 5746a41905 Release: v4.23.1 2025-10-30 07:48:12 +01:00
Dennis Guse 361ae909e7 Bugfix: post-recording workout crashes.
Fixes #2180.

Introduced in 02a77e5ce7
2025-10-29 22:14:46 +01:00
Dennis Guse 4b59660ea1 Revert "Allow adding newly developed UI Components to existing custom layouts."
This reverts commit daa4689f44.
2025-10-29 22:14:12 +01:00
SomeTr cabf5d238e Translated using Weblate (Ukrainian)
Currently translated at 94.6% (514 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/uk/
2025-10-28 17:35:25 +01:00
Outbreak2096 9c902b89ed Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (543 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/zh_Hans/
2025-10-28 17:35:25 +01:00
Claudinux c31b8a5802 Translated using Weblate (Italian)
Currently translated at 100.0% (543 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/it/
2025-10-28 17:35:25 +01:00
SomeTr 901c548d13 Translated using Weblate (Ukrainian)
Currently translated at 94.4% (513 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/uk/
2025-10-28 17:35:25 +01:00
SomeTr b77de1e10d Translated using Weblate (Ukrainian)
Currently translated at 94.2% (512 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/uk/
2025-10-28 17:35:25 +01:00
SomeTr b8c7fba7d8 Translated using Weblate (Ukrainian)
Currently translated at 94.2% (512 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/uk/
2025-10-28 17:35:25 +01:00
ghose 466719fbc8 Translated using Weblate (Galician)
Currently translated at 100.0% (543 of 543 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/gl/
2025-10-28 17:35:25 +01:00
ghose 4f0ab71503 Translated using Weblate (Galician)
Currently translated at 100.0% (541 of 541 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/gl/
2025-10-28 17:35:25 +01:00
Jeff Shelley daa4689f44 Allow adding newly developed UI Components to existing custom layouts.
Fixes #2176.
2025-10-28 09:51:51 -05:00
Jeff Shelley 023a5aa221 added new UI component which shows elapsed segment time 2025-10-28 09:51:29 -05:00
Peter Storch 832005565a run forgejo actions on pull requests from forks (#2183)
Reviewed-on: https://codeberg.org/OpenTracksApp/OpenTracks/pulls/2183
Co-authored-by: Peter Storch <peter.storch@tuta.io>
Co-committed-by: Peter Storch <peter.storch@tuta.io>
2025-10-27 20:58:18 +01:00
Dennis Guse 9af8b0d353 Cleanup. 2025-10-24 22:26:08 +02:00
Dennis Guse 57c0750980 Release: v4.23.0 2025-10-24 10:23:14 +02:00
Dennis Guse 8e36ee2e7d Cleanup: TrackRecordingServiceNotificationManager uses RecordingData. 2025-10-24 10:19:43 +02:00
Dennis Guse ec2e527fd1 Cleanup. 2025-10-24 10:04:04 +02:00
Dennis Guse d968e5d0c1 Notification opens recording UI.
Features was removed as it broke occasionally and re-implemented after refactoring.

Fixes #1156.
2025-10-22 23:25:55 +02:00
Dennis Guse 4257f21cae Fixed tests.
Missed in1fa76301e23bf709402c19838efea597e7e38ca7
2025-10-22 23:24:13 +02:00
Dennis Guse 26e7059af2 Cleanup. 2025-10-22 22:49:20 +02:00
Jeff Shelley 94595f2a1f Added support for average pace of the current segment 2025-10-21 19:34:19 -05:00
Dennis Guse 1fa76301e2 Cleanup: TrackShareSummaryGenerator (was DescriptionGenerator) now only produces plaintext (HTML was not used anymore). 2025-10-20 09:15:39 +02:00
Dennis Guse ce2c608cc9 Cleanup: TrackStatistics has altitudeExtremities or not. 2025-10-19 22:27:11 +02:00
Dennis Guse 916f26dfda Merge pull request 'Cleanup' (#2173) from cleanup into main
Reviewed-on: https://codeberg.org/OpenTracksApp/OpenTracks/pulls/2173
2025-10-19 18:43:38 +02:00
Dennis Guse a108edc125 Bump androidx.work:work-runtime from 2.10.2 to 2.10.5 2025-10-19 18:28:13 +02:00
Dennis Guse 1a1a8a851b Cleanup: use Stream.toList()
Replaces Stream.collect(Collection.toList() | Collectors.toCollection()).
2025-10-19 18:26:49 +02:00
Dennis Guse ddd1efeb58 Cleanup: use .isEmpty() (except for CharSequence and StringBuilder as it requires SDK33). 2025-10-19 18:26:48 +02:00
Dennis Guse 6c30dd8509 Lists should show vertical scrolling indicator (was lost by switching to RecyclerView). 2025-10-19 17:59:47 +02:00
Dennis Guse 21fe59f32c Cleanup: SDK_INT is always >= Android O. 2025-10-19 17:48:23 +02:00
Dennis Guse f79b2b51c8 Cleanup: use correct order for assert in tests. 2025-10-18 21:48:45 +02:00
Dennis Guse b16e9ad964 Cleanup: UintUtilsTest was only partly executed. 2025-10-18 21:41:46 +02:00
Dennis Guse 65f8ba16b3 Cleanup: RecyclerViewSwipeDeleteCallback.onChildDraw() should only call super once. 2025-10-18 21:28:49 +02:00
Dennis Guse 9b48993cd0 Cleanup. 2025-10-18 21:27:31 +02:00
Dennis Guse 54cec3e821 Cleanup: limit method visibility. 2025-10-18 21:10:26 +02:00
Dennis Guse daeb972c8a Cleanup: simplify stream by using List operations (desugar). 2025-10-18 21:10:26 +02:00
Dennis Guse 73872e8926 Cleanup. 2025-10-18 21:09:21 +02:00
Dennis Guse c15fa21a56 Cleanup: use viewHolder.getAbsoluteAdapterPosition(). 2025-10-18 09:40:56 +02:00
Dennis Guse e9d1080e5d Cleanup: SpeedFormatter doesn't support decimal places. 2025-10-18 09:40:54 +02:00
Claudinux d0b3f45151 Translated using Weblate (Italian)
Currently translated at 4.0% (7 of 172 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://translate.codeberg.org/projects/opentracks/app-store-metadata-files/it/
2025-10-16 21:50:25 +02:00
happylocalisation 32b0b02d28 Added translation using Weblate (English (Middle)) 2025-10-16 21:50:25 +02:00
Dennis Guse d6617f61b7 Cleanup: use PreferenceUtils.isKey(List). 2025-10-15 18:10:35 +02:00
Dennis Guse b5180f235f Cleanup: StatisticsUtils were unused. 2025-10-15 18:10:15 +02:00
Dennis Guse e879eedbd6 Migrate ImportService to WorkManager.
Part of #1315.
2025-10-15 17:25:48 +02:00
Dennis Guse c7ca6800f7 Cleanup: ImportActivity. 2025-10-15 09:02:49 +02:00
Dennis Guse fed884a6ce ExportActivity inherits AbstractActivity. 2025-10-15 08:40:19 +02:00
Dennis Guse 02a77e5ce7 Migrate ExportService to WorkManager.
Part of #1315.
2025-10-14 22:45:00 +02:00
Dennis Guse 6f97399aeb Migrate TrackDeletionService to WorkManager.
Part of #1315.
2025-10-14 19:13:10 +02:00
pstorch 1c4f0e67ab Merge pull request 'use forgejo runner with simple unit tests' (#2159) from connected_check into main
Reviewed-on: https://codeberg.org/OpenTracksApp/OpenTracks/pulls/2159
2025-10-13 11:27:17 +02:00
Peter Storch ebed386d96 use forgejo runners with unit tests 2025-10-12 17:39:35 +02:00
Dennis Guse e44f63feb7 Merge remote-tracking branch 'weblate/main' 2025-09-25 19:08:49 +02:00
Dennis Guse 34c5a3ab97 Release: v4.22.2 2025-09-25 18:59:19 +02:00
Dennis Guse eac47db058 Bump material from 1.12.0 to 1.13.0 2025-09-25 18:58:13 +02:00
SomeTr e72d2a750c Translated using Weblate (Ukrainian)
Currently translated at 93.5% (507 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/uk/
2025-09-22 10:09:12 +00:00
Rob Herremans f54856c3f1 Fix for time and unit announcements (#2166)
Bugfix: time and unit announcement where not configurable correctly.

Fixes #2165.

Reviewed-on: https://codeberg.org/OpenTracksApp/OpenTracks/pulls/2166
Co-authored-by: Rob Herremans <dev@robherremans.nl>
Co-committed-by: Rob Herremans <dev@robherremans.nl>
2025-09-16 20:13:15 +02:00
Claudinux 81f6bbe955 Translated using Weblate (Italian)
Currently translated at 3.5% (6 of 171 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://translate.codeberg.org/projects/opentracks/app-store-metadata-files/it/
2025-09-09 15:09:10 +00:00
mikini c162c0a0ff Translated using Weblate (Danish)
Currently translated at 97.4% (528 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/da/
2025-09-07 08:51:08 +00:00
Outbreak2096 385d05dcdb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/zh_Hans/
2025-09-07 08:51:08 +00:00
Claudinux 308ce4ac07 Translated using Weblate (Italian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/it/
2025-09-07 08:51:08 +00:00
Outbreak2096 f8a0241e1f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.5% (159 of 170 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://translate.codeberg.org/projects/opentracks/app-store-metadata-files/zh_Hans/
2025-09-07 08:51:08 +00:00
Claudinux c74a5c8749 Translated using Weblate (Italian)
Currently translated at 2.9% (5 of 170 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://translate.codeberg.org/projects/opentracks/app-store-metadata-files/it/
2025-09-07 08:51:08 +00:00
Claudinux defdd49a65 Translated using Weblate (Italian)
Currently translated at 97.4% (528 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://translate.codeberg.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/it/
2025-09-07 08:51:08 +00:00
Dennis Guse 46cdae399d Release: v4.22.1 2025-08-31 09:31:26 +02:00
Dennis Guse a19f363b4a Translations are now on translate.codeberg.org
Part of #2154.
2025-08-28 22:14:45 +02:00
Aindriú Mac Giolla Eoin b55b25e00d Translated using Weblate (Irish)
Currently translated at 100.0% (170 of 170 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/ga/
2025-08-28 21:55:10 +02:00
Ghost of Sparta d527770a0a Translated using Weblate (Hungarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/hu/
2025-08-28 21:55:10 +02:00
Fjuro fb75b0fa58 Translated using Weblate (Czech)
Currently translated at 100.0% (170 of 170 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/cs/
2025-08-28 21:55:10 +02:00
Dennis Guse 1c986e48f2 Reproducible builds: use OpenJDK-21 (build script only). 2025-08-28 21:55:10 +02:00
Peter Storch 7f666c571e codeberg migration 2025-08-24 20:48:53 +02:00
Dennis Guse 3c23a9f540 Release: v4.22.0 2025-08-24 08:41:30 +02:00
Peter Storch ec08717d01 Before codeberg migration (#2159)
Co-authored-by: Dennis Guse <dennis.guse@alumni.tu-berlin.de>
2025-08-24 08:36:08 +02:00
Dennis Guse 30dc440d43 Merge remote-tracking branch 'weblate/main' 2025-08-24 08:28:18 +02:00
Dennis Guse 919e670f95 Revert "Bump com.android.tools.build:gradle from 8.11.1 to 8.12.0"
This reverts commit dd37526914.
2025-08-24 08:24:48 +02:00
Dennis Guse 8ff95efc65 Revert "Bump com.android.tools.build:gradle from 8.12.0 to 8.12.1"
This reverts commit b3f2db4619.
2025-08-24 08:24:46 +02:00
Yurt Page b2b98210d5 Translated using Weblate (Russian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/ru/
2025-08-19 20:02:17 +00:00
dependabot[bot] b3f2db4619 Bump com.android.tools.build:gradle from 8.12.0 to 8.12.1
Bumps com.android.tools.build:gradle from 8.12.0 to 8.12.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 18:05:06 +02:00
dependabot[bot] caede289d0 Bump org.mockito:mockito-android from 5.18.0 to 5.19.0
Bumps [org.mockito:mockito-android](https://github.com/mockito/mockito) from 5.18.0 to 5.19.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.18.0...v5.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 18:04:56 +02:00
dependabot[bot] 7a09e32261 Bump androidx.core:core from 1.16.0 to 1.17.0
Bumps androidx.core:core from 1.16.0 to 1.17.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-14 07:53:52 +02:00
dependabot[bot] 388f1d0213 Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 18:54:28 +02:00
dependabot[bot] f44d72a51f Bump androidx.test:orchestrator from 1.6.0 to 1.6.1
Bumps androidx.test:orchestrator from 1.6.0 to 1.6.1.

---
updated-dependencies:
- dependency-name: androidx.test:orchestrator
  dependency-version: 1.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 18:54:16 +02:00
mcliquid 5e9b1d1cb7 Translated using Weblate (German)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/de/
2025-08-06 20:01:54 +00:00
Jerry 305c0d2502 Translated using Weblate (Czech)
Currently translated at 99.6% (540 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/cs/
2025-08-02 22:20:54 +00:00
தமிழ்நேரம் 4306634fb2 Translated using Weblate (Tamil)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/ta/
2025-08-02 22:20:54 +00:00
தமிழ்நேரம் 9fded8953d Translated using Weblate (Tamil)
Currently translated at 100.0% (169 of 169 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/ta/
2025-08-02 22:20:53 +00:00
Łukasz Soja a416b4b0e7 Translated using Weblate (Polish)
Currently translated at 90.9% (493 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/pl/
2025-08-02 22:20:52 +00:00
Aindriú Mac Giolla Eoin e795fbf07d Translated using Weblate (Irish)
Currently translated at 100.0% (169 of 169 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/ga/
2025-08-02 22:20:51 +00:00
Fjuro 41401e2f13 Translated using Weblate (Czech)
Currently translated at 100.0% (169 of 169 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/cs/
2025-08-02 22:20:50 +00:00
josé m 848c5a8db8 Translated using Weblate (Galician)
Currently translated at 99.8% (541 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/gl/
2025-08-02 22:20:50 +00:00
Cloud Esp becd65f9f5 Translated using Weblate (French)
Currently translated at 95.3% (517 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/fr/
2025-08-02 22:20:49 +00:00
Patrick Santa Maria ece4470fec Translated using Weblate (Corsican)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/co/
2025-08-02 22:20:48 +00:00
Fjuro de08707000 Translated using Weblate (Czech)
Currently translated at 100.0% (168 of 168 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/cs/
2025-08-02 22:20:48 +00:00
Sketch6580 d7a5bf8231 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/zh_Hans/
2025-08-02 22:20:47 +00:00
Sketch6580 10453e3d4e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/zh_Hans/
2025-08-02 22:20:46 +00:00
Aindriú Mac Giolla Eoin 4d4898e01a Translated using Weblate (Irish)
Currently translated at 100.0% (168 of 168 strings)

Translation: OpenTracks/App store metadata files
Translate-URL: https://hosted.weblate.org/projects/opentracks/app-store-metadata-files/ga/
2025-08-02 22:20:46 +00:00
ovl-1 286fbc9b45 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.2% (527 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/nb_NO/
2025-08-02 22:20:45 +00:00
ovl-1 b1ea89a548 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.2% (527 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/nb_NO/
2025-08-02 22:20:44 +00:00
NiaJ3oE2LM 2e5643aa0d Translated using Weblate (Italian)
Currently translated at 96.3% (522 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/it/
2025-08-02 22:20:44 +00:00
Ghost of Sparta f48e175578 Translated using Weblate (Hungarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/hu/
2025-08-02 22:20:43 +00:00
Ghost of Sparta 252909b133 Translated using Weblate (Hungarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/hu/
2025-08-02 22:20:42 +00:00
Ghost of Sparta 125cafa79d Translated using Weblate (Hungarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/hu/
2025-08-02 22:20:41 +00:00
Milo Ivir d15810f908 Translated using Weblate (Croatian)
Currently translated at 96.4% (523 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/hr/
2025-08-02 22:20:41 +00:00
Aindriú Mac Giolla Eoin a89e25b00c Translated using Weblate (Irish)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/ga/
2025-08-02 22:20:40 +00:00
Aindriú Mac Giolla Eoin f256c25cb6 Translated using Weblate (Irish)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/ga/
2025-08-02 22:20:39 +00:00
Deleted User db75b28d5b Translated using Weblate (Spanish)
Currently translated at 97.2% (527 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/es/
2025-08-02 22:20:39 +00:00
Fjuro 87c4428a86 Translated using Weblate (Czech)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/cs/
2025-08-02 22:20:38 +00:00
Fjuro 8f1eda9726 Translated using Weblate (Czech)
Currently translated at 100.0% (542 of 542 strings)

Translation: OpenTracks/opentracks.src-main-res-values-strings-xml--main
Translate-URL: https://hosted.weblate.org/projects/opentracks/opentracks-src-main-res-values-strings-xml-main/cs/
2025-08-02 22:20:37 +00:00
Dennis Guse dc88007154 Upgrade to Gradlew 9.0.0 2025-08-03 00:20:28 +02:00
Simon851 8f82375fa4 Added Decathlon HRM as a tested HRM device 2025-08-02 23:56:28 +02:00
dependabot[bot] dd37526914 Bump com.android.tools.build:gradle from 8.11.1 to 8.12.0
Bumps com.android.tools.build:gradle from 8.11.1 to 8.12.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-01 04:28:31 +00:00
dependabot[bot] 16d2f080b2 Bump androidx.test:runner from 1.6.2 to 1.7.0
Bumps androidx.test:runner from 1.6.2 to 1.7.0.

---
updated-dependencies:
- dependency-name: androidx.test:runner
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 07:08:42 +02:00
dependabot[bot] 2cce5c56cd Bump androidx.test.espresso:espresso-core from 3.6.1 to 3.7.0
Bumps androidx.test.espresso:espresso-core from 3.6.1 to 3.7.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 07:07:42 +02:00
dependabot[bot] 24be37aea5 Bump androidx.test.ext:junit from 1.2.1 to 1.3.0
Bumps androidx.test.ext:junit from 1.2.1 to 1.3.0.

---
updated-dependencies:
- dependency-name: androidx.test.ext:junit
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 07:07:30 +02:00
dependabot[bot] f1c9f7512b Bump androidx.test:orchestrator from 1.5.1 to 1.6.0
Bumps androidx.test:orchestrator from 1.5.1 to 1.6.0.

---
updated-dependencies:
- dependency-name: androidx.test:orchestrator
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 07:06:35 +02:00
dependabot[bot] 03a200ec4b Bump androidx.test:core from 1.6.1 to 1.7.0
Bumps androidx.test:core from 1.6.1 to 1.7.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 07:06:08 +02:00
Dennis Guse 93eefe5cf2 Bugfix: track list should show description.
Fixes #2127.
2025-07-12 16:50:08 +02:00
Dennis Guse 792e88acaa Revert "Cleanup: remove unused code for track list."
This reverts commit 9b5ef0707e.
2025-07-12 16:42:37 +02:00
195 changed files with 1903 additions and 1901 deletions
+36
View File
@@ -0,0 +1,36 @@
name: Android Test
on:
push:
branches:
- main
pull_request:
jobs:
lint:
name: Android Lint
runs-on: docker
container:
image: 'ubuntu:android-24.04'
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Lint
shell: bash
run: ./gradlew lint
android-check:
runs-on: docker
container:
image: 'ubuntu:android-24.04'
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Test
shell: bash
run: ./gradlew testNightlyDebugUnitTest --stacktrace
-5
View File
@@ -1,5 +0,0 @@
# These are supported funding model platforms
liberapay: OpenTracks
github: [rgmf, pstorch, dennisguse]
custom: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
-10
View File
@@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
-38
View File
@@ -1,38 +0,0 @@
#https://github.com/marketplace/actions/android-emulator-runner
name: Build APK
on:
push
jobs:
apk-build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-tags: true
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
- uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: '17'
- name: Assemble APK
shell: bash
run: |
echo ${NIGHTLY_STORE_FILE} | base64 -d > KEY_NIGHTLY.jks
./gradlew assembleNightlyRelease -Dnightly_store_file=KEY_NIGHTLY.jks -Dnightly_store_password="${NIGHTLY_STORE_PASSWORD}" -Dnightly_key_alias="${NIGHTLY_KEY_ALIAS}" -Dnightly_key_password="${NIGHTLY_STORE_PASSWORD}"
env:
NIGHTLY_STORE_FILE: ${{ secrets.NIGHTLY_STORE_FILE }}
NIGHTLY_STORE_PASSWORD: ${{ secrets.NIGHTLY_STORE_PASSWORD }}
NIGHTLY_KEY_ALIAS: ${{ secrets.NIGHTLY_KEY_ALIAS }}
- name: Archive
if: always()
uses: actions/upload-artifact@v4
with:
name: OpenTracks-APK.apk
path: ./build/outputs/apk/nightly/*.apk
retention-days: 7
-23
View File
@@ -1,23 +0,0 @@
name: Linting
on:
push:
pull_request:
jobs:
analyse:
name: Analyse
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-tags: true
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
- uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: '17'
- run: ./gradlew lint
-43
View File
@@ -1,43 +0,0 @@
#https://github.com/marketplace/actions/android-emulator-runner
name: Test
on:
push:
pull_request:
jobs:
test:
timeout-minutes: 45
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-tags: true
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
- uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: '17'
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: run tests
uses: reactivecircus/android-emulator-runner@v2.34.0
with:
arch: x86_64
api-level: 34
script: ./gradlew connectedCheck
- name: Archive
if: always()
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
path: build/reports/androidTests/
retention-days: 7
+2 -2
View File
@@ -3,7 +3,7 @@
## Testing ## Testing
Just use OpenTracks and tell us what can be improved by opening an Just use OpenTracks and tell us what can be improved by opening an
issue [here](https://github.com/OpenTracksApp/OpenTracks/issues/new/choose). issue [here](https://codeberg.org/OpenTracksApp/OpenTracks/issues/new/choose).
If we broke things (happens now and then), please tell us also. If we broke things (happens now and then), please tell us also.
@@ -16,7 +16,7 @@ Translations are hosted on [hosted.weblate.org](https://hosted.weblate.org/engag
You have a cool idea for a feature that is missing in OpenTracks? You have a cool idea for a feature that is missing in OpenTracks?
And you would like to help by implementing it? And you would like to help by implementing it?
If not, you can just take a look at If not, you can just take a look at
the [issue tracker](https://github.com/OpenTracksApp/OpenTracks/issues). the [issue tracker](https://codeberg.org/OpenTracksApp/OpenTracks/issues).
Advices: Advices:
+5 -5
View File
@@ -40,10 +40,10 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
</tr> </tr>
</table> </table>
Translations are hosted on <a href="https://hosted.weblate.org/engage/opentracks/"> Translations are hosted on <a href="https://translate.codeberg.org/engage/opentracks/">
hosted.weblate.org</a>. translate.codeberg.org/projects/opentracks/</a>.
<a href="https://hosted.weblate.org/engage/opentracks/"> <a href="https://translate.codeberg.org/engage/opentracks/">
<img src="https://hosted.weblate.org/widgets/opentracks/-/horizontal-auto.svg" alt="Translation status" /> <img src="https://translate.codeberg.org/widget/opentracks/opentracks-src-main-res-values-strings-xml-main/horizontal-auto.svg" alt="Translation status" />
</a> </a>
## Screenshots ## Screenshots
@@ -151,7 +151,7 @@ adb shell am start -n "de.dennisguse.opentracks.playstore/de.dennisguse.opentrac
As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live
tracks. tracks.
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which The reference implementation is [OSMDashboard](https://codeberg.org/OpenTracksApp/OSMDashboard), which
presents an OpenStreetMap map (showing the current track, incl. updates). The Dashboard API is also presents an OpenStreetMap map (showing the current track, incl. updates). The Dashboard API is also
used by [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) for displaying live track used by [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) for displaying live track
statistics on supported wearables. statistics on supported wearables.
+1 -1
View File
@@ -31,4 +31,4 @@ By using explicit Intents for the calls and URIs with specific temporary read pe
All required information can be found in `IntentDashboardUtils.java`. All required information can be found in `IntentDashboardUtils.java`.
A _reference implementation_ is the [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard). A _reference implementation_ is the [OSMDashboard](https://codeberg.org/OpenTracksApp/OSMDashboard).
+3 -3
View File
@@ -3,10 +3,10 @@
## Craft new releases ## Craft new releases
1. Execute use `RELEASE.sh`. 1. Execute use `RELEASE.sh`.
2. Push to Github 2. Push to Codeberg
3. Create release on Github (incl. changelog) 3. Create release on Codeberg (incl. changelog)
This actually creates a tag that is later used by F-Droid This actually creates a tag that is later used by F-Droid
4. Pull from Github 4. Pull from Codeberg
5. Build reproducible release and attach to release 5. Build reproducible release and attach to release
6. ... wait until reproducibility is verified by F-Droid 6. ... wait until reproducibility is verified by F-Droid
+2 -1
View File
@@ -14,6 +14,7 @@
* Garmin HRM-Dual (Reference: 010-12883-00) * Garmin HRM-Dual (Reference: 010-12883-00)
* CYCPLUS H1 * CYCPLUS H1
* Mojawa Haptifit Terra - all you have to do is connect the app to device called "HT" * Mojawa Haptifit Terra - all you have to do is connect the app to device called "HT"
* Decathlon HRM Band
## 0x1816: Cycling Cadence and Speed Service ## 0x1816: Cycling Cadence and Speed Service
@@ -68,7 +69,7 @@ We do not support type of movement (i.e., walking vs running).
Sadly, Bluetooth sensors providing _air pressure_ via Environmental Sensing Service seem to be very rare. Sadly, Bluetooth sensors providing _air pressure_ via Environmental Sensing Service seem to be very rare.
* [Flybeeper Pressure Sensor](https://market.flybeeper.com/device/ps1) * [Flybeeper Pressure Sensor](https://market.flybeeper.com/device/ps1)
* NoTrustIssues: https://github.com/OpenTracksApp/NoTrustIssues * NoTrustIssues: https://codeberg.org/OpenTracksApp/NoTrustIssues
An Android app that exposes the internal barometer via Environmental Sensing Service. An Android app that exposes the internal barometer via Environmental Sensing Service.
### Internal: tested Barometric Sensor Smartphones ### Internal: tested Barometric Sensor Smartphones
+1 -1
View File
@@ -48,4 +48,4 @@ read
git add -u git add -u
git commit -m "$COMMIT_MESSAGE" git commit -m "$COMMIT_MESSAGE"
echo -e "Next steps:\n1. Push to Github\n2. Create release on Github: https://github.com/OpenTracksApp/OpenTracks/releases" echo -e "Next steps:\n1. Push to Codeberg\n2. Create release on Codeberg: https://codeberg.org/OpenTracksApp/OpenTracks/releases"
+3 -3
View File
@@ -2,11 +2,11 @@
set -e set -e
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64/
JAVA_VERSION=`java --version` JAVA_VERSION=`java --version`
if [[ $JAVA_VERSION != "openjdk 17."* ]]; then if [[ $JAVA_VERSION != "openjdk 21."* ]]; then
echo "OpenJDK version should be 17.X" echo "OpenJDK version should be 21.X"
exit -1; exit -1;
fi fi
+13 -12
View File
@@ -46,8 +46,8 @@ android {
defaultConfig { defaultConfig {
applicationId 'de.dennisguse.opentracks' applicationId 'de.dennisguse.opentracks'
versionCode 6237 versionCode 6353
versionName "v4.21.1" versionName "v4.23.1"
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\"" buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
@@ -104,7 +104,7 @@ android {
versionNameSuffix 'irreproducible' versionNameSuffix 'irreproducible'
} }
reproducible { reproducible {
// Developer Binaries: https://github.com/OpenTracksApp/OSMDashboard/releases/download/v%v/de.dennisguse.opentracks.playstore_%v.apk // Developer Binaries: https://codeberg.org/OpenTracksApp/OSMDashboard/releases/download/v%v/de.dennisguse.opentracks.playstore_%v.apk
// FDroid: https://f-droid.org/de/packages/de.dennisguse.opentracks.playstore // FDroid: https://f-droid.org/de/packages/de.dennisguse.opentracks.playstore
// PlayStore: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore // PlayStore: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
dimension 'version' dimension 'version'
@@ -146,19 +146,20 @@ dependencies {
implementation 'androidx.preference:preference:1.2.1' implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.documentfile:documentfile:1.1.0' implementation 'androidx.documentfile:documentfile:1.1.0'
implementation 'androidx.gridlayout:gridlayout:1.1.0' implementation 'androidx.gridlayout:gridlayout:1.1.0'
implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.material:material:1.13.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
implementation 'androidx.core:core:1.16.0' implementation 'androidx.core:core:1.17.0'
implementation 'androidx.core:core-splashscreen:1.0.1' implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'androidx.mediarouter:mediarouter:1.8.1' implementation 'androidx.mediarouter:mediarouter:1.8.1'
implementation 'androidx.core:core-location-altitude:1.0.0-alpha03' implementation 'androidx.core:core-location-altitude:1.0.0-alpha03'
implementation 'androidx.work:work-runtime:2.10.5'
androidTestImplementation 'androidx.test:core:1.6.1' androidTestImplementation 'androidx.test:core:1.7.0'
androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test:rules:1.7.0'
androidTestImplementation 'androidx.test:runner:1.6.2' androidTestImplementation 'androidx.test:runner:1.7.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
androidTestImplementation 'org.mockito:mockito-android:5.18.0' androidTestImplementation 'org.mockito:mockito-android:5.19.0'
androidTestUtil 'androidx.test:orchestrator:1.5.1' androidTestUtil 'androidx.test:orchestrator:1.6.1'
} }
@@ -0,0 +1,5 @@
v4.21.0: OpenTracks
Změny:
- Seznam stop podporuje posunutí pro odstranění
- Reimplementovány motivy (pro dynamické barvy a OLED)
@@ -0,0 +1,4 @@
v4.21.1: OpenTracks
Oprava chyby:
- Opraven pád v rozhraní exportu/importu (vznikl ve v4.21.0)
@@ -0,0 +1,4 @@
v4.22.0: OpenTracks
Změny:
- Přesun na https://codeberg.org/OpenTracksApp/OpenTracks
@@ -0,0 +1,4 @@
v4.22.0: OpenTracks
Changes:
- Migration to https://codeberg.org/OpenTracksApp/OpenTracks
@@ -0,0 +1,4 @@
v4.22.1: OpenTracks
Changes:
- First release via Codeberg
@@ -0,0 +1,4 @@
v4.22.2: OpenTracks
Bugfix:
- Voice annoucements setting for time and unit were linked
@@ -0,0 +1,10 @@
v4.23.0: OpenTracks
Changes:
- UI: added average pace of current segment
(currently only available in new layouts)
- Clicking on notification opens actual recording UI
Developer:
- Deprecated JobIntentService replaced with WorkManager
- Use .isEmpty() except for CharSequence and Stream.toList()
@@ -0,0 +1,7 @@
v4.23.1: OpenTracks
Changes:
- New UI component to show elapsed time in the current segment
Bugfix:
- Instant post-workout export crashed (introduced in v4.23.0)
@@ -0,0 +1,8 @@
v4.20.0: OpenTracks
Athruithe:
- Ceadaítear athrú ar fhritháireamh crios ama rianta
- Comhéadan Úsáideora Marcóra Simplithe
Ceartú:
- Imeall-2-imeall: imoibríonn le méarchlár fíorúil
@@ -0,0 +1,5 @@
v4.21.0: OpenTracks
Athruithe:
- Tacaíonn liosta na rianta le svaidhpeáil chun scriosadh
- Téamaí athchurtha i bhfeidhm (do DynamicColor agus OLED)
@@ -0,0 +1,4 @@
v4.21.1: OpenTracks
Ceartú fabht:
- Tuairteáil socraithe ar chomhéadan úsáideora easpórtála/allmhairithe (tugtha isteach i v4.21.0)
@@ -0,0 +1,4 @@
v4.22.0: OpenTracks
Athruithe:
- Aistriú go https://codeberg.org/OpenTracksApp/OpenTracks
@@ -0,0 +1,4 @@
v4.22.0: OpenTracks
Modifiche:
- Migrazione a https://codeberg.org/OpenTracksApp/OpenTracks
@@ -0,0 +1,4 @@
v4.22.1: OpenTracks
Modiciche:
- Primo rilascio da Codeberg
@@ -0,0 +1,4 @@
v4.22.2: OpenTracks
Correzione di errori:
- L'impostazione degli annunci vocali per l'ora e l'unità di misura è stata collegata
@@ -0,0 +1,10 @@
(versionName): OpenTracks
Modifiche:
-
Correzioni di errori:
-
Sviluppatore:
-
@@ -4,7 +4,7 @@ v3.12.0: ஓபன்ட்ராக்ச்
- ஊடலை சென்சார் முகவரிகள் - ஊடலை சென்சார் முகவரிகள்
- இடைவெளிகள்: உயர ஆதாயத்தைக் காட்டு - இடைவெளிகள்: உயர ஆதாயத்தைக் காட்டு
- ஏற்றுமதி: இயல்புநிலை ஏற்றுமதி அடைவு - ஏற்றுமதி: இயல்புநிலை ஏற்றுமதி அடைவு
- ஏற்றுமதி: ஒரு பாதையை முடித்த பிறகு தானியங்கி ஏற்றுமதி - ஏற்றுமதி: ஒரு பாதையை முடித்தபிறகு தானியங்கி ஏற்றுமதி
- கையேடு இறக்குமதி/ஏற்றுமதி: புதிய பயனர் இடைமுகம் - கையேடு இறக்குமதி/ஏற்றுமதி: புதிய பயனர் இடைமுகம்
- கையேடு ஏற்றுமதி: கையேடு ஏற்றுமதியில் மேலெழுத விருப்பம் - கையேடு ஏற்றுமதி: கையேடு ஏற்றுமதியில் மேலெழுத விருப்பம்
@@ -19,4 +19,4 @@ v3.12.0: ஓபன்ட்ராக்ச்
டெவலப்பர்: டெவலப்பர்:
- வியூ பிண்டிங்சைப் பயன்படுத்துங்கள் - வியூ பிண்டிங்சைப் பயன்படுத்துங்கள்
- தரவுத்தளம் வெளிநாட்டு விசையை செயல்படுத்துகிறது மற்றும் அடுக்கு நீக்குதல்களைப் பயன்படுத்துகிறது - தரவுத்தளம் வெளிநாட்டு விசையைச் செயல்படுத்துகிறது மற்றும் அடுக்கு நீக்குதல்களைப் பயன்படுத்துகிறது
@@ -2,19 +2,19 @@ v3.15.0: ஓபன்ட்ராக்ச்
எச்சரிக்கை: எச்சரிக்கை:
இந்த வெளியீடு மாற்ற முடியாத தரவுத்தள மாற்றங்களைப் பயன்படுத்துகிறது. இந்த வெளியீடு மாற்ற முடியாத தரவுத்தள மாற்றங்களைப் பயன்படுத்துகிறது.
KMZ/KML ஏற்றுமதி/இறக்குமதி நடத்தை மாற்றப்படுவதால், (அ) மேம்படுத்துவதற்கு முன் காப்புப்பிரதி எடுக்க பரிந்துரைக்கப்படுகிறது, பின்னர் (ஆ). KMZ/KML ஏற்றுமதி/இறக்குமதி நடத்தை மாற்றப்படுவதால், (அ) மேம்படுத்துவதற்கு முன் காப்புப்பிரதி எடுக்கப் பரிந்துரைக்கப்படுகிறது, பின்னர் (ஆ).
பரிந்துரைக்கப்பட்ட வடிவம்: KMZ. பரிந்துரைக்கப்பட்ட வடிவம்: KMZ.
மாற்றங்களை உடைத்தல்: மாற்றங்களை உடைத்தல்:
- டிராக் பிரிவுகளின் உள் சேமிப்பு மாற்றப்பட்டுள்ளது - டிராக் பிரிவுகளின் உள் சேமிப்பு மாற்றப்பட்டுள்ளது
(பயனர் உருவாக்கிய நிகழ்வுகள் இப்போது இடம் இல்லாமல் டிராக் பாயிண்டுகளாகக் கருதப்படுகின்றன, ஆனால் நேர முத்திரையுடன்) (பயனர் உருவாக்கிய நிகழ்வுகள் இப்போது இடம் இல்லாமல் டிராக் பாயிண்டுகளாகக் கருதப்படுகின்றன, ஆனால் நேர முத்திரையுடன்)
- சி.பி.எச் நேரத்திற்கு பதிலாக சாதன நேரம் சேமிக்கப்படுகிறது - சி.பி.எச் நேரத்திற்கு பதிலாகச் சாதன நேரம் சேமிக்கப்படுகிறது
(இருக்கும் தரவு மாற்றியமைக்கப்படவில்லை) (இருக்கும் தரவு மாற்றியமைக்கப்படவில்லை)
- டாச்போர்டு பநிஇ வி 2 - டாச்போர்டு பநிஇ வி 2
(தயவுசெய்து OSMDashboard 2.10.0 ஐ மேம்படுத்தவும்) (தயவுசெய்து OSMDashboard 2.10.0 ஐ மேம்படுத்தவும்)
மாற்றங்கள்: மாற்றங்கள்:
. - KML/KMZ சரியாக காப்புப் பிரதி எடுக்கவும் மீட்டமைக்கவும் பயன்படுத்தலாம் (புள்ளிவிவரங்கள் உட்பட)
டெவலப்பர்: டெவலப்பர்:
- மறுவேலை செய்யப்பட்ட தட பிரிவு மற்றும் அது சேமிப்பு (முன்னர் இடைநிறுத்தம்/மீண்டும் மார்க்கர்) - மறுவேலை செய்யப்பட்ட தட பிரிவு மற்றும் அது சேமிப்பு (முன்னர் இடைநிறுத்தம்/மீண்டும் மார்க்கர்)
@@ -2,12 +2,12 @@ v3.16.0: ஓபன்ட்ராக்ச்
மாற்றங்கள்: மாற்றங்கள்:
- சைக்கிள் ஓட்டுதல்: பி.எல்.இ வேக சென்சாரிலிருந்து தூரத்தைப் பெறுங்கள் - சைக்கிள் ஓட்டுதல்: பி.எல்.இ வேக சென்சாரிலிருந்து தூரத்தைப் பெறுங்கள்
- பதிவு செய்யும் போது வழங்கப்பட்ட இடைமுகம் மறுவேலை - பதிவு செய்யும்போது வழங்கப்பட்ட இடைமுகம் மறுவேலை
- இடைமுகம் செயல்திறன் மேம்படுத்தல்கள் - இடைமுகம் செயல்திறன் மேம்படுத்தல்கள்
- ஏற்றுமதி செய்யப்பட்ட கோப்பு பெயர்கள்: <முதல் 32bits uuid> _ <டிராக்கின் பெயர்> - ஏற்றுமதி செய்யப்பட்ட கோப்புப் பெயர்கள்: <முதல் 32bits uuid> _ <டிராக்கின் பெயர்>
- பல கோப்புகளை நோக்கம் வழியாக இறக்குமதி செய்யுங்கள் (எ.கா., கேசெட் பிரிட்சிலிருந்து) - பல கோப்புகளை நோக்கம் வழியாக இறக்குமதி செய்யுங்கள் (எ.கா., கேசெட் பிரிட்சிலிருந்து)
- சி.பி.எக்ச்: ஏற்றுமதி ஆற்றல் தரவு - சி.பி.எக்ச்: ஏற்றுமதி ஆற்றல் தரவு
- புதுப்பிக்கப்பட்ட மொழிபெயர்ப்புகள் - புதுப்பிக்கப்பட்ட மொழிபெயர்ப்புகள்
பிழைத்திருத்த: பிழைத்திருத்த:
- குரல் அறிவிப்பு நிமிடங்களை சரியாகப் பயன்படுத்துங்கள் - குரல் அறிவிப்பு நிமிடங்களைச் சரியாகப் பயன்படுத்துங்கள்
@@ -2,16 +2,16 @@ v3.17.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- கயாக்கிங்கிற்கு ஐகானைச் சேர்க்கவும் - கயாக்கிங்கிற்கு ஐகானைச் சேர்க்கவும்
- விளக்கப்படங்கள் காணாமல் போன சென்சார் தரவை சரியாக வரையவும் - விளக்கப்படங்கள் காணாமல் போன சென்சார் தரவைச் சரியாக வரையவும்
- இயல்புநிலை: பதிவு செய்யும் போது ஆயத்தொலைவுகளைக் காட்டு - இயல்புநிலை: பதிவு செய்யும்போது ஆயத்தொலைவுகளைக் காட்டு
பிழைத்திருத்தங்கள்: பிழைத்திருத்தங்கள்:
- சிபிஎக்ச் ச்கீமா சரி செய்யப்பட்டது - சிபிஎக்ச் ச்கீமா சரி செய்யப்பட்டது
- சிபிஎக்ச் உயரத்தை சென்சார் தூரமாக ஏற்றுமதி செய்தது - சிபிஎக்ச் உயரத்தை சென்சார் தூரமாக ஏற்றுமதி செய்தது
- வேகம்/தூர சென்சார் பயன்படுத்தினால் புள்ளிவிவரங்கள் சரியாக கணக்கிடப்படவில்லை - வேகம்/தூர சென்சார் பயன்படுத்தினால் புள்ளிவிவரங்கள் சரியாகக் கணக்கிடப்படவில்லை
டெவலப்பர்: டெவலப்பர்:
- தூரம்/வேக மதிப்பு பொருள்கள் - தூரம்/வேக மதிப்புப் பொருள்கள்
- பகிர்வு முன்னேற்றங்கள் வழியாக தகவல்தொடர்புகளை மாற்றியது - பகிர்வு முன்னேற்றங்கள் வழியாகத் தகவல்தொடர்புகளை மாற்றியது
- நிலையான அல்லாத பணி பைண்டரைப் பயன்படுத்தவும் - நிலையான அல்லாத பணி பைண்டரைப் பயன்படுத்தவும்
- குறியீடு தளத்தில் உயரத்தைப் பயன்படுத்தவும் (உயரத்திற்கு பதிலாக) - குறியீடு தளத்தில் உயரத்தைப் பயன்படுத்தவும் (உயரத்திற்கு பதிலாக)
@@ -1,13 +1,13 @@
v3.18.0: ஓபன்ட்ராக்ச் v3.18.0: ஓபன்ட்ராக்ச்
மாற்றங்கள்: மாற்றங்கள்:
- உயரம் EGM2008 இல் காட்டப்பட்டுள்ளது (WGS84 என சேமிக்கப்படுகிறது/ஏற்றுமதி செய்யப்படுகிறது) - உயரம் EGM2008 இல் காட்டப்பட்டுள்ளது (WGS84 எனச் சேமிக்கப்படுகிறது/ஏற்றுமதி செய்யப்படுகிறது)
பிழைத்திருத்த: பிழைத்திருத்த:
- நிலையான நினைவக கசிவு (V3.17.0 இல் அறிமுகப்படுத்தப்பட்டது) - நிலையான நினைவக கசிவு (V3.17.0 இல் அறிமுகப்படுத்தப்பட்டது)
- விளக்கப்படங்கள்: உயரம் M/ft இல் இருக்க வேண்டும் (V3.17.1 இல் அறிமுகப்படுத்தப்பட்டது) - விளக்கப்படங்கள்: உயரம் M/ft இல் இருக்க வேண்டும் (V3.17.1 இல் அறிமுகப்படுத்தப்பட்டது)
- விளக்கப்படங்கள்: பதிவு சரியாக புதுப்பிக்கப்படவில்லை (V3.17.3 இல் அறிமுகப்படுத்தப்பட்டது) - விளக்கப்படங்கள்: பதிவு சரியாகப் புதுப்பிக்கப்படவில்லை (V3.17.3 இல் அறிமுகப்படுத்தப்பட்டது)
. - TrackDataHub பதிவுசெய்தல் தொலைநிலை இடைவெளியைக் கணக்கில் எடுத்துக்கொள்ளவில்லை (v3.17.2 இல் அறிமுகப்படுத்தப்பட்டது)
டெவலப்பர்: டெவலப்பர்:
- பி.என்.சி க்ரஞ்சிங் முடக்கு (இனப்பெருக்கம் உருவாக்க) - பி.என்.சி க்ரஞ்சிங் முடக்கு (இனப்பெருக்கம் உருவாக்க)
@@ -2,7 +2,7 @@ v3.18.3: ஓபன்ட்ராக்ச்
மாற்றங்கள்: மாற்றங்கள்:
- KML பாகுபடுத்தலுக்கு/GX: KOURS இன் ஆர்டர் தேவையில்லை - KML பாகுபடுத்தலுக்கு/GX: KOURS இன் ஆர்டர் தேவையில்லை
- ட்ராக் இறக்குமதியாளர்: நேர முத்திரை மூலம் இருப்பிடங்களை மறுசீரமைக்கிறது - ட்ராக் இறக்குமதியாளர்: நேர முத்திரைமூலம் இருப்பிடங்களை மறுசீரமைக்கிறது
- ஆண்ட்ராய்டு <8.0.0 (ஏபிஐ 26) க்கான அகற்றப்பட்ட லாஞ்சர் ஐகான்கள் அகற்றப்பட்டன - ஆண்ட்ராய்டு <8.0.0 (ஏபிஐ 26) க்கான அகற்றப்பட்ட லாஞ்சர் ஐகான்கள் அகற்றப்பட்டன
(சற்று வித்தியாசமாகத் தோன்றலாம், ஆனால் இனப்பெருக்கம் செய்யக்கூடிய கட்டமைப்புகளுக்கான சிக்கல்களைத் தவிர்க்கவும்) (சற்று வித்தியாசமாகத் தோன்றலாம், ஆனால் இனப்பெருக்கம் செய்யக்கூடிய கட்டமைப்புகளுக்கான சிக்கல்களைத் தவிர்க்கவும்)
@@ -1,9 +1,9 @@
v3.18.6: Opentracks v3.18.6: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- "வரைபடத்தில் காட்டு"- KMZ க்கு பதிலாக KML வழியாக செயல்பாடு - "வரைபடத்தில் காட்டு"- KMZ க்கு பதிலாக KML வழியாகச் செயல்பாடு
- குரல் அறிவிப்பில் பயன்பாட்டு பெயர் இல்லை - குரல் அறிவிப்பில் பயன்பாட்டு பெயர் இல்லை
- பதிவு செய்யும் போது: ஒவ்வொரு நொடியும் உயர ஆதாயம்/இழப்பு புதுப்பிக்கப்படும் - பதிவு செய்யும்போது: ஒவ்வொரு நொடியும் உயர ஆதாயம்/இழப்பு புதுப்பிக்கப்படும்
- கடை விளக்கங்கள் மொழிபெயர்க்கப்பட்டவை - கடை விளக்கங்கள் மொழிபெயர்க்கப்பட்டவை
பஃபிக்ச்: பஃபிக்ச்:
@@ -2,15 +2,15 @@ v3.19.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- இயங்கும் விரைவு மற்றும் கேடென்ச் (ஆர்.சி.எச்) சென்சார்களுக்கான உதவி செயல்படுத்தப்பட்டது - இயங்கும் விரைவு மற்றும் கேடென்ச் (ஆர்.சி.எச்) சென்சார்களுக்கான உதவி செயல்படுத்தப்பட்டது
- ஒரு பாதையைப் பகிரும்போது: ஒரு பங்கு படம் உருவாக்கப்பட்டது - ஒரு பாதையைப் பகிரும்போது: ஒரு பங்குப் படம் உருவாக்கப்பட்டது
- பதிவைத் தொடங்கும்போது அதிர்வு இல்லை - பதிவைத் தொடங்கும்போது அதிர்வு இல்லை
- பதிவு செய்யும் போது: இடைமுகம் மிக அண்மைக் காலத்தில் பெறப்பட்ட உயரம், விரைவு மற்றும் தாங்கி (சேமிக்கப்படாவிட்டாலும் கூட) காட்டுகிறது - பதிவு செய்யும்போது: இடைமுகம் மிக அண்மைக் காலத்தில் பெறப்பட்ட உயரம், விரைவு மற்றும் தாங்கி (சேமிக்கப்படாவிட்டாலும் கூட) காட்டுகிறது
பிழைத்திருத்த: பிழைத்திருத்த:
- மொத்த கால கணக்கீட்டில் இடைநிறுத்தப்பட்ட காலங்கள் இருக்கக்கூடாது (மறு இறக்குமதி தேவை) - மொத்த கால கணக்கீட்டில் இடைநிறுத்தப்பட்ட காலங்கள் இருக்கக் கூடாது (மறு இறக்குமதி தேவை)
- (மீண்டும்) இருந்தால் தனிப்பயன் சுருக்கங்களைப் பயன்படுத்தவும் - (மீண்டும்) இருந்தால் தனிப்பயன் சுருக்கங்களைப் பயன்படுத்தவும்
டெவலப்பர்: டெவலப்பர்:
- SDK31 மற்றும் AGP7.0.0 க்கு மேம்படுத்தவும் (JDK11 தேவை) - SDK31 மற்றும் AGP7.0.0 க்கு மேம்படுத்தவும் (JDK11 தேவை)
. - டிராக் ரெக்கார்டிங் சேவை: எக்ஸ்டாக்டட் சென்சார் ஃப்யூஷன் (டிராக்பாயிண்ட் கிரியேட்டர்) மற்றும் டிராக்பாயிண்ட் ஸ்டோரேஜ் (டிராக் ரெக்கார்டிங் மேனேஜர்)
- எக்ச்போர்ட்டிம்போர்ட்டெச்ட் இப்போது தீர்மானிக்கும்/ மாறிலி - எக்ச்போர்ட்டிம்போர்ட்டெச்ட் இப்போது தீர்மானிக்கும்/ மாறிலி
@@ -6,6 +6,6 @@ v3.20.2: ஓபன்ட்ராக்ச்
பிழைத்திருத்த: பிழைத்திருத்த:
- ஆண்ட்ராய்டு 12 இல் செயலிழப்பதைத் தவிர்ப்பதற்கு நிலுவைத் தொகைக்கு கொடி_இம் செய்யக்கூடியதாக அமைக்கவும் - ஆண்ட்ராய்டு 12 இல் செயலிழப்பதைத் தவிர்ப்பதற்கு நிலுவைத் தொகைக்கு கொடி_இம் செய்யக்கூடியதாக அமைக்கவும்
- பயனர் பெடலிங் செய்யாதபோது எதற்கும் பதிலாக காடென்ச் சென்சார் 0 ஐ வழங்குகிறது - பயனர் பெடலிங் செய்யாதபோது எதற்கும் பதிலாகக் காடென்ச் சென்சார் 0 ஐ வழங்குகிறது
- வேக சென்சார் நிறுத்தப்படும்போது கடைசி வேகத்திற்கு பதிலாக 0 ஐ வழங்குகிறது - வேக சென்சார் நிறுத்தப்படும்போது கடைசி வேகத்திற்கு பதிலாக 0 ஐ வழங்குகிறது
- சென்சார்களுடன், நகரும் நேரம் நகரும் போது நிறுத்தப்படும் - சென்சார்களுடன், நகரும் நேரம் நகரும்போது நிறுத்தப்படும்
@@ -1,19 +1,19 @@
v3.21.0: Opentracks v3.21.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- பதிவு செய்யும் போது: டிராக் பாயிண்டுகளின் செயலற்ற/செயலற்ற அல்லாத உருவாக்கத்தை அகற்று - பதிவு செய்யும்போது: டிராக் பாயிண்டுகளின் செயலற்ற அல்லாத உருவாக்கத்தை அகற்று
- அமைப்புகள் இப்போது தனி கோப்புறைகளில் உள்ளன - அமைப்புகள் இப்போது தனி கோப்புறைகளில் உள்ளன
. - அறிவிப்பிலிருந்து OpenTracks ஐத் திறந்து (பதிவு செய்யும்போது) மீண்டும் அழுத்தினால் டிராக் பட்டியல் திறக்கும்.
- GPX compatibilty: support <speed> க்கு import - GPX compatibilty: support <speed> க்கு import
பிழைத்திருத்தங்கள்: பிழைத்திருத்தங்கள்:
- உயரம் மற்றும் தூரம் (பி.எல்.இ சென்சாரிலிருந்து): தரவு உண்மையில் சேமிக்கப்பட்டிருந்தால் மட்டுமே கவுண்டர்களை மீட்டமைக்கவும் - உயரம் மற்றும் தூரம் (பி.எல்.இ சென்சாரிலிருந்து): தரவு உண்மையில் சேமிக்கப்பட்டிருந்தால் மட்டுமே கவுண்டர்களை மீட்டமைக்கவும்
- விரைவு இல்லாமல் இறக்குமதி செய்ய, கணினி விரைவு தேவை - விரைவு இல்லாமல் இறக்குமதி செய்ய, கணினி விரைவு தேவை
- ப்ளூ இயங்கும் சென்சார் இணைக்கப்படவில்லை, தற்போது போல புகாரளிக்கக்கூடாது - ப்ளூ இயங்கும் சென்சார் இணைக்கப்படவில்லை, தற்போது போலப் புகாரளிக்கக் கூடாது
- BLE இயங்கும் சென்சார்: பதிவு செய்யும் போது தரவைக் காட்டு - BLE இயங்கும் சென்சார்: பதிவு செய்யும்போது தரவைக் காட்டு
- செயல்பாட்டை மாற்றும்போது செயல்பாட்டு வகை படவுரு புதுப்பிக்கப்படவில்லை - செயல்பாட்டை மாற்றும்போது செயல்பாட்டு வகை படவுரு புதுப்பிக்கப்படவில்லை
டெவலப்பர்: டெவலப்பர்:
- நிலையான குறிப்பு வழியாக பகிரப்பட்டவை - நிலையான குறிப்பு வழியாகப் பகிரப்பட்டவை
- நினைவக தரவுத்தளத்திற்கு எதிராக சோதனைகள் செயல்படுத்தப்படுகின்றன - நினைவக தரவுத்தளத்திற்கு எதிராகச் சோதனைகள் செயல்படுத்தப்படுகின்றன
- ட்ராக் ரெக்கார்டிங்மேனேசர் கடைசி ட்ராக் பாயிண்ட்டை நினைவகத்தில் வைத்திருக்கிறது - ட்ராக் ரெக்கார்டிங்மேனேசர் கடைசி ட்ராக் பாயிண்ட்டை நினைவகத்தில் வைத்திருக்கிறது
@@ -2,10 +2,10 @@ V3.22.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- பயணம் செய்தால் மட்டுமே இடங்கள் சேமிக்கப்படும்> தூர இடைவெளியைப் பதிவுசெய்க - பயணம் செய்தால் மட்டுமே இடங்கள் சேமிக்கப்படும்> தூர இடைவெளியைப் பதிவுசெய்க
(செயலற்ற/செயலற்ற கண்டறிதலில் இருந்து செயல்பாட்டுக்கு மேல் அகற்றப்பட்டது) (செயலற்ற கண்டறிதலிலிருந்து செயல்பாட்டுக்கு மேல் அகற்றப்பட்டது)
- ஒரு கடிகாரத்தைக் காட்ட இடைமுகம் ஐ கட்டமைக்க முடியும் - ஒரு கடிகாரத்தைக் காட்ட இடைமுகம் ஐ கட்டமைக்க முடியும்
- செயலற்ற விரைவு இப்போது கட்டமைக்கப்படுகிறது - செயலற்ற விரைவு இப்போது கட்டமைக்கப்படுகிறது
பிழைத்திருத்த: பிழைத்திருத்த:
- இடைவெளிகள்: லாபம் ஆனால் இழப்பு சேமிக்கப்படாதபோது செயலிழப்பு - இடைவெளிகள்: லாபம் ஆனால் இழப்பு சேமிக்கப்படாதபோது செயலிழப்பு
- பதிவு செய்யும் போது: குரல் அறிவிப்புகளை முடக்கும்போது செயலிழப்பைத் தடுக்கவும் - பதிவு செய்யும்போது: குரல் அறிவிப்புகளை முடக்கும்போது செயலிழப்பைத் தடுக்கவும்
@@ -3,7 +3,7 @@ v3.23.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- இடைமுகம் சுயவிவரங்கள் சேர்க்கப்பட்டன - இடைமுகம் சுயவிவரங்கள் சேர்க்கப்பட்டன
- தேர்ந்தெடுக்கப்பட்ட தடங்களுக்கான ஒருங்கிணைந்த புள்ளிவிவரங்கள் - தேர்ந்தெடுக்கப்பட்ட தடங்களுக்கான ஒருங்கிணைந்த புள்ளிவிவரங்கள்
-நகரும் நேரம் வேலை செய்வதை நிறுத்துவதால் மீண்டும் செயல்படுத்தப்பட்ட செயலற்ற/செயலற்ற டிராக் பாயிண்ட்ச் (V3.22.0 இல் அறிமுகப்படுத்தப்பட்டது) -நகரும் நேரம் வேலை செய்வதை நிறுத்துவதால் மீண்டும் செயல்படுத்தப்பட்ட செயலற்ற டிராக் பாயிண்ட்ச் (V3.22.0 இல் அறிமுகப்படுத்தப்பட்டது)
பிழைத்திருத்தங்கள்: பிழைத்திருத்தங்கள்:
- பி.எல்.இ சென்சார்கள்: துண்டிக்கப்படுவதற்கான தரவை அழிக்கவும் - பி.எல்.இ சென்சார்கள்: துண்டிக்கப்படுவதற்கான தரவை அழிக்கவும்
@@ -3,14 +3,14 @@ v3.24.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- சி.பி.எச் விருப்பமானது (உட்புற பயன்பாட்டிற்கும்): தூரத்தை வழங்கும் பி.எல்.இ சென்சார்களைப் பயன்படுத்தினால் பயன்படுத்தப்பட்டால் - சி.பி.எச் விருப்பமானது (உட்புற பயன்பாட்டிற்கும்): தூரத்தை வழங்கும் பி.எல்.இ சென்சார்களைப் பயன்படுத்தினால் பயன்படுத்தப்பட்டால்
- அமைப்புகள்: சாதனங்களின் BLE வடிகட்டலை முடக்க விருப்பம் - அமைப்புகள்: சாதனங்களின் BLE வடிகட்டலை முடக்க விருப்பம்
- விளக்கப்படங்கள்: உயரம் 0M க்கு பதிலாக குறைந்தபட்ச மதிப்பில் தொடங்குகிறது. - விளக்கப்படங்கள்: உயரம் 0M க்கு பதிலாகக் குறைந்தபட்ச மதிப்பில் தொடங்குகிறது.
- சேமிக்கப்பட்ட நேர மண்டல தகவல்களைக் காண்பிப்பதை இடைமுகம் ஆதரிக்கிறது - சேமிக்கப்பட்ட நேர மண்டல தகவல்களைக் காண்பிப்பதை இடைமுகம் ஆதரிக்கிறது
பிழைத்திருத்த: பிழைத்திருத்த:
- கடிகாரம் சரியான நேரத்தில் பயணித்ததால் விபத்துக்கான மறு சேர்க்கப்பட்ட பணித்தொகுப்பு (V3.23.0 இல் பணித்தொகுப்பு அகற்றப்பட்டது) - கடிகாரம் சரியான நேரத்தில் பயணித்ததால் விபத்துக்கான மறு சேர்க்கப்பட்ட பணித்தொகுப்பு (V3.23.0 இல் பணித்தொகுப்பு அகற்றப்பட்டது)
- பி.எல்.இ சைக்கிள் ஓட்டுதல் சென்சார் (ஆர்.டி.எஃப்.எம்) க்கான தேவையற்ற பணித்தொகுப்பு அகற்றப்பட்டது - பி.எல்.இ சைக்கிள் ஓட்டுதல் சென்சார் (ஆர்.டி.எஃப்.எம்) க்கான தேவையற்ற பணித்தொகுப்பு அகற்றப்பட்டது
- காணாமல் போன தரவை சிபிஎக்ச் இறக்குமதியாளர் சரியாக கையாளவில்லை - காணாமல் போன தரவை சிபிஎக்ச் இறக்குமதியாளர் சரியாகக் கையாளவில்லை
டெவலப்பர்: டெவலப்பர்:
-BLE சென்சார்கள் புல் அடிப்படையிலானதை விட தரவு நிகழ்வு-இயக்கப்படும் என்று தெரிவிக்கின்றன -BLE சென்சார்கள் புல் அடிப்படையிலானதை விடத் தரவு நிகழ்வு-இயக்கப்படும் என்று தெரிவிக்கின்றன
- பதிவு செய்வதற்கான ஒருங்கிணைப்பு சோதனைகளை மறுவேலை செய்து சேர்த்தது - பதிவு செய்வதற்கான ஒருங்கிணைப்பு சோதனைகளை மறுவேலை செய்து சேர்த்தது
@@ -6,7 +6,7 @@ v3.24.1: Opentracks
-பிளே தூர சென்சார்கள்: முந்தைய சி.பி.எச்-இடங்களின் அடிப்படையில் சி.பி.எச்-இடங்களை சேமிக்கவும் -பிளே தூர சென்சார்கள்: முந்தைய சி.பி.எச்-இடங்களின் அடிப்படையில் சி.பி.எச்-இடங்களை சேமிக்கவும்
பிழைத்திருத்த: பிழைத்திருத்த:
- பதிவு செய்யும் போது: விளக்கப்படங்களைத் திறக்கும்போது நிலையான செயலிழப்பு - பதிவு செய்யும்போது: விளக்கப்படங்களைத் திறக்கும்போது நிலையான செயலிழப்பு
- ட்ராக்டாடாஅப் நிறுத்தத்திற்குப் பிறகு செயலாக்கத்தை முடிக்க வேண்டும் () - ட்ராக்டாடாஅப் நிறுத்தத்திற்குப் பிறகு செயலாக்கத்தை முடிக்க வேண்டும் ()
- தடங்களை நீக்கும்போது அரிதான செயலிழப்பைத் தடுக்கவும் - தடங்களை நீக்கும்போது அரிதான செயலிழப்பைத் தடுக்கவும்
@@ -13,5 +13,5 @@ V3.27.0: Opentracks
- தூர இடைவெளியைப் பதிவுசெய்வது; - தூர இடைவெளியைப் பதிவுசெய்வது;
ட்ராக் பாயிண்டுகள் மிக நெருக்கமாக இருந்தபோதிலும் பதிவு செய்யப்பட்டன ட்ராக் பாயிண்டுகள் மிக நெருக்கமாக இருந்தபோதிலும் பதிவு செய்யப்பட்டன
- ச்டாப் ரெக்கார்டிங் (ரேச் நிலை) இல் செயலிழப்பதைத் தடுக்கவும் - ச்டாப் ரெக்கார்டிங் (ரேச் நிலை) இல் செயலிழப்பதைத் தடுக்கவும்
- பல சென்சார்களைப் பயன்படுத்தும் போது செயலிழப்பைத் தடுக்கவும் (ரேச் நிலை) - பல சென்சார்களைப் பயன்படுத்தும்போது செயலிழப்பைத் தடுக்கவும் (ரேச் நிலை)
- அறிவிப்பு வழியாக ஓபன்ட்ராக்சைத் திறக்கும்போது செயலிழப்பைத் தடுக்கவும் - அறிவிப்பு வழியாக ஓபன்ட்ராக்சைத் திறக்கும்போது செயலிழப்பைத் தடுக்கவும்
@@ -2,10 +2,10 @@ v4.0.0: Opentracks
மாற்றங்கள்: மாற்றங்கள்:
- கீழ் பயன்பாட்டு பட்டியுடன் இடைமுகம் மறுசீரமைப்பு. - கீழ் பயன்பாட்டு பட்டியுடன் இடைமுகம் மறுசீரமைப்பு.
- பொது ஏபிஐ: சரியாக செயல்படுத்தப்பட்டது. - பொது ஏபிஐ: சரியாகச் செயல்படுத்தப்பட்டது.
- தூய்மைப்படுத்துதல்: ட்ராக்ஃபைல்ஃபார்மட்டுக்கு வெளிப்படையான விருப்பத்தேர்வுகளைப் பயன்படுத்தவும். - தூய்மைப்படுத்துதல்: ட்ராக்ஃபைல்ஃபார்மட்டுக்கு வெளிப்படையான விருப்பத்தேர்வுகளைப் பயன்படுத்தவும்.
- BLE ஏண்ட்லரில் மேம்பாடுகள். - BLE ஏண்ட்லரில் மேம்பாடுகள்.
- விதிவிலக்கு கையாளுபவரைச் சேர்த்து பிழை செயல்பாட்டைக் காட்டுங்கள், இதனால் பயனர்கள் பிழைகள் பற்றிய அறிக்கைகளை அனுப்ப முடியும். - விதிவிலக்கு கையாளுபவரைச் சேர்த்து பிழை செயல்பாட்டைக் காட்டுங்கள், இதனால் பயனர்கள் பிழைகள்பற்றிய அறிக்கைகளை அனுப்ப முடியும்.
- ஆண்ட்ராய்டு 13: துவக்கி படவுரு, ஒரு கருப்பொருள் ஐகானை வழங்கவும். - ஆண்ட்ராய்டு 13: துவக்கி படவுரு, ஒரு கருப்பொருள் ஐகானை வழங்கவும்.
- டிராக் தலைப்பு மூலதனத்தை வாக்கியங்களுக்கு மாற்றவும். - டிராக் தலைப்பு மூலதனத்தை வாக்கியங்களுக்கு மாற்றவும்.
- மொழிபெயர்ப்புகள் புதுப்பிக்கப்பட்டன. - மொழிபெயர்ப்புகள் புதுப்பிக்கப்பட்டன.
@@ -4,8 +4,8 @@ V4.0.1: Opentracks
- குரல் அறிவிப்புகள் இப்போது கட்டமைக்கப்படுகின்றன - குரல் அறிவிப்புகள் இப்போது கட்டமைக்கப்படுகின்றன
- முழுத்திரை பயன்முறை இப்போது ஆண்ட்ராய்டு இன் வழிசெலுத்தல் பட்டையும் மறைக்கிறது - முழுத்திரை பயன்முறை இப்போது ஆண்ட்ராய்டு இன் வழிசெலுத்தல் பட்டையும் மறைக்கிறது
- பி.எல்.இ சென்சார்களுக்கான இணைப்பு இப்போது வேகமாக இருக்க வேண்டும் - பி.எல்.இ சென்சார்களுக்கான இணைப்பு இப்போது வேகமாக இருக்க வேண்டும்
- பதிவு செய்யும் போது அமைப்புகளை மீட்டமைக்க அனுமதிக்கவும் - பதிவு செய்யும்போது அமைப்புகளை மீட்டமைக்க அனுமதிக்கவும்
- பதிவு செய்யும் போது இறக்குமதி/ஏற்றுமதி அமைப்புகளை மாற்ற அனுமதிக்கவும் - பதிவு செய்யும்போது இறக்குமதி/ஏற்றுமதி அமைப்புகளை மாற்ற அனுமதிக்கவும்
- KML/KMZ: Google இலிருந்து ஏற்ற ஐகான்களைப் பயன்படுத்த வேண்டாம் - KML/KMZ: Google இலிருந்து ஏற்ற ஐகான்களைப் பயன்படுத்த வேண்டாம்
பிழைத்திருத்த: பிழைத்திருத்த:
@@ -6,7 +6,7 @@ V4.5.0: Opentracks
- புதிய அலகு: மீட்டர் கொண்ட மைல்கள் - புதிய அலகு: மீட்டர் கொண்ட மைல்கள்
பிழைத்திருத்த: பிழைத்திருத்த:
- சி.பி.எச் முடக்கப்பட்ட எச்சரிக்கைகள் மீண்டும் மீண்டும் காட்டப்பட்டுள்ளன (#1429) - சி.பி.எச் முடக்கப்பட்ட எச்சரிக்கைகள் மறுநிகழ்வுகள் காட்டப்பட்டுள்ளன (#1429)
டெவலப்பர்: டெவலப்பர்:
- சாவா பதிவுகளைப் பயன்படுத்தவும் - சாவா பதிவுகளைப் பயன்படுத்தவும்
@@ -5,19 +5,19 @@ V4.9.0: Opentracks
இந்த வெளியீடு ஓபன்ட்ராக்ச் நகர்த்துவதையும் நகர்த்தப்படுவதையும் எவ்வாறு தீர்மானிக்கிறது என்பதை மாற்றுகிறது. இந்த வெளியீடு ஓபன்ட்ராக்ச் நகர்த்துவதையும் நகர்த்தப்படுவதையும் எவ்வாறு தீர்மானிக்கிறது என்பதை மாற்றுகிறது.
இப்போது வரை, விரைவு (சி.பி.எச் அல்லது சென்சார்) ஒரு வாசலைப் பயன்படுத்துவதன் மூலம் பயன்படுத்தப்பட்டது (எ.கா., 0.3 மீ/வி க்கும் குறைவாக). இப்போது வரை, விரைவு (சி.பி.எச் அல்லது சென்சார்) ஒரு வாசலைப் பயன்படுத்துவதன் மூலம் பயன்படுத்தப்பட்டது (எ.கா., 0.3 மீ/வி க்கும் குறைவாக).
இருப்பினும், இது மிகவும் சத்தமாக இருக்கலாம். இருப்பினும், இது மிகவும் சத்தமாக இருக்கலாம்.
இனிமேல், ஒரு காலக்கெடு காலம் பயன்படுத்தப்படுகிறது (அதாவது, கடைசி ஃச் விநாடிகளில் குறிப்பிடத்தக்க நிலை மாற்றம் இல்லை). இனிமேல், ஒரு காலக்கெடு காலம் பயன்படுத்தப்படுகிறது (அதாவது, கடைசி ஃச் விநாடிகளில் குறிப்பிடத் தக்க நிலை மாற்றம் இல்லை).
இந்த காலம் பயனர் கட்டமைக்கக்கூடியது. இந்தக் காலம் பயனர் கட்டமைக்கக்கூடியது.
சும்மா ஆகும் நிகழ்வுகள் தரவுத்தள உள்ளிட்டவற்றில் சேமிக்கப்படுகின்றன. ஒரு நேர முத்திரை, எனவே புள்ளிவிவரங்களை மீண்டும் கணக்கிட முடியும். சும்மா ஆகும் நிகழ்வுகள் தரவுத்தள உள்ளிட்டவற்றில் சேமிக்கப்படுகின்றன. ஒரு நேர முத்திரை, எனவே புள்ளிவிவரங்களை மீண்டும் கணக்கிட முடியும்.
இந்த பதிப்பிலிருந்து தரமிறக்குதல் செயல்படுத்தப்படவில்லை. இந்தப் பதிப்பிலிருந்து தரமிறக்குதல் செயல்படுத்தப்படவில்லை.
மேம்படுத்துவதற்கு முன் அனைத்தையும் காப்புப் பிரதி எடுக்கவும். மேம்படுத்துவதற்கு முன் அனைத்தையும் காப்புப் பிரதி எடுக்கவும்.
மாற்றங்கள்: மாற்றங்கள்:
- செயலற்ற கண்டறிதல் வேகத்தை விட "இயக்கம் இல்லை" காலத்தைப் பயன்படுத்துகிறது - செயலற்ற கண்டறிதல் வேகத்தைவிட "இயக்கம் இல்லை" காலத்தைப் பயன்படுத்துகிறது
- ச்கூட்டர் செயல்பாடு சேர்க்கப்பட்டது - ச்கூட்டர் செயல்பாடு சேர்க்கப்பட்டது
பிழைத்திருத்த: பிழைத்திருத்த:
- பதிவு செய்யும் போது, ட்ராக்லிச்ட் அனைத்து தடங்களையும் பதிவாக காட்டியது - பதிவு செய்யும்போது, ட்ராக்லிச்ட் அனைத்து தடங்களையும் பதிவாகக் காட்டியது
டெவலப்பர்: டெவலப்பர்:
- மீண்டும் இயக்கப்பட்ட அறிவிலிமையம் நடவடிக்கை சோதனைகளை இயக்கும் - மீண்டும் இயக்கப்பட்ட அறிவிலிமையம் நடவடிக்கை சோதனைகளை இயக்கும்
@@ -7,5 +7,5 @@ v4.10.1: ஓபன்ட்ராக்ச்
பிழைத்திருத்த: பிழைத்திருத்த:
- பி.எல்.இ சென்சார் மறு இணைப்பு விபத்துக்குள்ளானது (V4.9.6 இல் அறிமுகப்படுத்தப்பட்டது) - பி.எல்.இ சென்சார் மறு இணைப்பு விபத்துக்குள்ளானது (V4.9.6 இல் அறிமுகப்படுத்தப்பட்டது)
- சைக்கிள் ஓட்டுதல் ஆற்றல் செயலாக்கப்படவில்லை (V4.9.6 இல் அறிமுகப்படுத்தப்பட்டது) - சைக்கிள் ஓட்டுதல் ஆற்றல் செயலாக்கப்படவில்லை (V4.9.6 இல் அறிமுகப்படுத்தப்பட்டது)
- சைக்கிள் ஓட்டுதல் மற்றும் தூரம் மீண்டும் மீண்டும் தரவை அனுமதிக்கிறது - சைக்கிள் ஓட்டுதல் மற்றும் தூரம் மறுநிகழ்வு தரவை அனுமதிக்கிறது
- BLE காற்றழுத்தமானி தரவு சரியாக செயலாக்கப்படவில்லை - BLE காற்றழுத்தமானி தரவு சரியாகச் செயலாக்கப்படவில்லை
@@ -2,4 +2,4 @@ v4.11.2: ஓபன்ட்ராக்ச்
பிழைத்திருத்த: பிழைத்திருத்த:
- திரை திரும்பும்போது பதிவு நிறுத்தப்பட்டது (V4.11.1 இல் அறிமுகப்படுத்தப்பட்டது) - திரை திரும்பும்போது பதிவு நிறுத்தப்பட்டது (V4.11.1 இல் அறிமுகப்படுத்தப்பட்டது)
. . (மாற்றியமைத்தல் da3dd29b8e44624a8222caea9067955f252ef5f8)
@@ -1,7 +1,7 @@
v4.13.0: ஓபன்ட்ராக்ச் v4.13.0: ஓபன்ட்ராக்ச்
மாற்றங்கள்: மாற்றங்கள்:
- பொது பநிஇ வழியாக குறிப்பான்களை உருவாக்க முடியும் - பொது பநிஇ வழியாகக் குறிப்பான்களை உருவாக்க முடியும்
இது எந்த இடத்திலும் பதிவுசெய்த பிறகு குறிப்பான்களை உருவாக்க அனுமதிக்கிறது. இது எந்த இடத்திலும் பதிவுசெய்த பிறகு குறிப்பான்களை உருவாக்க அனுமதிக்கிறது.
குறைபாடு: குறிப்பான்கள் இனி வரைபடங்களில் காட்டப்படவில்லை. குறைபாடு: குறிப்பான்கள் இனி வரைபடங்களில் காட்டப்படவில்லை.
குறிப்பு: பதிப்பிற்குப் பிறகு இந்த பநிஇ ஐ ஆதரிக்கிறது: v4.1.0 குறிப்பு: பதிப்பிற்குப் பிறகு இந்த பநிஇ ஐ ஆதரிக்கிறது: v4.1.0
@@ -1,4 +1,4 @@
V4.19.3: Opentracks V4.19.3: Opentracks
பிழைத்திருத்த: பிழைத்திருத்த:
- உயரத்திற்கு காபிம ஏற்றுமதியை சரிசெய்யவும் (1000 மீ. - உயரத்திற்கு காபிம ஏற்றுமதியை சரிசெய்யவும் (1000 மீட்டரில் வெட்டப்பட்டது)
@@ -0,0 +1,5 @@
v4.19.5: OpenTracks
பிழைத்திருத்தம்:
- துவக்கி ஐகான் சில நேரங்களில் மிகச் சிறியதாகக் காட்டப்பட்டது
- உள்ளூர்மயமாக்கப்பட்ட செயல்பாட்டு வகையைப் பயன்படுத்தி விவரப் பக்கத்தில் டிராக் ஐகான்
@@ -0,0 +1,4 @@
v4.19.6: OpenTracks
மாற்றங்கள்:
- Edge-2-edge இப்போது அனைத்து Android பதிப்புகளிலும் வேலை செய்ய வேண்டும்
@@ -0,0 +1,8 @@
v4.20.0: OpenTracks
மாற்றங்கள்:
- டிராக்குகளின் நேர மண்டல ஆஃப்செட்டை மாற்ற அனுமதிக்கவும்
- எளிமைப்படுத்தப்பட்ட மார்க்கர் UI
பிழைத்திருத்தம்:
- எட்ஜ்-2-எட்ஜ்: மெய்நிகர் விசைப்பலகைக்கு எதிர்வினையாற்று
@@ -0,0 +1,5 @@
v4.21.0: OpenTracks
மாற்றங்கள்:
- டிராக் பட்டியல் ஸ்வைப்-டு-டிலீட்டை ஆதரிக்கிறது
- மீண்டும் செயல்படுத்தப்பட்ட தீம்கள் (டைனமிக் கலர் மற்றும் OLED க்கு)
@@ -0,0 +1,4 @@
v4.21.1: OpenTracks
பிழைத்திருத்தம்:
- ஏற்றுமதி/இறக்குமதி UI இல் ஏற்பட்ட செயலிழப்பு சரி செய்யப்பட்டது (v4.21.0 இல் அறிமுகப்படுத்தப்பட்டது)
@@ -1,22 +1,22 @@
一款尊重您的隐私的运动追踪应用。 尊重您隐私的运动追踪伙伴。
健康幸福的生活总少不了各种运动和户外活动。 运动与户外活动能带来快乐、提升技能、增强自信。
使用本应用,您可以保持对您的训练数据的有效追踪,为您的健康助力。 通过跟踪训练数据,珍视您的健康。
本应用可以在您跑步或散步时记录数据,也可以在您骑车时作为一个大屏幕自行车电脑。 记录您的跑步或步行数据,并提供大屏的专用骑行码表。
您可以为路上的有趣位置创建标记,还可以用图片作为标记。 用照片标记沿途有趣的地点。
您的数据会被详尽地记录下来,供您查阅分析。 保留详细记录的统计数据以供分析。
您的数据只会分享给您想要分享给的人。 仅分享您愿意公开的数据。
* 语音播报 * 语音播报。
* 支持蓝牙LE传感器:心率、速度和距离(骑车)、踏频(骑车)和功率计(骑车)。 * 支持蓝牙低功耗传感器:心率、速度和距离(骑行)、踏频(骑行)、功率计(骑行)。
* 海拔增减:通过气压传感器。 * 海拔上升和下降:通过气压传感器。
* EGM2008 海拔显示(平均海平面以上);导出为 WGS84。 * 采用 EGM2008 显示海拔(平均海平面以上);导出为 WGS84。
* 导出路线数据,支持 KMZ(包括照片)、KML 和 GPX 格式。 * 以 KMZ(含照片)、KML 或 GPX 格式导出轨迹数据。
* 不需要联网,不需要额外权限。 * 无需互联网访问或额外权限。
* 深色和浅色主题,跟随系统设置。 * 深色和浅色主题,跟随系统设置。
* 没有广告。 * 无广告。
本应用是开源软件 ‌自由软件/开放源代码
意味着您可以使用、学习、修改和分发本应用的源代码。 意味着您可以使用、研究、修改和分享源代码。
本应用使用 Apache 2.0 协议发布。 采用 Apache 2.0 许可
@@ -1 +1 @@
一款尊重您的隐私的运动追踪应用。 尊重您隐私的运动追踪伙伴。
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
Vendored
+4 -4
View File
@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.
Vendored
+2 -2
View File
@@ -70,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
@@ -47,7 +47,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.content.data.TestDataUtil; import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.content.data.TestSensorDataUtil; import de.dennisguse.opentracks.content.data.TestSensorDataUtil;
@@ -451,7 +450,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertMarker(marker1); contentProviderUtils.insertMarker(marker1);
// Check insert was done. // Check insert was done.
assertEquals(contentProviderUtils.getMarkers(trackId).size(), 1); assertEquals(1, contentProviderUtils.getMarkers(trackId).size());
// Get marker id that needs to delete. // Get marker id that needs to delete.
Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1); Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1);
@@ -478,7 +477,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertMarker(marker1); contentProviderUtils.insertMarker(marker1);
// Check insert was done. // Check insert was done.
assertEquals(contentProviderUtils.getMarkers(trackId).size(), 1); assertEquals(1, contentProviderUtils.getMarkers(trackId).size());
// Get marker id that needs to delete. // Get marker id that needs to delete.
Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1); Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1);
@@ -832,7 +831,7 @@ public class CustomContentProviderUtilsTest {
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId())))
.map(TrackPoint.Id::new).collect(Collectors.toList()); .map(TrackPoint.Id::new).toList();
// when // when
try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackpointIds.get(8))) { try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackpointIds.get(8))) {
@@ -850,7 +849,7 @@ public class CustomContentProviderUtilsTest {
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId())))
.map(TrackPoint.Id::new).collect(Collectors.toList()); .map(TrackPoint.Id::new).toList();
TrackPoint.Id startTrackPointId = trackpointIds.get(0); TrackPoint.Id startTrackPointId = trackpointIds.get(0);
@@ -48,10 +48,8 @@ public class CustomSQLiteOpenHelperTest {
public static Map<String, String> getSQL(SQLiteDatabase db, String type) { public static Map<String, String> getSQL(SQLiteDatabase db, String type) {
HashMap<String, String> sqlMap = new HashMap<>(); HashMap<String, String> sqlMap = new HashMap<>();
try (Cursor cursor = db.query("sqlite_master", new String[]{"name", "SQL"}, "type=?", new String[]{type}, null, null, "name")) { try (Cursor cursor = db.query("sqlite_master", new String[]{"name", "SQL"}, "type=?", new String[]{type}, null, null, "name")) {
if (cursor != null) { while (cursor.moveToNext()) {
while (cursor.moveToNext()) { sqlMap.put(cursor.getString(0), cursor.getString(1));
sqlMap.put(cursor.getString(0), cursor.getString(1));
}
} }
} }
return sqlMap; return sqlMap;
@@ -64,12 +62,10 @@ public class CustomSQLiteOpenHelperTest {
*/ */
private static boolean hasSqlCreate(SQLiteDatabase db, String sqlCreate) { private static boolean hasSqlCreate(SQLiteDatabase db, String sqlCreate) {
try (Cursor cursor = db.rawQuery("SELECT SQL FROM sqlite_master", null)) { try (Cursor cursor = db.rawQuery("SELECT SQL FROM sqlite_master", null)) {
if (cursor != null) { while (cursor.moveToNext()) {
while (cursor.moveToNext()) { String sql = cursor.getString(0);
String sql = cursor.getString(0); if (sqlCreate.equals(sql)) {
if (sqlCreate.equals(sql)) { return true;
return true;
}
} }
} }
} }
@@ -37,9 +37,9 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "_id IN (?)"); assertEquals("_id IN (?)", selection.selection());
assertEquals(selection.selectionArgs().length, 1); assertEquals(1, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "1"); assertEquals("1", selection.selectionArgs()[0]);
} }
@Test @Test
@@ -57,11 +57,11 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "_id IN (?,?,?)"); assertEquals("_id IN (?,?,?)", selection.selection());
assertEquals(selection.selectionArgs().length, 3); assertEquals(3, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "1"); assertEquals("1", selection.selectionArgs()[0]);
assertEquals(selection.selectionArgs()[1], "2"); assertEquals("2", selection.selectionArgs()[1]);
assertEquals(selection.selectionArgs()[2], "3"); assertEquals("3", selection.selectionArgs()[2]);
} }
@Test @Test
@@ -73,9 +73,9 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "category IN (?)"); assertEquals("category IN (?)", selection.selection());
assertEquals(selection.selectionArgs().length, 1); assertEquals(1, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "running"); assertEquals("running", selection.selectionArgs()[0]);
} }
@Test @Test
@@ -91,12 +91,12 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "category IN (?,?,?,?)"); assertEquals("category IN (?,?,?,?)", selection.selection());
assertEquals(selection.selectionArgs().length, 4); assertEquals(4, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "running"); assertEquals("running", selection.selectionArgs()[0]);
assertEquals(selection.selectionArgs()[1], "road biking"); assertEquals("road biking", selection.selectionArgs()[1]);
assertEquals(selection.selectionArgs()[2], "mountain biking"); assertEquals("mountain biking", selection.selectionArgs()[2]);
assertEquals(selection.selectionArgs()[3], "trail walking"); assertEquals("trail walking", selection.selectionArgs()[3]);
} }
@Test @Test
@@ -120,8 +120,8 @@ public class TrackSelectionTest extends TestCase {
assertNull(selectionWrong2.selection()); assertNull(selectionWrong2.selection());
assertNull(selectionWrong2.selectionArgs()); assertNull(selectionWrong2.selectionArgs());
assertEquals(selectionOk.selection(), "starttime BETWEEN ? AND ?"); assertEquals("starttime BETWEEN ? AND ?", selectionOk.selection());
assertEquals(selectionOk.selectionArgs().length, 2); assertEquals(2, selectionOk.selectionArgs().length);
assertEquals(selectionOk.selectionArgs()[0], Long.toString(instant.toEpochMilli())); assertEquals(selectionOk.selectionArgs()[0], Long.toString(instant.toEpochMilli()));
assertEquals(selectionOk.selectionArgs()[1], Long.toString(instant.toEpochMilli() + oneDay)); assertEquals(selectionOk.selectionArgs()[1], Long.toString(instant.toEpochMilli() + oneDay));
} }
@@ -143,13 +143,13 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "_id IN (?,?,?) AND category IN (?,?)"); assertEquals("_id IN (?,?,?) AND category IN (?,?)", selection.selection());
assertEquals(selection.selectionArgs().length, 5); assertEquals(5, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "1"); assertEquals("1", selection.selectionArgs()[0]);
assertEquals(selection.selectionArgs()[1], "2"); assertEquals("2", selection.selectionArgs()[1]);
assertEquals(selection.selectionArgs()[2], "3"); assertEquals("3", selection.selectionArgs()[2]);
assertEquals(selection.selectionArgs()[3], "running"); assertEquals("running", selection.selectionArgs()[3]);
assertEquals(selection.selectionArgs()[4], "road biking"); assertEquals("road biking", selection.selectionArgs()[4]);
} }
@Test @Test
@@ -172,11 +172,11 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "_id IN (?,?,?) AND starttime BETWEEN ? AND ?"); assertEquals("_id IN (?,?,?) AND starttime BETWEEN ? AND ?", selection.selection());
assertEquals(selection.selectionArgs().length, 5); assertEquals(5, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "1"); assertEquals("1", selection.selectionArgs()[0]);
assertEquals(selection.selectionArgs()[1], "2"); assertEquals("2", selection.selectionArgs()[1]);
assertEquals(selection.selectionArgs()[2], "3"); assertEquals("3", selection.selectionArgs()[2]);
assertEquals(selection.selectionArgs()[3], Long.toString(instant.toEpochMilli())); assertEquals(selection.selectionArgs()[3], Long.toString(instant.toEpochMilli()));
assertEquals(selection.selectionArgs()[4], Long.toString(instant.toEpochMilli() + oneDay)); assertEquals(selection.selectionArgs()[4], Long.toString(instant.toEpochMilli() + oneDay));
} }
@@ -196,10 +196,10 @@ public class TrackSelectionTest extends TestCase {
SelectionData selection = filter.buildSelection(); SelectionData selection = filter.buildSelection();
// Then // Then
assertEquals(selection.selection(), "category IN (?,?) AND starttime BETWEEN ? AND ?"); assertEquals("category IN (?,?) AND starttime BETWEEN ? AND ?", selection.selection());
assertEquals(selection.selectionArgs().length, 4); assertEquals(4, selection.selectionArgs().length);
assertEquals(selection.selectionArgs()[0], "running"); assertEquals("running", selection.selectionArgs()[0]);
assertEquals(selection.selectionArgs()[1], "road biking"); assertEquals("road biking", selection.selectionArgs()[1]);
assertEquals(selection.selectionArgs()[2], Long.toString(instant.toEpochMilli())); assertEquals(selection.selectionArgs()[2], Long.toString(instant.toEpochMilli()));
assertEquals(selection.selectionArgs()[3], Long.toString(instant.toEpochMilli() + oneDay)); assertEquals(selection.selectionArgs()[3], Long.toString(instant.toEpochMilli() + oneDay));
} }
@@ -21,7 +21,7 @@ public class DistanceFormatterTest {
@Test @Test
public void testFormatDistance_metric() { public void testFormatDistance_metric() {
DistanceFormatter formatter = DistanceFormatter.Builder() DistanceFormatter formatter = DistanceFormatter.Builder()
.setDecimalCount(2) .setDecimalPlaces(2)
.setUnit(UnitSystem.METRIC) .setUnit(UnitSystem.METRIC)
.build(context); .build(context);
@@ -34,7 +34,7 @@ public class DistanceFormatterTest {
@Test @Test
public void testFormatDistance_imperial() { public void testFormatDistance_imperial() {
DistanceFormatter formatter = DistanceFormatter.Builder() DistanceFormatter formatter = DistanceFormatter.Builder()
.setDecimalCount(2) .setDecimalPlaces(2)
.setUnit(UnitSystem.IMPERIAL_FEET) .setUnit(UnitSystem.IMPERIAL_FEET)
.build(context); .build(context);
@@ -47,7 +47,7 @@ public class DistanceFormatterTest {
@Test @Test
public void testFormatDistance_nautical() { public void testFormatDistance_nautical() {
DistanceFormatter formatter = DistanceFormatter.Builder() DistanceFormatter formatter = DistanceFormatter.Builder()
.setDecimalCount(2) .setDecimalPlaces(2)
.setUnit(UnitSystem.NAUTICAL_IMPERIAL) .setUnit(UnitSystem.NAUTICAL_IMPERIAL)
.build(context); .build(context);
@@ -21,7 +21,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_pace_metric() { public void testGetSpeedParts_pace_metric() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.METRIC) .setUnit(UnitSystem.METRIC)
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(context); .build(context);
@@ -35,7 +34,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_pace_imperial() { public void testGetSpeedParts_pace_imperial() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.IMPERIAL_FEET) .setUnit(UnitSystem.IMPERIAL_FEET)
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(context); .build(context);
@@ -47,7 +45,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_pace_nautical() { public void testGetSpeedParts_pace_nautical() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.NAUTICAL_IMPERIAL) .setUnit(UnitSystem.NAUTICAL_IMPERIAL)
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(context); .build(context);
@@ -59,7 +56,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_speed_metric() { public void testGetSpeedParts_speed_metric() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.METRIC) .setUnit(UnitSystem.METRIC)
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(context); .build(context);
@@ -71,7 +67,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_speed_imperial() { public void testGetSpeedParts_speed_imperial() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.IMPERIAL_FEET) .setUnit(UnitSystem.IMPERIAL_FEET)
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(context); .build(context);
@@ -83,7 +78,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testGetSpeedParts_speed_nautical() { public void testGetSpeedParts_speed_nautical() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.NAUTICAL_IMPERIAL) .setUnit(UnitSystem.NAUTICAL_IMPERIAL)
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(context); .build(context);
@@ -95,7 +89,6 @@ public class SpeedFormatterTest {
@Test @Test
public void testFormatSpeed() { public void testFormatSpeed() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2)
.setUnit(UnitSystem.METRIC) .setUnit(UnitSystem.METRIC)
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(context); .build(context);
@@ -1,50 +1,54 @@
package de.dennisguse.opentracks.sensors; package de.dennisguse.opentracks.sensors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import org.junit.Test; import org.junit.Test;
public class UintUtilsTest { public class UintUtilsTest {
@Test @Test
public void diff() { public void diff_uint16_valid() {
assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT16_MAX)); assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT16_MAX));
assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT16_MAX)); assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT16_MAX));
assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT16_MAX)); assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT16_MAX));
assertEquals(65535, UintUtils.diff(1, 2, UintUtils.UINT16_MAX)); /* unsigned 16 arithmetic is modulo UINT16_MAX + 1, not modulo UINT16_MAX */ assertEquals(65535, UintUtils.diff(1, 2, UintUtils.UINT16_MAX)); /* unsigned 16 arithmetic is modulo UINT16_MAX + 1, not modulo UINT16_MAX */
assertEquals(65530, UintUtils.diff(UintUtils.UINT16_MAX, 5, UintUtils.UINT16_MAX)); assertEquals(65530, UintUtils.diff(UintUtils.UINT16_MAX, 5, UintUtils.UINT16_MAX));
}
@Test
public void diff_uint16_invalid() {
/* Test modulo arithmetic for arguments that are out of range */ /* Test modulo arithmetic for arguments that are out of range */
assertThrows(RuntimeException.class, () -> UintUtils.diff(65537, 1, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(1, 65537, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(65537, 65537, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(-65535, 1, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(1, -65535, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(-65535, -65535, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(-65535, 65537, UintUtils.UINT16_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(65537, -65535, UintUtils.UINT16_MAX));
}
if (false) { /* false means UintUtils.diff() throws if arguments out of range */ @Test
assertEquals(0, UintUtils.diff(65537, 1, UintUtils.UINT16_MAX)); public void diff_uint32() {
assertEquals(0, UintUtils.diff(1, 65537, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(65537, 65537, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(-65535, 1, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(1, -65535, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(-65535, -65535, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(-65535, 65537, UintUtils.UINT16_MAX));
assertEquals(0, UintUtils.diff(65537, -65535, UintUtils.UINT16_MAX));
}
/* The following tests are the above, but for 32-bit unsigned. */
assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT32_MAX)); assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT32_MAX));
assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT32_MAX)); assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT32_MAX));
assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT32_MAX)); assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT32_MAX));
assertEquals(4294967295L, UintUtils.diff(1, 2, UintUtils.UINT32_MAX)); assertEquals(4294967295L, UintUtils.diff(1, 2, UintUtils.UINT32_MAX));
assertEquals(4294967290L, UintUtils.diff(UintUtils.UINT32_MAX, 5, UintUtils.UINT32_MAX)); assertEquals(4294967290L, UintUtils.diff(UintUtils.UINT32_MAX, 5, UintUtils.UINT32_MAX));
}
if (false) { /* false means UintUtils.diff() throws if arguments out of range */ @Test
assertEquals(0, UintUtils.diff(4294967297L, 1, UintUtils.UINT32_MAX)); public void diff_unint32_invalid() {
assertEquals(0, UintUtils.diff(1, 4294967297L, UintUtils.UINT32_MAX)); /* Test modulo arithmetic for arguments that are out of range */
assertEquals(0, UintUtils.diff(4294967297L, 4294967297L, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(4294967297L, 1, UintUtils.UINT32_MAX));
assertEquals(0, UintUtils.diff(-4294967295L, 1, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(1, 4294967297L, UintUtils.UINT32_MAX));
assertEquals(0, UintUtils.diff(1, -4294967295L, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(4294967297L, 4294967297L, UintUtils.UINT32_MAX));
assertEquals(0, UintUtils.diff(-4294967295L, -4294967295L, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(-4294967295L, 1, UintUtils.UINT32_MAX));
assertEquals(0, UintUtils.diff(-4294967295L, 4294967297L, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(1, -4294967295L, UintUtils.UINT32_MAX));
assertEquals(0, UintUtils.diff(65537, -4294967297L, UintUtils.UINT32_MAX)); assertThrows(RuntimeException.class, () -> UintUtils.diff(-4294967295L, -4294967295L, UintUtils.UINT32_MAX));
} assertThrows(RuntimeException.class, () -> UintUtils.diff(-4294967295L, 4294967297L, UintUtils.UINT32_MAX));
assertThrows(RuntimeException.class, () -> UintUtils.diff(65537, -4294967297L, UintUtils.UINT32_MAX));
} }
@Test @Test
@@ -18,6 +18,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatistics;
@@ -51,11 +52,15 @@ public class TrackRecordingServiceNotificationManagerTest {
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder); TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
subject.setUnitSystem(UnitSystem.METRIC); subject.setUnitSystem(UnitSystem.METRIC);
Track track = new Track();
track.setTrackStatistics(trackStatisticsMock);
RecordingData data = new RecordingData(track, trackPointMock, null, null);
// when // when
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(100)); subject.updateTrackPoint(context, data, Distance.of(100));
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(100)); subject.updateTrackPoint(context, data, Distance.of(100));
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(1000)); subject.updateTrackPoint(context, data, Distance.of(1000));
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(100)); subject.updateTrackPoint(context, data, Distance.of(100));
// then // then
verify(notificationCompatBuilder, times(6)).setOnlyAlertOnce(true); verify(notificationCompatBuilder, times(6)).setOnlyAlertOnce(true);
@@ -165,7 +165,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -216,7 +216,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -330,7 +330,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -381,7 +381,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -411,7 +411,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -449,7 +449,7 @@ public class VoiceAnnouncementUtilsTest {
TrackStatistics stats = trackWithStats.second; TrackStatistics stats = trackWithStats.second;
IntervalStatistics.Interval lastInterval; IntervalStatistics.Interval lastInterval;
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
assertEquals(trackPointIterator.getCount(), numberOfPoints); assertEquals(numberOfPoints, trackPointIterator.getCount());
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000)); IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
intervalStatistics.addTrackPoints(trackPointIterator); intervalStatistics.addTrackPoints(trackPointIterator);
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1); lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
@@ -41,7 +41,7 @@ public class PreferencesOpenHelperTest {
// then there should be one layout with old custom layout that has the new CSV value. // then there should be one layout with old custom layout that has the new CSV value.
List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts();
assertNotNull(recordingLayouts); assertNotNull(recordingLayouts);
assertEquals(recordingLayouts.size(), 1); assertEquals(1, recordingLayouts.size());
assertEquals(recordingLayouts.get(0).toCsv(), PreferencesUtils.getCustomLayout().toCsv()); assertEquals(recordingLayouts.get(0).toCsv(), PreferencesUtils.getCustomLayout().toCsv());
} }
@@ -66,7 +66,7 @@ public class PreferencesOpenHelperTest {
// then there should be one layout with old custom layout that has the new CSV value. // then there should be one layout with old custom layout that has the new CSV value.
List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts();
assertNotNull(recordingLayouts); assertNotNull(recordingLayouts);
assertEquals(recordingLayouts.size(), 1); assertEquals(1, recordingLayouts.size());
assertEquals(recordingLayouts.get(0).toCsv(), updatedOldCustomLayoutCsv); assertEquals(recordingLayouts.get(0).toCsv(), updatedOldCustomLayoutCsv);
} }
@@ -90,8 +90,8 @@ public class PreferencesOpenHelperTest {
// then there should be one layout with old custom layout that has the new CSV value. // then there should be one layout with old custom layout that has the new CSV value.
List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts();
assertNotNull(recordingLayouts); assertNotNull(recordingLayouts);
assertEquals(recordingLayouts.size(), 1); assertEquals(1, recordingLayouts.size());
assertEquals(recordingLayouts.get(0).toCsv(), updatedOldCustomLayoutCsv); assertEquals(updatedOldCustomLayoutCsv, recordingLayouts.get(0).toCsv());
} }
@Test @Test
@@ -113,7 +113,7 @@ public class PreferencesOpenHelperTest {
RecordingLayout defaultRecordingLayout = RecordingLayoutIO.fromCsv(PreferencesUtils.buildDefaultLayout(), resources); RecordingLayout defaultRecordingLayout = RecordingLayoutIO.fromCsv(PreferencesUtils.buildDefaultLayout(), resources);
List<RecordingLayout> customRecordingLayout = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> customRecordingLayout = PreferencesUtils.getAllCustomLayouts();
assertEquals(customRecordingLayout.size(), 1); assertEquals(1, customRecordingLayout.size());
assertEquals(defaultRecordingLayout.toCsv(), customRecordingLayout.get(0).toCsv()); assertEquals(defaultRecordingLayout.toCsv(), customRecordingLayout.get(0).toCsv());
} }
} }
@@ -89,8 +89,8 @@ public class PreferencesUtilsTest {
List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> recordingLayouts = PreferencesUtils.getAllCustomLayouts();
// then // then
assertEquals(recordingLayouts.size(), 1); assertEquals(1, recordingLayouts.size());
assertTrue(recordingLayouts.get(0).getFields().size() > 0); assertFalse(recordingLayouts.get(0).getFields().isEmpty());
assertEquals(recordingLayouts.get(0).getName(), context.getString(R.string.stats_custom_layout_default_layout)); assertEquals(recordingLayouts.get(0).getName(), context.getString(R.string.stats_custom_layout_default_layout));
assertTrue(recordingLayouts.get(0).getFields().stream().anyMatch(DataField::isVisible)); assertTrue(recordingLayouts.get(0).getFields().stream().anyMatch(DataField::isVisible));
} }
@@ -107,7 +107,7 @@ public class PreferencesUtilsTest {
RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout(); RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout();
// then // then
assertTrue(recordingLayout.getFields().size() > 0); assertFalse(recordingLayout.getFields().isEmpty());
assertEquals(recordingLayout.getName(), context.getString(R.string.stats_custom_layout_default_layout)); assertEquals(recordingLayout.getName(), context.getString(R.string.stats_custom_layout_default_layout));
assertTrue(recordingLayout.getFields().stream().anyMatch(DataField::isVisible)); assertTrue(recordingLayout.getFields().stream().anyMatch(DataField::isVisible));
} }
@@ -130,9 +130,9 @@ public class PreferencesUtilsTest {
RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout(); RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout();
// then // then
assertEquals(recordingLayout.getFields().size(), 4); assertEquals(4, recordingLayout.getFields().size());
assertEquals(recordingLayout.getName(), "run"); assertEquals("run", recordingLayout.getName());
assertEquals(recordingLayout.getColumnsPerRow(), 2); assertEquals(2, recordingLayout.getColumnsPerRow());
assertEquals(recordingLayout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key)); assertEquals(recordingLayout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key));
assertTrue(recordingLayout.getFields().get(0).isVisible()); assertTrue(recordingLayout.getFields().get(0).isVisible());
@@ -169,9 +169,9 @@ public class PreferencesUtilsTest {
RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout(); RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout();
// then // then
assertEquals(recordingLayout.getFields().size(), 4); assertEquals(4, recordingLayout.getFields().size());
assertEquals(recordingLayout.getName(), "walking"); assertEquals("walking", recordingLayout.getName());
assertEquals(recordingLayout.getColumnsPerRow(), 2); assertEquals(2, recordingLayout.getColumnsPerRow());
assertEquals(recordingLayout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key)); assertEquals(recordingLayout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key));
assertTrue(recordingLayout.getFields().get(0).isVisible()); assertTrue(recordingLayout.getFields().get(0).isVisible());
@@ -266,11 +266,11 @@ public class PreferencesUtilsTest {
// then only updated profile is modified in the custom layouts // then only updated profile is modified in the custom layouts
List<RecordingLayout> layoutsAfter = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> layoutsAfter = PreferencesUtils.getAllCustomLayouts();
assertEquals(layoutsBefore.size(), 2); assertEquals(2, layoutsBefore.size());
assertEquals(layoutsAfter.size(), 2); assertEquals(2, layoutsAfter.size());
assertEquals(layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count(), 4); assertEquals(4, layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count());
assertEquals(layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count(), 1); assertEquals(1, layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count());
} }
@Test @Test
@@ -309,11 +309,11 @@ public class PreferencesUtilsTest {
// then only updated profile is modified in the custom layouts // then only updated profile is modified in the custom layouts
List<RecordingLayout> layoutsAfter = PreferencesUtils.getAllCustomLayouts(); List<RecordingLayout> layoutsAfter = PreferencesUtils.getAllCustomLayouts();
assertEquals(layoutsBefore.size(), 2); assertEquals(2, layoutsBefore.size());
assertEquals(layoutsAfter.size(), 2); assertEquals(2, layoutsAfter.size());
assertEquals(layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count(), 4); assertEquals(4, layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count());
assertEquals(layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count(), 1); assertEquals(1, layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count());
} }
@Test @Test
@@ -341,6 +341,6 @@ public class PreferencesUtilsTest {
RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout(); RecordingLayout recordingLayout = PreferencesUtils.getCustomLayout();
// then the first one was returned // then the first one was returned
assertEquals(recordingLayout.getName(), "cycling"); assertEquals("cycling", recordingLayout.getName());
} }
} }
@@ -1,193 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.share;
import static org.junit.Assert.assertEquals;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.Locale;
import de.dennisguse.opentracks.LocaleRule;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.util.StringUtils;
/**
* Tests for {@link DescriptionGenerator}.
*
* @author Jimmy Shih
*/
@RunWith(AndroidJUnit4.class)
public class DescriptionGeneratorTest {
@Rule
public final LocaleRule mLocaleRule = new LocaleRule(Locale.ENGLISH);
private static final Instant START_TIME = Instant.ofEpochMilli(1288721514000L);
private DescriptionGenerator descriptionGenerator;
private final Context context = ApplicationProvider.getApplicationContext();
@Before
public void setUp() {
descriptionGenerator = new DescriptionGenerator(ApplicationProvider.getApplicationContext());
}
/**
* Tests {@link DescriptionGenerator#generateTrackDescription(Track, boolean)}.
*/
@Test
public void testGenerateTrackDescription() {
Track track = new Track();
TrackStatistics stats = new TrackStatistics();
stats.setTotalDistance(Distance.of(20000));
stats.setTotalTime(Duration.ofMillis(600000));
stats.setMovingTime(Duration.ofMillis(300000));
stats.setMaxSpeed(Speed.of(100));
stats.setMaxAltitude(550);
stats.setMinAltitude(-500);
stats.setTotalAltitudeGain(6000f);
stats.setTotalAltitudeLoss(6000f);
stats.setStartTime(START_TIME);
track.setTrackStatistics(stats);
track.setActivityTypeLocalized("hiking");
String expected = //"Created by"
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks (Debug)</a><p>"
+ "Name: -<br>"
+ "Activity type: hiking<br>"
+ "Description: -<br>"
+ "Total distance: 20.00 km (12.4 mi)<br>"
+ "Total time: 10:00<br>"
+ "Moving time: 05:00<br>"
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
+ "Average pace: 0:30 min/km (0:48 min/mi)<br>"
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
+ "Max elevation: 550 m (1804 ft)<br>"
+ "Min elevation: -500 m (-1640 ft)<br>"
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Elevation loss: 6000 m (19685 ft)<br>"
+ "Recorded: " + StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(START_TIME, ZoneId.systemDefault())) + "<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
}
@Test
public void testGenerateTrackDescriptionWithoutMaxMinAltitude() {
Track track = new Track();
TrackStatistics stats = new TrackStatistics();
stats.setTotalDistance(Distance.of(20000));
stats.setTotalTime(Duration.ofMillis(600000));
stats.setMovingTime(Duration.ofMillis(300000));
stats.setMaxSpeed(Speed.of(100));
stats.setMaxAltitude(Double.POSITIVE_INFINITY);
stats.setMinAltitude(Double.NEGATIVE_INFINITY);
stats.setTotalAltitudeGain(6000f);
stats.setTotalAltitudeLoss(6000f);
stats.setStartTime(START_TIME);
track.setTrackStatistics(stats);
track.setActivityTypeLocalized("hiking");
String expected = //"Created by"
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks (Debug)</a><p>"
+ "Name: -<br>"
+ "Activity type: hiking<br>"
+ "Description: -<br>"
+ "Total distance: 20.00 km (12.4 mi)<br>"
+ "Total time: 10:00<br>"
+ "Moving time: 05:00<br>"
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
+ "Average pace: 0:30 min/km (0:48 min/mi)<br>"
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Elevation loss: 6000 m (19685 ft)<br>"
+ "Recorded: " + StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(START_TIME, ZoneId.systemDefault())) + "<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
}
/**
* Tests {@link DescriptionGenerator#writeDistance(Distance, StringBuilder, int, String)}.
*/
@Test
public void testWriteDistance() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeDistance(Distance.of(1100), builder, R.string.description_total_distance, "<br>");
assertEquals("Total distance: 1.10 km (0.7 mi)<br>", builder.toString());
}
/**
* Tests {@link DescriptionGenerator#writeTime(Duration, StringBuilder, int, String)}.
*/
@Test
public void testWriteTime() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeTime(Duration.ofMillis(1000), builder, R.string.description_total_time, "<br>");
assertEquals("Total time: 00:01<br>", builder.toString());
}
/**
* Tests {@link DescriptionGenerator#writeSpeed(Speed, StringBuilder, int, String)}.
*/
@Test
public void testWriteSpeed() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeSpeed(Speed.of(1.1), builder, R.string.description_average_speed, "\n");
assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString());
}
/**
* Tests {@link DescriptionGenerator#writeAltitude(double, StringBuilder, int, String)}.
*/
@Test
public void testWriteAltitude() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeAltitude(4.2, builder, R.string.description_min_altitude, "<br>");
assertEquals("Min elevation: 4 m (14 ft)<br>", builder.toString());
}
/**
* Tests {@link DescriptionGenerator#writePace(Speed, StringBuilder, int, String)}.
*/
@Test
public void testWritePace() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writePace(Speed.of(1.1), builder, R.string.description_average_pace_in_minute, "\n");
assertEquals("Average pace: 15:09 min/km (24:23 min/mi)\n", builder.toString());
}
}
@@ -0,0 +1,138 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.share;
import static org.junit.Assert.assertEquals;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.Locale;
import de.dennisguse.opentracks.LocaleRule;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.util.StringUtils;
/**
* Tests for {@link TrackShareSummaryGenerator}.
*
* @author Jimmy Shih
*/
@RunWith(AndroidJUnit4.class)
public class TrackShareSummaryGeneratorTest {
@Rule
public final LocaleRule mLocaleRule = new LocaleRule(Locale.ENGLISH);
private static final Instant START_TIME = Instant.ofEpochMilli(1288721514000L);
private TrackShareSummaryGenerator descriptionGenerator;
private final Context context = ApplicationProvider.getApplicationContext();
@Before
public void setUp() {
descriptionGenerator = new TrackShareSummaryGenerator(ApplicationProvider.getApplicationContext());
}
@Test
public void testGenerateTrackDescription() {
Track track = new Track();
TrackStatistics stats = new TrackStatistics();
stats.setTotalDistance(Distance.of(20000));
stats.setTotalTime(Duration.ofMillis(600000));
stats.setMovingTime(Duration.ofMillis(300000));
stats.setMaxSpeed(Speed.of(100));
stats.setMaxAltitude(550);
stats.setMinAltitude(-500);
stats.setTotalAltitudeGain(6000f);
stats.setTotalAltitudeLoss(6000f);
stats.setStartTime(START_TIME);
track.setTrackStatistics(stats);
track.setActivityTypeLocalized("hiking");
String expected = //"Created by"
"OpenTracks (Debug)\n\n"
+ "Name: -\n"
+ "Activity type: hiking\n"
+ "Description: -\n"
+ "Total distance: 20.00 km (12.4 mi)\n"
+ "Total time: 10:00\n"
+ "Moving time: 05:00\n"
+ "Average speed: 120.00 km/h (74.6 mi/h)\n"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)\n"
+ "Max speed: 360.00 km/h (223.7 mi/h)\n"
+ "Average pace: 0:30 min/km (0:48 min/mi)\n"
+ "Average moving pace: 0:15 min/km (0:24 min/mi)\n"
+ "Fastest pace: 0:10 min/km (0:16 min/mi)\n"
+ "Max elevation: 550 m (1804 ft)\n"
+ "Min elevation: -500 m (-1640 ft)\n"
+ "Elevation gain: 6000 m (19685 ft)\n"
+ "Elevation loss: 6000 m (19685 ft)\n"
+ "Recorded: " + StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(START_TIME, ZoneId.systemDefault())) + "\n";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track));
}
@Test
public void testWriteDistance() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeDistance(Distance.of(1100), builder, R.string.description_total_distance);
assertEquals("Total distance: 1.10 km (0.7 mi)\n", builder.toString());
}
@Test
public void testWriteTime() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeTime(Duration.ofMillis(1000), builder, R.string.description_total_time);
assertEquals("Total time: 00:01\n", builder.toString());
}
@Test
public void testWriteSpeed() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeSpeed(Speed.of(1.1), builder, R.string.description_average_speed);
assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString());
}
@Test
public void testWriteAltitude() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeAltitude(4.2, builder, R.string.description_min_altitude);
assertEquals("Min elevation: 4 m (14 ft)\n", builder.toString());
}
@Test
public void testWritePace() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writePace(Speed.of(1.1), builder, R.string.description_average_pace_in_minute);
assertEquals("Average pace: 15:09 min/km (24:23 min/mi)\n", builder.toString());
}
}
@@ -26,11 +26,11 @@ public class CsvRecordingLayoutUtilsTest extends TestCase {
// then // then
assertNotNull(partsOk); assertNotNull(partsOk);
assertEquals(partsOk.size(), 4); assertEquals(4, partsOk.size());
assertEquals(partsOk.get(0), "Layout Name"); assertEquals("Layout Name", partsOk.get(0));
assertEquals(partsOk.get(1), "2"); assertEquals("2", partsOk.get(1));
assertEquals(partsOk.get(2), "distance,1,1"); assertEquals("distance,1,1", partsOk.get(2));
assertEquals(partsOk.get(3), "speed,1,1"); assertEquals("speed,1,1", partsOk.get(3));
assertNull(partsWrong1); assertNull(partsWrong1);
assertNull(partsWrong2); assertNull(partsWrong2);
} }
@@ -32,9 +32,9 @@ public class RecordingLayoutTest extends TestCase {
List<DataField> dataFieldList = recordingLayout.getFields(); List<DataField> dataFieldList = recordingLayout.getFields();
// then layout and data fields are built correctly // then layout and data fields are built correctly
assertEquals(recordingLayout.getName(), "running"); assertEquals("running", recordingLayout.getName());
assertEquals(recordingLayout.getColumnsPerRow(), 2); assertEquals(2, recordingLayout.getColumnsPerRow());
assertEquals(dataFieldList.size(), 4); assertEquals(4, dataFieldList.size());
assertEquals(dataFieldList.get(0).getKey(), context.getString(R.string.stats_custom_layout_speed_key)); assertEquals(dataFieldList.get(0).getKey(), context.getString(R.string.stats_custom_layout_speed_key));
assertEquals(dataFieldList.get(1).getKey(), context.getString(R.string.stats_custom_layout_distance_key)); assertEquals(dataFieldList.get(1).getKey(), context.getString(R.string.stats_custom_layout_distance_key));
assertEquals(dataFieldList.get(2).getKey(), context.getString(R.string.stats_custom_layout_altitude_key)); assertEquals(dataFieldList.get(2).getKey(), context.getString(R.string.stats_custom_layout_altitude_key));
@@ -66,7 +66,7 @@ public class RecordingLayoutTest extends TestCase {
// then layout and data fields are built correctly // then layout and data fields are built correctly
assertEquals(recordingLayout.getName(), PreferencesUtils.getDefaultLayoutName()); assertEquals(recordingLayout.getName(), PreferencesUtils.getDefaultLayoutName());
assertEquals(recordingLayout.getColumnsPerRow(), PreferencesUtils.getLayoutColumnsByDefault()); assertEquals(recordingLayout.getColumnsPerRow(), PreferencesUtils.getLayoutColumnsByDefault());
assertEquals(recordingLayout.getFields().size(), 0); assertEquals(0, recordingLayout.getFields().size());
} }
@Test @Test
@@ -81,7 +81,7 @@ public class RecordingLayoutTest extends TestCase {
// then layout and data fields are built correctly // then layout and data fields are built correctly
assertEquals(recordingLayout.getName(), PreferencesUtils.getDefaultLayoutName()); assertEquals(recordingLayout.getName(), PreferencesUtils.getDefaultLayoutName());
assertEquals(recordingLayout.getColumnsPerRow(), PreferencesUtils.getLayoutColumnsByDefault()); assertEquals(recordingLayout.getColumnsPerRow(), PreferencesUtils.getLayoutColumnsByDefault());
assertEquals(recordingLayout.getFields().size(), 0); assertEquals(0, recordingLayout.getFields().size());
} }
@Test @Test
@@ -94,9 +94,9 @@ public class RecordingLayoutTest extends TestCase {
List<DataField> dataFieldList = recordingLayout.getFields(); List<DataField> dataFieldList = recordingLayout.getFields();
// then layout and data fields are built correctly // then layout and data fields are built correctly
assertEquals(recordingLayout.getName(), "Layout Name"); assertEquals("Layout Name", recordingLayout.getName());
assertEquals(recordingLayout.getColumnsPerRow(), 2); assertEquals(2, recordingLayout.getColumnsPerRow());
assertEquals(recordingLayout.getFields().size(), 0); assertEquals(0, recordingLayout.getFields().size());
} }
@Test @Test
@@ -109,9 +109,9 @@ public class RecordingLayoutTest extends TestCase {
List<DataField> dataFieldList = recordingLayout.getFields(); List<DataField> dataFieldList = recordingLayout.getFields();
// then layout and data fields are built correctly // then layout and data fields are built correctly
assertEquals(recordingLayout.getName(), "Layout Name"); assertEquals("Layout Name", recordingLayout.getName());
assertEquals(recordingLayout.getColumnsPerRow(), 2); assertEquals(2, recordingLayout.getColumnsPerRow());
assertEquals(recordingLayout.getFields().size(), 1); assertEquals(1, recordingLayout.getFields().size());
} }
@Test @Test
@@ -128,7 +128,7 @@ public class RecordingLayoutTest extends TestCase {
String csv = recordingLayout.toCsv(); String csv = recordingLayout.toCsv();
// then csv is well built // then csv is well built
assertEquals(csv, "Test Layout;2;key1,0,0,0;key2,0,1,0;key3,1,0,0;key4,1,1,0;key5,1,1,1;"); assertEquals("Test Layout;2;key1,0,0,0;key2,0,1,0;key3,1,0,0;key4,1,1,0;key5,1,1,1;", csv);
} }
@Test @Test
@@ -1,68 +0,0 @@
package de.dennisguse.opentracks.util;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
import de.dennisguse.opentracks.ui.customRecordingLayout.RecordingLayout;
@RunWith(AndroidJUnit4.class)
public class StatisticsUtilsTest extends TestCase {
private final Context context = ApplicationProvider.getApplicationContext();
@Test
public void testEmptyValue() {
assertEquals(context.getString(R.string.stats_empty_value_float), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_distance_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_total_time_key)));
assertEquals(context.getString(R.string.stats_empty_value_float), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_speed_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_moving_time_key)));
assertEquals(context.getString(R.string.stats_empty_value_float), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_average_speed_key)));
assertEquals(context.getString(R.string.stats_empty_value_float), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_max_speed_key)));
assertEquals(context.getString(R.string.stats_empty_value_float), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_average_moving_speed_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_altitude_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_gain_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_loss_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_pace_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_average_moving_pace_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_average_pace_key)));
assertEquals(context.getString(R.string.stats_empty_value_time), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_fastest_pace_key)));
assertEquals(context.getString(R.string.stats_empty_value_coordinates), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_coordinates_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_heart_rate_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_cadence_key)));
assertEquals(context.getString(R.string.stats_empty_value_integer), StatisticsUtils.emptyValue(context, context.getString(R.string.stats_custom_layout_power_key)));
}
@Test
public void testFilterVisible() {
// given
RecordingLayout recordingLayout = new RecordingLayout("profile");
recordingLayout.addField(new DataField("key1", true, true, false));
recordingLayout.addField(new DataField("key2", false, true, false));
recordingLayout.addField(new DataField("key3", true, true, false));
recordingLayout.addField(new DataField("key4", false, true, false));
recordingLayout.addField(new DataField("key5", true, true, false));
// when
RecordingLayout resultTrue = recordingLayout.toRecordingLayout(true);
RecordingLayout resultFalse = recordingLayout.toRecordingLayout(false);
// then
assertEquals(resultTrue.getFields().size(), 3);
assertTrue(resultTrue.getFields().stream().anyMatch(f -> "key1".equals(f.getKey())));
assertTrue(resultTrue.getFields().stream().anyMatch(f -> "key3".equals(f.getKey())));
assertTrue(resultTrue.getFields().stream().anyMatch(f -> "key5".equals(f.getKey())));
assertEquals(resultFalse.getFields().size(), 2);
assertTrue(resultFalse.getFields().stream().anyMatch(f -> "key2".equals(f.getKey())));
assertTrue(resultFalse.getFields().stream().anyMatch(f -> "key4".equals(f.getKey())));
}
}
@@ -38,11 +38,10 @@ import java.time.OffsetDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.format.TextStyle; import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.LocaleRule; import de.dennisguse.opentracks.LocaleRule;
import de.dennisguse.opentracks.TimezoneRule; import de.dennisguse.opentracks.TimezoneRule;
@@ -133,8 +132,10 @@ public class StringUtilsTest {
@Test @Test
public void testFormatDateTodayRelative() { public void testFormatDateTodayRelative() {
// given // given
ArrayList<String> shortDays = Arrays.stream(DayOfWeek.values()).map(d -> d.getDisplayName(TextStyle.FULL, Locale.getDefault())).collect(Collectors.toCollection(ArrayList::new)); List<String> shortDays = Arrays.stream(DayOfWeek.values()).map(d -> d.getDisplayName(TextStyle.FULL, Locale.getDefault()))
ArrayList<String> shortMonths = Arrays.stream(Month.values()).map(m -> m.getDisplayName(TextStyle.SHORT, Locale.getDefault())).collect(Collectors.toCollection(ArrayList::new)); .toList();
List<String> shortMonths = Arrays.stream(Month.values()).map(m -> m.getDisplayName(TextStyle.SHORT, Locale.getDefault()))
.toList();
LocalDate today = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()).toLocalDate(); LocalDate today = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()).toLocalDate();
LocalDate yesterday = today.minusDays(1); LocalDate yesterday = today.minusDays(1);
-15
View File
@@ -395,21 +395,6 @@ limitations under the License.
android:icon="@drawable/ic_logo_color_24dp" android:icon="@drawable/ic_logo_color_24dp"
android:label="@string/recording_service" /> android:label="@string/recording_service" />
<service
android:name=".io.file.exporter.ExportService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name=".io.file.importer.ImportService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name=".services.TrackDeleteService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
<!--Necessary for SDK < 33 to (re-)store per app locale information--> <!--Necessary for SDK < 33 to (re-)store per app locale information-->
<service <service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService" android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
@@ -16,15 +16,18 @@
package de.dennisguse.opentracks; package de.dennisguse.opentracks;
import android.os.Handler;
import android.widget.Toast; import android.widget.Toast;
import java.util.ArrayList; import androidx.work.Data;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.Collectors; import java.util.List;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.services.TrackDeleteService; import de.dennisguse.opentracks.services.TrackDeletionWorker;
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment.ConfirmDeleteCaller; import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment.ConfirmDeleteCaller;
@@ -37,7 +40,7 @@ import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragm
* @author Jimmy Shih * @author Jimmy Shih
*/ */
//TODO Check if this class is still such a good idea; inheritance might limit maintainability //TODO Check if this class is still such a good idea; inheritance might limit maintainability
public abstract class AbstractTrackDeleteActivity extends AbstractActivity implements ConfirmDeleteCaller, TrackDeleteService.TrackDeleteResultReceiver.Receiver { public abstract class AbstractTrackDeleteActivity extends AbstractActivity implements ConfirmDeleteCaller {
protected void deleteTracks(Track.Id... trackIds) { protected void deleteTracks(Track.Id... trackIds) {
ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds); ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds);
@@ -46,8 +49,8 @@ public abstract class AbstractTrackDeleteActivity extends AbstractActivity imple
//TODO A callback is better. //TODO A callback is better.
@Override @Override
public void onConfirmDeleteDone(Track.Id... trackIds) { public void onConfirmDeleteDone(Track.Id... trackIds) {
ArrayList<Track.Id> trackIdList = Arrays.stream(trackIds) List<Track.Id> trackIdList = Arrays.stream(trackIds)
.filter(trackId -> !trackId.equals(getRecordingTrackId())).collect(Collectors.toCollection(ArrayList::new)); .filter(trackId -> !trackId.equals(getRecordingTrackId())).toList();
onDeleteConfirmed(); onDeleteConfirmed();
@@ -55,10 +58,29 @@ public abstract class AbstractTrackDeleteActivity extends AbstractActivity imple
Toast.makeText(this, getString(R.string.track_delete_not_recording), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.track_delete_not_recording), Toast.LENGTH_LONG).show();
} }
TrackDeleteService.enqueue(this, new TrackDeleteService.TrackDeleteResultReceiver(new Handler(), this), trackIdList); WorkManager workManager = WorkManager.getInstance(this);
WorkRequest deleteRequest = new OneTimeWorkRequest.Builder(TrackDeletionWorker.class)
.setInputData(new Data.Builder()
.putLongArray(TrackDeletionWorker.TRACKIDS_KEY, Arrays.stream(trackIds).mapToLong(Track.Id::id).toArray())
.build())
.build();
workManager
.getWorkInfoByIdLiveData(deleteRequest.getId())
.observe(this, workInfo -> {
if (workInfo != null) {
if (workInfo.getState().isFinished()) {
onDeleteFinished();
}
}
});
workManager.enqueue(deleteRequest);
} }
protected abstract void onDeleteConfirmed(); protected abstract void onDeleteConfirmed();
protected abstract void onDeleteFinished();
protected abstract Track.Id getRecordingTrackId(); protected abstract Track.Id getRecordingTrackId();
} }
@@ -16,10 +16,10 @@ import de.dennisguse.opentracks.data.models.SpeedFormatter;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.databinding.TrackStoppedBinding; import de.dennisguse.opentracks.databinding.TrackStoppedBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.io.file.exporter.ExportUtils;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.util.ExportUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.chart; package de.dennisguse.opentracks.chart;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.DashPathEffect; import android.graphics.DashPathEffect;
import android.graphics.Paint; import android.graphics.Paint;
@@ -49,10 +48,8 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.stats.ExtremityMonitor; import de.dennisguse.opentracks.stats.ExtremityMonitor;
import de.dennisguse.opentracks.ui.markers.MarkerDetailActivity;
import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.ui.markers.MarkerUtils;
import de.dennisguse.opentracks.ui.util.ThemeUtils; import de.dennisguse.opentracks.ui.util.ThemeUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
/** /**
@@ -857,7 +854,7 @@ public class ChartView extends View {
* @param chartValueSeries the chart value series * @param chartValueSeries the chart value series
* @param canvas the canvas * @param canvas the canvas
* @param xPosition the right most x position * @param xPosition the right most x position
* @parm yOffset offset to apply to y position * @param yOffset offset to apply to y position
* @param yValue the y value * @param yValue the y value
* @return the marker width. * @return the marker width.
*/ */
@@ -883,7 +880,7 @@ public class ChartView extends View {
break; break;
} }
} }
if (firstChartValueSeries != null && chartPoints.size() > 0) { if (firstChartValueSeries != null && !chartPoints.isEmpty()) {
int dx = getX(maxX) - pointer.getIntrinsicWidth() / 2; int dx = getX(maxX) - pointer.getIntrinsicWidth() / 2;
double value = firstChartValueSeries.extractDataFromChartPoint(last); double value = firstChartValueSeries.extractDataFromChartPoint(last);
int dy = getY(firstChartValueSeries, value) - pointer.getIntrinsicHeight(); int dy = getY(firstChartValueSeries, value) - pointer.getIntrinsicHeight();
@@ -897,7 +894,7 @@ public class ChartView extends View {
*/ */
private void updateSeries() { private void updateSeries() {
synchronized (chartPoints) { synchronized (chartPoints) {
seriesList.stream().forEach(this::updateSerie); seriesList.forEach(this::updateSerie);
} }
} }
@@ -2,7 +2,7 @@ package de.dennisguse.opentracks.data;
public record SelectionData( public record SelectionData(
String selection, String selection,
String[] selectionArgs String[] selectionArgs //TODO Refactor to List<String>
) { ) {
public SelectionData() { public SelectionData() {
@@ -386,7 +386,7 @@ public class TrackDataHub {
lastSeenTrackPointId = localLastSeenTrackPointIdId; lastSeenTrackPointId = localLastSeenTrackPointIdId;
} }
listeners.stream().forEach(Listener::onNewTrackPointsDone); listeners.forEach(Listener::onNewTrackPointsDone);
} }
@@ -6,7 +6,6 @@ import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.data.tables.TracksColumns;
@@ -67,10 +66,11 @@ public class TrackSelection implements ContentProviderUtils.ContentProviderSelec
} }
// Builds selection arguments. // Builds selection arguments.
ArrayList<String> args = trackIds.stream().map(id -> Long.toString(id.id())).collect(Collectors.toCollection(ArrayList::new)); ArrayList<String> args = new ArrayList<>();
args.addAll(trackIds.stream().map(id -> Long.toString(id.id())).toList());
args.addAll(categories); args.addAll(categories);
args.addAll(fromToArgs); args.addAll(fromToArgs);
selectionArgs = args.stream().toArray(String[]::new); selectionArgs = args.toArray(String[]::new);
return new SelectionData(selection, selectionArgs); return new SelectionData(selection, selectionArgs);
} }
@@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
@@ -118,7 +117,7 @@ public enum ActivityType {
return Arrays.stream(values()) return Arrays.stream(values())
.map(ActivityType::getLocalizedStringId) .map(ActivityType::getLocalizedStringId)
.map(context::getString) .map(context::getString)
.collect(Collectors.toList()); .toList();
} }
@NonNull @NonNull
@@ -14,15 +14,15 @@ public class DistanceFormatter {
private final Resources resources; private final Resources resources;
private final int decimalCount; private final int decimalPlaces;
private final double threshold; private final double threshold;
private final UnitSystem unitSystem; private final UnitSystem unitSystem;
private DistanceFormatter(Resources resources, int decimalCount, double threshold, UnitSystem unitSystem) { private DistanceFormatter(Resources resources, int decimalPlaces, double threshold, UnitSystem unitSystem) {
this.resources = resources; this.resources = resources;
this.decimalCount = decimalCount; this.decimalPlaces = decimalPlaces;
this.threshold = threshold; this.threshold = threshold;
this.unitSystem = unitSystem; this.unitSystem = unitSystem;
assert unitSystem != null; assert unitSystem != null;
@@ -57,30 +57,30 @@ public class DistanceFormatter {
switch (unitSystem) { switch (unitSystem) {
case METRIC -> { case METRIC -> {
if (distance.greaterThan(Distance.ofKilometer(threshold))) { if (distance.greaterThan(Distance.ofKilometer(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalCount), resources.getString(R.string.unit_kilometer)); return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalPlaces), resources.getString(R.string.unit_kilometer));
} else { } else {
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter)); return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalPlaces), resources.getString(R.string.unit_meter));
} }
} }
case IMPERIAL_FEET -> { case IMPERIAL_FEET -> {
if (distance.greaterThan(Distance.ofMile(threshold))) { if (distance.greaterThan(Distance.ofMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile)); return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalPlaces), resources.getString(R.string.unit_mile));
} else { } else {
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet)); return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalPlaces), resources.getString(R.string.unit_feet));
} }
} }
case IMPERIAL_METER -> { case IMPERIAL_METER -> {
if (distance.greaterThan(Distance.ofMile(threshold))) { if (distance.greaterThan(Distance.ofMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile)); return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalPlaces), resources.getString(R.string.unit_mile));
} else { } else {
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter)); return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalPlaces), resources.getString(R.string.unit_meter));
} }
} }
case NAUTICAL_IMPERIAL -> { case NAUTICAL_IMPERIAL -> {
if (distance.greaterThan(Distance.ofNauticalMile(threshold))) { if (distance.greaterThan(Distance.ofNauticalMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalCount), resources.getString(R.string.unit_nautical_mile)); return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalPlaces), resources.getString(R.string.unit_nautical_mile));
} else { } else {
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet)); return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalPlaces), resources.getString(R.string.unit_feet));
} }
} }
default -> throw new RuntimeException("Not implemented"); default -> throw new RuntimeException("Not implemented");
@@ -93,19 +93,19 @@ public class DistanceFormatter {
public static class Builder { public static class Builder {
private int decimalCount; private int decimalPlaces;
private UnitSystem unitSystem; private UnitSystem unitSystem;
private double threshold; private double threshold;
public Builder() { public Builder() {
decimalCount = 2; decimalPlaces = 2;
threshold = 0.5; threshold = 0.5;
} }
public Builder setDecimalCount(int decimalCount) { public Builder setDecimalPlaces(int decimalPlaces) {
this.decimalCount = decimalCount; this.decimalPlaces = decimalPlaces;
return this; return this;
} }
@@ -120,7 +120,7 @@ public class DistanceFormatter {
} }
public DistanceFormatter build(Resources resource) { public DistanceFormatter build(Resources resource) {
return new DistanceFormatter(resource, decimalCount, threshold, unitSystem); return new DistanceFormatter(resource, decimalPlaces, threshold, unitSystem);
} }
public DistanceFormatter build(Context context) { public DistanceFormatter build(Context context) {
@@ -12,17 +12,16 @@ import de.dennisguse.opentracks.util.StringUtils;
public class SpeedFormatter { public class SpeedFormatter {
private final Resources resources; private final int DECIMAL_PLACES = 1;
private final int decimalCount; private final Resources resources;
private final UnitSystem unitSystem; private final UnitSystem unitSystem;
private final boolean reportSpeedOrPace; private final boolean reportSpeedOrPace;
private SpeedFormatter(Resources resources, int decimalCount, UnitSystem unitSystem, boolean reportSpeedOrPace) { private SpeedFormatter(Resources resources, UnitSystem unitSystem, boolean reportSpeedOrPace) {
this.resources = resources; this.resources = resources;
this.decimalCount = decimalCount;
this.unitSystem = unitSystem; this.unitSystem = unitSystem;
this.reportSpeedOrPace = reportSpeedOrPace; this.reportSpeedOrPace = reportSpeedOrPace;
} }
@@ -55,7 +54,7 @@ public class SpeedFormatter {
} }
if (reportSpeedOrPace) { if (reportSpeedOrPace) {
return new Pair<>(StringUtils.formatDecimal(speed.to(unitSystem), 1), unitString); return new Pair<>(StringUtils.formatDecimal(speed.to(unitSystem), DECIMAL_PLACES), unitString);
} }
int pace = (int) speed.toPace(unitSystem).getSeconds(); int pace = (int) speed.toPace(unitSystem).getSeconds();
@@ -71,22 +70,14 @@ public class SpeedFormatter {
public static class Builder { public static class Builder {
private int decimalCount;
private UnitSystem unitSystem; private UnitSystem unitSystem;
private boolean reportSpeedOrPace; private boolean reportSpeedOrPace;
public Builder() { public Builder() {
decimalCount = 2;
reportSpeedOrPace = true; reportSpeedOrPace = true;
} }
public Builder setDecimalCount(int decimalCount) {
this.decimalCount = decimalCount;
return this;
}
public Builder setUnit(@NonNull UnitSystem unitSystem) { public Builder setUnit(@NonNull UnitSystem unitSystem) {
this.unitSystem = unitSystem; this.unitSystem = unitSystem;
return this; return this;
@@ -98,7 +89,7 @@ public class SpeedFormatter {
} }
public SpeedFormatter build(Resources resource) { public SpeedFormatter build(Resources resource) {
return new SpeedFormatter(resource, decimalCount, unitSystem, reportSpeedOrPace); return new SpeedFormatter(resource, unitSystem, reportSpeedOrPace);
} }
public SpeedFormatter build(Context context) { public SpeedFormatter build(Context context) {
@@ -35,7 +35,7 @@ import java.util.Optional;
public class TrackPoint { public class TrackPoint {
@Nullable @Nullable
private TrackPoint.Id id; private final TrackPoint.Id id;
//Requires: position.time must be non-null //Requires: position.time must be non-null
@NonNull @NonNull
@@ -23,7 +23,6 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements
private static final String CHOOSE_ACTIVITY_TYPE_DIALOG_TAG = "chooseActivityType"; private static final String CHOOSE_ACTIVITY_TYPE_DIALOG_TAG = "chooseActivityType";
@Deprecated
public static void showDialog(FragmentManager fragmentManager, Context context, String activityTypeLocalized) { public static void showDialog(FragmentManager fragmentManager, Context context, String activityTypeLocalized) {
ActivityType activityType = ActivityType.findByLocalizedString(context, activityTypeLocalized); ActivityType activityType = ActivityType.findByLocalizedString(context, activityTypeLocalized);
showDialog(fragmentManager, activityType); showDialog(fragmentManager, activityType);
@@ -62,7 +62,7 @@ public class StatisticsRecordingFragment extends Fragment {
updateDataOnUI(); updateDataOnUI();
} }
if (PreferencesUtils.isKey(R.string.stats_custom_layouts_key, key) || PreferencesUtils.isKey(R.string.stats_custom_layout_selected_layout_key, key)) { if (PreferencesUtils.isKey(List.of(R.string.stats_custom_layouts_key, R.string.stats_custom_layout_selected_layout_key), key)) {
onLayoutChanged(PreferencesUtils.getCustomLayout()); onLayoutChanged(PreferencesUtils.getCustomLayout());
} }
}; };
@@ -10,8 +10,6 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.FileUtils;
@@ -25,8 +23,7 @@ public class TrackFilenameGenerator {
public static final String STARTTIME_DATE_KEY = "{date}"; public static final String STARTTIME_DATE_KEY = "{date}";
public static String getAllOptions() { public static String getAllOptions() {
return Stream.of(UUID_KEY, TRACKNAME_KEY, ACTIVITY_TYPE_KEY, STARTTIME_TIME_KEY, STARTTIME_DATE_KEY) return String.join(", ", UUID_KEY, TRACKNAME_KEY, ACTIVITY_TYPE_KEY, STARTTIME_TIME_KEY, STARTTIME_DATE_KEY);
.collect(Collectors.joining(", "));
} }
public static String format(@NonNull String name, @NonNull TrackFileFormat trackFileFormat) { public static String format(@NonNull String name, @NonNull TrackFileFormat trackFileFormat) {
@@ -149,12 +149,12 @@ public class CSVTrackExporter implements TrackExporter {
printWriter = null; printWriter = null;
} }
public void writeHeader(List<Column> columns) { private void writeHeader(List<Column> columns) {
String columnNames = columns.stream().map(c -> c.columnName).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined")); String columnNames = columns.stream().map(c -> c.columnName).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined"));
printWriter.println("#" + columnNames); printWriter.println("#" + columnNames);
} }
public void writeTrackPoint(List<Column> columns, TrackPoint trackPoint) { private void writeTrackPoint(List<Column> columns, TrackPoint trackPoint) {
String columnNames = columns.stream().map(c -> c.extractor.apply(trackPoint)).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined")); String columnNames = columns.stream().map(c -> c.extractor.apply(trackPoint)).reduce((s, s2) -> s + "," + s2).orElseThrow(() -> new RuntimeException("No columns defined"));
printWriter.println(columnNames); printWriter.println(columnNames);
} }
@@ -24,15 +24,19 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import androidx.work.Data;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.AbstractActivity;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
@@ -41,14 +45,12 @@ import de.dennisguse.opentracks.io.file.ErrorListDialog;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator; import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.ExportUtils;
import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.FileUtils;
/** /**
* An activity for saving tracks to the external storage. * An activity for saving tracks to the external storage.
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
* TODO: This class needs some refactoring.
* * It pushes each export job (usually one Track) for export; although export could be run in parallel. * * It pushes each export job (usually one Track) for export; although export could be run in parallel.
* Also this requires that the ExportActivity stays in foreground, so the user has to activily wait. * Also this requires that the ExportActivity stays in foreground, so the user has to activily wait.
* It would be better to let the ExportService handle this and let it report progress / conflicts to ExportActivity * It would be better to let the ExportService handle this and let it report progress / conflicts to ExportActivity
@@ -56,7 +58,9 @@ import de.dennisguse.opentracks.util.FileUtils;
* So, for this check actually a different file name might be used than in the ExportService. * So, for this check actually a different file name might be used than in the ExportService.
* * Saved state as an object instead of individual values. * * Saved state as an object instead of individual values.
*/ */
public class ExportActivity extends AppCompatActivity implements ExportService.ExportServiceResultReceiver.Receiver { //TODO Show progress per exported track (currently per exported file)
//TODO export tracks in parallel (for multiple files)
public class ExportActivity extends AbstractActivity {
private static final String TAG = ExportActivity.class.getSimpleName(); private static final String TAG = ExportActivity.class.getSimpleName();
@@ -84,8 +88,6 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
private TrackFileFormat trackFileFormat; private TrackFileFormat trackFileFormat;
private Uri directoryUri; private Uri directoryUri;
private ExportService.ExportServiceResultReceiver resultReceiver;
private List<String> directoryFiles; private List<String> directoryFiles;
private int trackExportSuccessCount; private int trackExportSuccessCount;
@@ -147,8 +149,6 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ExportActivityBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
setSupportActionBar(viewBinding.bottomAppBarLayout.bottomAppBar); setSupportActionBar(viewBinding.bottomAppBarLayout.bottomAppBar);
@@ -161,8 +161,6 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
DocumentFile documentFile = DocumentFile.fromTreeUri(this, directoryUri); DocumentFile documentFile = DocumentFile.fromTreeUri(this, directoryUri);
String directoryDisplayName = FileUtils.getPath(documentFile); String directoryDisplayName = FileUtils.getPath(documentFile);
resultReceiver = new ExportService.ExportServiceResultReceiver(new Handler(), this);
if (savedInstanceState == null) { if (savedInstanceState == null) {
autoConflict = ConflictResolutionStrategy.CONFLICT_NONE; autoConflict = ConflictResolutionStrategy.CONFLICT_NONE;
setProgress(); setProgress();
@@ -190,6 +188,13 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
viewBinding.exportActivityToolbar.setTitle(getString(R.string.export_progress_message, directoryDisplayName)); viewBinding.exportActivityToolbar.setTitle(getString(R.string.export_progress_message, directoryDisplayName));
} }
@NonNull
@Override
protected View createRootView() {
viewBinding = ExportActivityBinding.inflate(getLayoutInflater());
return viewBinding.getRoot();
}
@Override @Override
protected void onSaveInstanceState(@NonNull Bundle outState) { protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
@@ -207,6 +212,7 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
viewBinding = null;
conflictsQueue.clear(); conflictsQueue.clear();
exportTasks.clear(); exportTasks.clear();
} }
@@ -216,9 +222,9 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
exportTasks = new ArrayList<>(); exportTasks = new ArrayList<>();
if (allInOneFile) { if (allInOneFile) {
String filename = "OpenTracks-Backup"; String filename = "OpenTracks-Backup";
exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).collect(Collectors.toList()))); exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).toList()));
} else { } else {
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).collect(Collectors.toList())); exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).toList());
} }
trackExportTotalCount = exportTasks.size(); trackExportTotalCount = exportTasks.size();
} }
@@ -231,19 +237,45 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
if (fileExists && conflictResolution == ConflictResolutionStrategy.CONFLICT_NONE) { if (fileExists && conflictResolution == ConflictResolutionStrategy.CONFLICT_NONE) {
conflict(exportTask); conflict(exportTask);
} else if (fileExists && conflictResolution == ConflictResolutionStrategy.CONFLICT_SKIP) { return;
}
if (fileExists && conflictResolution == ConflictResolutionStrategy.CONFLICT_SKIP) {
trackExportSkippedCount++; trackExportSkippedCount++;
nextExport(exportTask); nextExport(exportTask);
} else { return;
ExportService.enqueue(this, resultReceiver, exportTask, directoryUri);
} }
WorkManager workManager = WorkManager.getInstance(this);
WorkRequest exportRequest = new OneTimeWorkRequest.Builder(ExportWorker.class)
.setInputData(new Data.Builder()
.putLongArray(ExportWorker.TRACKIDS_KEY, exportTask.getTrackIds().stream().mapToLong(Track.Id::id).toArray())
.putString(ExportWorker.DIRECTORY_URI_KEY, directoryUri.toString())
.putString(ExportWorker.TRACKFILEFORMAT_KEY, exportTask.getTrackFileFormat().toString())
.putString(ExportWorker.FILENAME_KEY, exportTask.getFilename())
.build())
.build();
workManager
.getWorkInfoByIdLiveData(exportRequest.getId())
.observe(this, workInfo -> {
if (workInfo != null) {
WorkInfo.State state = workInfo.getState();
switch (state) {
case SUCCEEDED -> onExportSuccess(exportTask);
case FAILED ->
onExportError(exportTask, workInfo.getOutputData().getString(ExportWorker.RESULT_EXPORT_ERROR_MESSAGE_KEY));
}
}
});
workManager.enqueue(exportRequest);
} }
private void export(ExportTask exportTask) { private void export(ExportTask exportTask) {
export(exportTask, autoConflict); export(exportTask, autoConflict);
} }
@Deprecated //TODO Check should be done in ExportService @Deprecated //TODO Check should be done in ExportWorker
private boolean exportFileExists(ExportTask exportTask) { private boolean exportFileExists(ExportTask exportTask) {
String filename; String filename;
if (exportTask.isMultiExport()) { if (exportTask.isMultiExport()) {
@@ -314,7 +346,6 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
} }
} }
@Override
public void onExportSuccess(ExportTask exportTask) { public void onExportSuccess(ExportTask exportTask) {
if (exportFileExists(exportTask)) { if (exportFileExists(exportTask)) {
trackExportOverwrittenCount++; trackExportOverwrittenCount++;
@@ -325,7 +356,6 @@ public class ExportActivity extends AppCompatActivity implements ExportService.E
nextExport(exportTask); nextExport(exportTask);
} }
@Override
public void onExportError(ExportTask exportTask, String errorMessage) { public void onExportError(ExportTask exportTask, String errorMessage) {
trackExportErrorCount++; trackExportErrorCount++;
String name; String name;

Some files were not shown because too many files have changed in this diff Show More