mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-24 11:15:18 +02:00
Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5746a41905 | |||
| 361ae909e7 | |||
| 4b59660ea1 | |||
| cabf5d238e | |||
| 9c902b89ed | |||
| c31b8a5802 | |||
| 901c548d13 | |||
| b77de1e10d | |||
| b8c7fba7d8 | |||
| 466719fbc8 | |||
| 4f0ab71503 | |||
| daa4689f44 | |||
| 023a5aa221 | |||
| 832005565a | |||
| 9af8b0d353 | |||
| 57c0750980 | |||
| 8e36ee2e7d | |||
| ec2e527fd1 | |||
| d968e5d0c1 | |||
| 4257f21cae | |||
| 26e7059af2 | |||
| 94595f2a1f | |||
| 1fa76301e2 | |||
| ce2c608cc9 | |||
| 916f26dfda | |||
| a108edc125 | |||
| 1a1a8a851b | |||
| ddd1efeb58 | |||
| 6c30dd8509 | |||
| 21fe59f32c | |||
| f79b2b51c8 | |||
| b16e9ad964 | |||
| 65f8ba16b3 | |||
| 9b48993cd0 | |||
| 54cec3e821 | |||
| daeb972c8a | |||
| 73872e8926 | |||
| c15fa21a56 | |||
| e9d1080e5d | |||
| d0b3f45151 | |||
| 32b0b02d28 | |||
| d6617f61b7 | |||
| b5180f235f | |||
| e879eedbd6 | |||
| c7ca6800f7 | |||
| fed884a6ce | |||
| 02a77e5ce7 | |||
| 6f97399aeb | |||
| 1c4f0e67ab | |||
| ebed386d96 | |||
| e44f63feb7 | |||
| 34c5a3ab97 | |||
| eac47db058 | |||
| e72d2a750c | |||
| f54856c3f1 | |||
| 81f6bbe955 | |||
| c162c0a0ff | |||
| 385d05dcdb | |||
| 308ce4ac07 | |||
| f8a0241e1f | |||
| c74a5c8749 | |||
| defdd49a65 | |||
| 46cdae399d | |||
| a19f363b4a | |||
| b55b25e00d | |||
| d527770a0a | |||
| fb75b0fa58 | |||
| 1c986e48f2 | |||
| 7f666c571e | |||
| 3c23a9f540 | |||
| ec08717d01 | |||
| 30dc440d43 | |||
| 919e670f95 | |||
| 8ff95efc65 | |||
| b2b98210d5 | |||
| b3f2db4619 | |||
| caede289d0 | |||
| 7a09e32261 | |||
| 388f1d0213 | |||
| f44d72a51f | |||
| 5e9b1d1cb7 | |||
| 305c0d2502 | |||
| 4306634fb2 | |||
| 9fded8953d | |||
| a416b4b0e7 | |||
| e795fbf07d | |||
| 41401e2f13 | |||
| 848c5a8db8 | |||
| becd65f9f5 | |||
| ece4470fec | |||
| de08707000 | |||
| d7a5bf8231 | |||
| 10453e3d4e | |||
| 4d4898e01a | |||
| 286fbc9b45 | |||
| b1ea89a548 | |||
| 2e5643aa0d | |||
| f48e175578 | |||
| 252909b133 | |||
| 125cafa79d | |||
| d15810f908 | |||
| a89e25b00c | |||
| f256c25cb6 | |||
| db75b28d5b | |||
| 87c4428a86 | |||
| 8f1eda9726 | |||
| dc88007154 | |||
| 8f82375fa4 | |||
| dd37526914 | |||
| 16d2f080b2 | |||
| 2cce5c56cd | |||
| 24be37aea5 | |||
| f1c9f7512b | |||
| 03a200ec4b | |||
| 93eefe5cf2 | |||
| 792e88acaa |
@@ -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
|
||||||
@@ -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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "gradle"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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
@@ -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:
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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 @@
|
|||||||
一款尊重您的隐私的运动追踪应用。
|
尊重您隐私的运动追踪伙伴。
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
+4
-5
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -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
|
||||||
|
|||||||
+9
-4
@@ -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);
|
||||||
|
|||||||
+6
-6
@@ -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);
|
||||||
|
|||||||
+5
-5
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+138
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -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);
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user