Compare commits
352 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0605dbb0ab | |||
| bf03de6be7 | |||
| d65ce361f7 | |||
| 3f600f6be7 | |||
| 9aab3c216c | |||
| 7935185812 | |||
| 4c1b1be96c | |||
| 5762830655 | |||
| 6d61206782 | |||
| b9dedef292 | |||
| f3caecd049 | |||
| e16780277f | |||
| 13484685a3 | |||
| 7b745d9837 | |||
| 52742064f6 | |||
| 2edf5582aa | |||
| 808eb92bf2 | |||
| c0b84c3d72 | |||
| e275d3e5c0 | |||
| b4ebad2c3c | |||
| 1ab76e1317 | |||
| 3d1104dd0b | |||
| 2df45d31de | |||
| 5436981e0d | |||
| fd2b1bec7d | |||
| bb1eaa5b56 | |||
| dae8eaa97a | |||
| 565b1ce94d | |||
| 543d5e18bf | |||
| 01368df6b1 | |||
| c666d55211 | |||
| 8cc4fd1d4f | |||
| c241a35861 | |||
| 674d231b7a | |||
| bebee59eb2 | |||
| 24f843b0db | |||
| f0259d13dd | |||
| 9dff965a52 | |||
| b4e6d10fbe | |||
| 1a9d88277f | |||
| 4ea956ca0e | |||
| 8060c2e1e3 | |||
| 8c96b65e59 | |||
| a407e94d3c | |||
| 310c790324 | |||
| 12b3d31f5c | |||
| d43dca61c1 | |||
| 20c14a03b2 | |||
| a6601f4eea | |||
| 220c7b1443 | |||
| 33bb63976d | |||
| 8db8f68d69 | |||
| 99b417217e | |||
| ac80386b8a | |||
| b96441a964 | |||
| 207f9563df | |||
| 7b84bf448b | |||
| 41a62fd412 | |||
| 1087dbf387 | |||
| e16d1d53c6 | |||
| 00c9ba6595 | |||
| 7c1995c67f | |||
| d2e0ae8b11 | |||
| f0aa49537d | |||
| 14ace294f3 | |||
| b53ef455a6 | |||
| 3dc6c6607d | |||
| dd91e05fb6 | |||
| 19fe5275b9 | |||
| 1aeb9ca332 | |||
| 520c240a19 | |||
| 48aaca13d0 | |||
| 88a31f4f39 | |||
| 5ce9e6606b | |||
| 4ea70b15e7 | |||
| d3cf2957cc | |||
| dbac595754 | |||
| d70e7b8788 | |||
| f6835852b6 | |||
| d5864726f6 | |||
| 3cc3271726 | |||
| 8aef9c8d28 | |||
| bcca00d110 | |||
| aa929161b4 | |||
| 70cb9cbf51 | |||
| fef3b97661 | |||
| 945f366195 | |||
| 8c0a851d87 | |||
| 3eb89d7899 | |||
| f12ff4a625 | |||
| 71dac06ce8 | |||
| 07090cd72c | |||
| 26a20fe32d | |||
| d74ef256d7 | |||
| 0392ba5128 | |||
| 3d12ebdaa3 | |||
| b3cb5e8091 | |||
| 8f9cbcc077 | |||
| 14b6746dff | |||
| a5eca8fa64 | |||
| 498ee20e2a | |||
| 2207865a70 | |||
| 8073f12947 | |||
| cacfcbd4d6 | |||
| 08673de331 | |||
| aecd1504f3 | |||
| f3bf42083a | |||
| 8a9cd40bd5 | |||
| fee1d1a871 | |||
| 0787ae6686 | |||
| 747ef9fc56 | |||
| 5911d60818 | |||
| b89dbf5819 | |||
| 99e2c1f38d | |||
| faa1ffe53b | |||
| 8461122df0 | |||
| 2ca7aa8f1d | |||
| 9db2aff631 | |||
| b7cedab1fb | |||
| 0a193c8b5c | |||
| 7049fab204 | |||
| 80fa49bcf0 | |||
| a1eb5fb15f | |||
| 9160b9b104 | |||
| 85a73c3c85 | |||
| 8389f9150a | |||
| 3075f4010f | |||
| 82e305e6a7 | |||
| 6351a335c0 | |||
| 6538daedef | |||
| 82fe859c84 | |||
| f567b03be5 | |||
| 7dc4e8dbc8 | |||
| 2a272a887e | |||
| 868509e00b | |||
| 477bdd5214 | |||
| 286cec8d77 | |||
| 58d4ee7d7d | |||
| 0e93a304f0 | |||
| 0adc4c7986 | |||
| a93424629d | |||
| da29766fd0 | |||
| dc7afbd07f | |||
| 67b174feac | |||
| b6b81b5d3d | |||
| 7d804b603d | |||
| 8696a15ce7 | |||
| 989fe39849 | |||
| ed1e432691 | |||
| 4f612e32d6 | |||
| e5d1e421a4 | |||
| 08ab8cc61d | |||
| c3b30815c8 | |||
| 5a4919efd2 | |||
| bb549fdc93 | |||
| 73e59cbba2 | |||
| 27727b6dcf | |||
| 06d2957407 | |||
| 8b08af6bcf | |||
| 78dad95ef6 | |||
| be9d56721e | |||
| e5785dd3ac | |||
| 11d912d14d | |||
| 807ac3fc9f | |||
| 45874d3749 | |||
| 594f69320a | |||
| d4927c9444 | |||
| 00dbd056d6 | |||
| 8f19ad8f66 | |||
| 2fdad54a7c | |||
| 5a5f040ed5 | |||
| 0ada9a2463 | |||
| 719bb981ec | |||
| 3c95d8744d | |||
| 63d1c9ee5e | |||
| 1ccd2e3c0a | |||
| cdbddabc1b | |||
| 9f6ca83f27 | |||
| f2ee99a477 | |||
| 7009ede095 | |||
| 2b530a1c53 | |||
| 33673f5921 | |||
| a7398d43e3 | |||
| 59b016a4a3 | |||
| 78aa5d51c6 | |||
| 95f584b554 | |||
| cf759d526d | |||
| 4c44ea12a4 | |||
| 9d09865907 | |||
| 5667d2d83e | |||
| 386f017fb7 | |||
| 87594e822d | |||
| ee832c7bd2 | |||
| 30042d5bc3 | |||
| 73cbb7a29c | |||
| c100fdde4f | |||
| 04e1496084 | |||
| 21d1852505 | |||
| 1502b0cfa7 | |||
| e7d6f65508 | |||
| 0e69a444a5 | |||
| 3b62999fde | |||
| 97431233ac | |||
| d49675afc8 | |||
| c1f7ab36a8 | |||
| eb14cc7bc6 | |||
| a47b9164af | |||
| 502e3ecb21 | |||
| 71903f174a | |||
| ab6606a295 | |||
| c4e2023992 | |||
| cb10bdda3f | |||
| f913472aae | |||
| af4826c578 | |||
| 63172ec66f | |||
| 3d6c339509 | |||
| 49f86c4eb9 | |||
| 7664bd248d | |||
| 73615aa0d6 | |||
| 81bb6699d8 | |||
| 93c67e3728 | |||
| 993816a34a | |||
| 3c0999c3a0 | |||
| 4528e7148f | |||
| 74042f5d85 | |||
| 92f6fbe04a | |||
| 5fa50250de | |||
| 8ee9daf7af | |||
| a54c8c1d25 | |||
| 8137ec8de2 | |||
| ae2a97576b | |||
| 3e830a086e | |||
| 618a1df3ea | |||
| 90cfc67c59 | |||
| cecc586868 | |||
| f956e7fab3 | |||
| 128b95cd83 | |||
| 895a5c2b2a | |||
| 91ce5cf8d7 | |||
| a283464331 | |||
| 1c3a2bd2e4 | |||
| 0b326a77c2 | |||
| d68008941e | |||
| b822d05a78 | |||
| 74bfed768c | |||
| ebfcce6d8d | |||
| d97d8f85e4 | |||
| 37c2c5029e | |||
| 105ff89fd8 | |||
| 0ac033106c | |||
| 21ec9fc568 | |||
| 2e3a7a31d4 | |||
| ecd7405a8c | |||
| 28abe360cb | |||
| 9cf88c00b0 | |||
| 8bbde4aacd | |||
| 00351136f2 | |||
| 30b85bd215 | |||
| 14b705b43e | |||
| 31fc0adabc | |||
| 1714da5d3b | |||
| 6ae47b5e01 | |||
| df8e4c2e2e | |||
| 6f9fa3719a | |||
| b9014c7219 | |||
| d44ab44620 | |||
| bcffe05744 | |||
| ed60734868 | |||
| e314ff8f43 | |||
| 1108684d06 | |||
| 6c0033c107 | |||
| 8a3e50ef9b | |||
| 05b572253e | |||
| f755a086cd | |||
| b0605323da | |||
| 585c2234eb | |||
| c5d7ea4245 | |||
| 281cd8a861 | |||
| 36400c8ad0 | |||
| fb00f697c5 | |||
| f529726218 | |||
| 059f3d8f43 | |||
| cae716925f | |||
| d29ee6da3d | |||
| 033b5211ea | |||
| 5f4f5baba4 | |||
| 4421046556 | |||
| 30482d5a34 | |||
| f12094c953 | |||
| c5147e7664 | |||
| 03b66bc6a2 | |||
| 7b40f2c949 | |||
| 785a922d03 | |||
| 5d2414977b | |||
| f9b8e46b32 | |||
| c79fc2f353 | |||
| e283e993bb | |||
| 3f1e74e71e | |||
| 300453e3e6 | |||
| ac8eea377e | |||
| cc44e8e9bf | |||
| 3860472e6b | |||
| 69029486b6 | |||
| b407f86d5e | |||
| 731adc7e31 | |||
| 858149e718 | |||
| 34e796f73c | |||
| 3ac71361b8 | |||
| e409b315b4 | |||
| 24eb768707 | |||
| 17ad13d559 | |||
| 3b71212905 | |||
| 16a29c5e31 | |||
| e421164282 | |||
| de01157964 | |||
| 8ef51ec318 | |||
| d2139d70ad | |||
| d1a37366be | |||
| 52d7c8a6cb | |||
| c62e56e5a3 | |||
| 6b89092adf | |||
| 118a56b8d6 | |||
| 7fb993014c | |||
| 09f72af66c | |||
| 815f111ca6 | |||
| 40d2bf0c22 | |||
| a77b7a0626 | |||
| 1a00b4b779 | |||
| 6c5c47240c | |||
| 3c32da970b | |||
| 9cff62c5ba | |||
| 424f93b4da | |||
| 3a23a412c8 | |||
| 9d64989ef1 | |||
| da62d26409 | |||
| a350077e5c | |||
| 36b6cd3c98 | |||
| 203b457ad0 | |||
| 0873b3bd12 | |||
| a7f7e3fca1 | |||
| a52beffef5 | |||
| e6f6d61b84 | |||
| 4a167c9335 | |||
| 16857a9968 | |||
| 094a20c379 | |||
| 0d3cf4ce0d | |||
| 8a2d1c42a8 | |||
| a5b44175a3 | |||
| db5c9479df | |||
| 16f238f34b | |||
| a57b5cd6ee | |||
| 5e54cb8fda |
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Data not recorded
|
||||||
|
about: Somehow OpenTracks did not record GPS data
|
||||||
|
title: ''
|
||||||
|
labels: potential bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Please describe the problem and how to reproduce it:**
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
**Checklist**
|
||||||
|
|
||||||
|
- [ ] Consulted [https://dontkillmyapp.com/]
|
||||||
|
- [ ] Power management: battery optimization is disabled for OpenTracks
|
||||||
|
|
||||||
|
**Technical information**
|
||||||
|
|
||||||
|
- Device: [e.g. Nexus 7 (2013)]
|
||||||
|
- OS: [e.g. LineageOS 15.1]
|
||||||
|
- OpenTracks version: [e.g. v3.2.4]
|
||||||
|
- OpenTracks commit id (only for nightly builds): [e.g. 4b333bb]
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#https://github.com/marketplace/actions/android-emulator-runner
|
#https://github.com/marketplace/actions/android-emulator-runner
|
||||||
name: Build nightly
|
name: Build APK
|
||||||
on: [ push ]
|
on:
|
||||||
|
push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
nightly-build:
|
apk-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
@@ -14,7 +15,7 @@ jobs:
|
|||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
java-version: '11'
|
java-version: '11'
|
||||||
|
|
||||||
- name: Assemble nighlty APK
|
- name: Assemble APK
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo ${NIGHTLY_STORE_FILE} | base64 -d > KEY_NIGHTLY.jks
|
echo ${NIGHTLY_STORE_FILE} | base64 -d > KEY_NIGHTLY.jks
|
||||||
@@ -28,7 +29,7 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: OpenTracks-nightly.apk
|
name: OpenTracks-APK.apk
|
||||||
path: ./build/outputs/apk/nightly/*.apk
|
path: ./build/outputs/apk/nightly/*.apk
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ name: Linting
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyse:
|
analyse:
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
# We have flaky test results due to performance limitations in Github Actions.
|
||||||
|
# Happens too often nowadays; See https://github.com/OpenTracksApp/OpenTracks/issues/1409
|
||||||
|
|
||||||
#https://github.com/marketplace/actions/android-emulator-runner
|
#https://github.com/marketplace/actions/android-emulator-runner
|
||||||
name: Test
|
name: Test
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@@ -23,7 +26,7 @@ jobs:
|
|||||||
java-version: '11'
|
java-version: '11'
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
uses: reactivecircus/android-emulator-runner@v2.23.0
|
uses: reactivecircus/android-emulator-runner@v2.26.0
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
@@ -60,7 +60,6 @@ captures/
|
|||||||
.idea/encodings.xml
|
.idea/encodings.xml
|
||||||
.idea/jsLibraryMappings.xml
|
.idea/jsLibraryMappings.xml
|
||||||
.idea/libraries/
|
.idea/libraries/
|
||||||
.idea/misc.xml
|
|
||||||
.idea/modules.xml
|
.idea/modules.xml
|
||||||
.idea/scopes/scope_settings.xml
|
.idea/scopes/scope_settings.xml
|
||||||
.idea/shelf/
|
.idea/shelf/
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
|||||||
<th>Free (F-Droid)</th>
|
<th>Free (F-Droid)</th>
|
||||||
<th>Free (Nightly for F-Droid)</th>
|
<th>Free (Nightly for F-Droid)</th>
|
||||||
<th>Donations</th>
|
<th>Donations</th>
|
||||||
<th>Translations</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
@@ -27,47 +26,26 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
|||||||
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45" align="middle">
|
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45" align="middle">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
|
||||||
<a href="https://weblate.bubu1.eu/engage/OpenTracks/">
|
|
||||||
<img src="https://weblate.bubu1.eu/widgets/OpenTracks/-/opentracks/svg-badge.svg" alt="Translation status" />
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<img alt="OpenTracks version published on F-Droid" src="https://img.shields.io/f-droid/v/de.dennisguse.opentracks.svg" align="middle" >
|
<img alt="OpenTracks version published on F-Droid" src="https://img.shields.io/f-droid/v/de.dennisguse.opentracks.svg" align="middle" >
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td align="center">
|
|
||||||
<a href="bitcoin:bc1qckpls3lpjlcpyxzm66hcy65hnesas9zgacy6yc">
|
|
||||||
<img alt="bitcoin:bc1qckpls3lpjlcpyxzm66hcy65hnesas9zgacy6yc" src="promotion/donations-bitcoin.png" height="90" align="middle">
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">
|
<a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">
|
||||||
<img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" height="60" align="middle">
|
<img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" height="60" align="middle">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://www.amazon.de/dp/B09K2KNQ7X/">
|
|
||||||
<img alt="Get it on Amazon App Store" src="https://images-na.ssl-images-amazon.com/images/G/01/mobile-apps/devportal2/res/images/amazon-appstore-badge-english-white.png" height="40" align="middle">
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<a href="https://hosted.weblate.org/engage/opentracks/">
|
||||||
|
<img src="https://hosted.weblate.org/widgets/opentracks/-/horizontal-auto.svg" alt="Translation status" />
|
||||||
|
</a>
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="23%" src="fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot1.png">
|
<img width="23%" src="fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot1.png">
|
||||||
<img width="23%" src="fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot2.png">
|
<img width="23%" src="fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot2.png">
|
||||||
@@ -86,19 +64,19 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
|||||||
* __Voice announcements__
|
* __Voice announcements__
|
||||||
* __Photos and Markers:__ mark interesting locations while tracking
|
* __Photos and Markers:__ mark interesting locations while tracking
|
||||||
* __Export:__
|
* __Export:__
|
||||||
* export tracks either as KMZ (incl. photos), KML, or GPX
|
* export tracks either as [KMZ 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html) (incl. photos), [KML 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html), or [GPX 1.1](https://www.topografix.com/GPX/1/1/)
|
||||||
* export automatically after each recording (e.g., to sync via [Nextcloud](https://nextcloud.com/))
|
* export automatically after each recording (e.g., to sync via [Nextcloud](https://nextcloud.com/))
|
||||||
* avoid duplication: each exported file contain a random unique identifier (i.e., `opentracks:trackid`)
|
* avoid duplication: each exported file contain a random unique identifier (i.e., `opentracks:trackid`)
|
||||||
* __Altitude:__
|
* __Altitude:__
|
||||||
* gain/loss via barometric sensor (if present)
|
* gain/loss via barometric sensor (if present)
|
||||||
* shown in EGM2008 (above mean sea level); exported as WGS84
|
* shown in EGM2008 (above mean sea level); exported as WGS84
|
||||||
* __Bluetooth LE sensors:__
|
* __Bluetooth LE sensors:__
|
||||||
* heart rate
|
* heart rate
|
||||||
* cycling: speed and distance
|
* cycling: speed and distance
|
||||||
* cycling: cadence
|
* cycling: cadence
|
||||||
* cycling: power meter
|
* cycling: power meter
|
||||||
* running: speed and cadence
|
* running: speed and cadence
|
||||||
* support for BLE sensor training only (i.e., without GPS) for indoor training
|
* support for BLE sensor training only (i.e., without GPS) for indoor training
|
||||||
|
|
||||||
An overview of tested sensors: [README_TESTED_SENSORS.md](README_TESTED_SENSORS.md)
|
An overview of tested sensors: [README_TESTED_SENSORS.md](README_TESTED_SENSORS.md)
|
||||||
|
|
||||||
@@ -117,7 +95,7 @@ OpenTracks can be used with [Gadgetbridge](https://www.gadgetbridge.org/):
|
|||||||
__Only required permission:__
|
__Only required permission:__
|
||||||
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
||||||
|
|
||||||
### API
|
### Public API
|
||||||
|
|
||||||
OpenTracks includes an API for starting/stopping recording by another installed application (e.g., [Automate](https://llamalab.com/automate/), [Tasker](https://tasker.joaoapps.com), or [Easer](https://github.com/renyuneyun/Easer)).
|
OpenTracks includes an API for starting/stopping recording by another installed application (e.g., [Automate](https://llamalab.com/automate/), [Tasker](https://tasker.joaoapps.com), or [Easer](https://github.com/renyuneyun/Easer)).
|
||||||
The API can be invoked by sending an explicit Intent to start an activity.
|
The API can be invoked by sending an explicit Intent to start an activity.
|
||||||
@@ -129,26 +107,50 @@ The API can be invoked by sending an explicit Intent to start an activity.
|
|||||||
* Nightly: `de.dennisguse.opentracks.nightly`
|
* Nightly: `de.dennisguse.opentracks.nightly`
|
||||||
|
|
||||||
`Class`:
|
`Class`:
|
||||||
|
|
||||||
* **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording`
|
* **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording`
|
||||||
|
* **Stop a recording:** `de.dennisguse.opentracks.publicapi.StopRecording`
|
||||||
|
|
||||||
For testing via adb: `adb shell am start -n "package/class"`
|
For testing via adb: `adb shell am start -e someParameter someValue -n "package/class"`
|
||||||
|
|
||||||
The Start/Stop API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings.
|
`StartRecording` supports the following parameters:
|
||||||
|
|
||||||
## Custom Dashboards (incl. map)
|
* Set track data: `TRACK_NAME`, `TRACK_DESCRIPTION`, `TRACK_CATEGORY`, and `TRACK_ICON` (non-localized identifier see [/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java#L38](/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java#L38)).
|
||||||
As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live tracks.
|
NOTE: if `TRACK_ICON` is not present, `TRACK_CATEGORY` will be used to determine the icon (localized).
|
||||||
|
* Send recorded data to another application via _Dashboard API_: `STATS_TARGET_PACKAGE` and `STATS_TARGET_CLASS`
|
||||||
|
|
||||||
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which 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 statistics on supported wearables.
|
The Public API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings.
|
||||||
|
|
||||||
Alternatively, recorded tracks can be shared as KMZ/GPX with installed applications (e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand)).
|
## File formats compatibility with open-source software
|
||||||
However, this is rather slow and does not provide updates while recording.
|
|
||||||
|
| | [GPX 1.1](https://www.topografix.com/GPX/1/1/) | [KML 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html) | [KMZ 2.3](https://docs.opengeospatial.org/is/12-007r2/12-007r2.html) |
|
||||||
|
|------------------------------------------------------|------------------------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------|
|
||||||
|
| [OpenLayers 7.1.0](https://openlayers.org/) | ? | [no](https://github.com/openlayers/openlayers/issues/14104) | [no](https://github.com/openlayers/openlayers/issues/14104) |
|
||||||
|
| [Golden Cheetah 3.5](https://www.goldencheetah.org/) | ? | [no](https://github.com/GoldenCheetah/GoldenCheetah/issues/4271) | [no](https://github.com/GoldenCheetah/GoldenCheetah/issues/4271) |
|
||||||
|
| [GpxPod](https://apps.nextcloud.com/apps/gpxpod) | ? | ? | ? |
|
||||||
|
| [OsmAnd](https://github.com/osmandapp/OsmAnd) | ? | [no](https://github.com/osmandapp/OsmAnd/issues/15271) | [no](https://github.com/osmandapp/OsmAnd/issues/15271) |
|
||||||
|
| [FitTrackee](https://github.com/SamR1/FitTrackee) | yes | n/a | n/a |
|
||||||
|
|
||||||
|
## Dashboard API (incl. map)
|
||||||
|
|
||||||
|
As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live
|
||||||
|
tracks.
|
||||||
|
|
||||||
|
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which
|
||||||
|
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
|
||||||
|
statistics on supported wearables.
|
||||||
|
|
||||||
|
Alternatively, recorded tracks can be shared as KMZ/GPX with installed applications (
|
||||||
|
e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand)). However, this is rather
|
||||||
|
slow and does not provide updates while recording.
|
||||||
|
|
||||||
The developer documentation is in [README_API.md](README_API.md).
|
The developer documentation is in [README_API.md](README_API.md).
|
||||||
|
|
||||||
## Project history
|
## Project history
|
||||||
|
|
||||||
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
|
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
|
||||||
Initially, _My Tracks_ was initially released by Google in 2010 as [open-source software](http://google-latlong.blogspot.fr/2010/05/code-for-my-tracks-is-now-yours.html).
|
_My Tracks_ was initially released by Google in 2010 as [open-source software](http://google-latlong.blogspot.fr/2010/05/code-for-my-tracks-is-now-yours.html).
|
||||||
In 2016, [Google decided to discontinue](https://support.google.com/maps/answer/6333516) _My Tracks_ and stopped distributing it via the Google Play store in April 2016.
|
In 2016, [Google decided to discontinue](https://support.google.com/maps/answer/6333516) _My Tracks_ and stopped distributing it via the Google Play store in April 2016.
|
||||||
Then [Plonk42](https://github.com/plonk42) conducted some maintenance work until 2016, so _My Tracks_ could still be used (based upon version _Google's MyTracks_ version 2.0.6).
|
Then [Plonk42](https://github.com/plonk42) conducted some maintenance work until 2016, so _My Tracks_ could still be used (based upon version _Google's MyTracks_ version 2.0.6).
|
||||||
Plonk42's version is available [here](https://github.com/Plonk42/mytracks).
|
Plonk42's version is available [here](https://github.com/Plonk42/mytracks).
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ Application id: de.dennisguse.opentracks
|
|||||||
It if it properly tagged F-Droid takes care of building the app and publishing.
|
It if it properly tagged F-Droid takes care of building the app and publishing.
|
||||||
Usually, it takes two days before the update is published (build, signed, and published).
|
Usually, it takes two days before the update is published (build, signed, and published).
|
||||||
|
|
||||||
The recent build activity can be found [here](https://f-droid.org/wiki/index.php?title=Special:RecentChanges&days=7&from=&hidebots=0&hideanons=1&hideliu=1&limit=500)
|
The recent build activity can be found [here](https://monitor.f-droid.org/builds/build)
|
||||||
|
|
||||||
## Google Play Store
|
## Google Play Store
|
||||||
Application id: de.dennisguse.opentracks.playstore
|
Application id: `de.dennisguse.opentracks.playstore`
|
||||||
|
|
||||||
Requirement: `gem install fastlane`
|
Requirement: `gem install fastlane`
|
||||||
|
|
||||||
@@ -35,4 +35,6 @@ Supported languages: https://support.google.com/googleplay/android-developer/tab
|
|||||||
|
|
||||||
## Translations (localization)
|
## Translations (localization)
|
||||||
|
|
||||||
Translations of the OpenTracks are handled in Weblate: [https://weblate.bubu1.eu/projects/OpenTracks/](https://weblate.bubu1.eu/projects/OpenTracks/).
|
Translations of the OpenTracks are handled in
|
||||||
|
Weblate: [https://hosted.weblate.org/projects/opentracks/](https://hosted.weblate.org/projects/opentracks)
|
||||||
|
.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 0x180D: Heartrate Service
|
## 0x180D: Heartrate Service
|
||||||
|
|
||||||
* Decathlon|Geonaute|Kalenji Dual HRM Belt
|
* Decathlon/Geonaute/Kalenji Dual HRM Belt
|
||||||
* moofit heart rate monitor
|
* moofit heart rate monitor
|
||||||
* Polar H7
|
* Polar H7
|
||||||
* Polar H10
|
* Polar H10
|
||||||
@@ -38,17 +38,13 @@ However, often only one value is provided.
|
|||||||
|
|
||||||
We only support _Instantaneous Power_.
|
We only support _Instantaneous Power_.
|
||||||
|
|
||||||
_WARNING_: we only support physically movements with valid GPS coordinates.
|
For cycling (incl. cadence):
|
||||||
Using a device indoors (no GPS available) will only show the current power values, but won't store anything.
|
|
||||||
Also the distance is not computed.
|
|
||||||
|
|
||||||
For cycling:
|
|
||||||
* Assioma Duo Powermeter
|
* Assioma Duo Powermeter
|
||||||
* Elite drivo II
|
* Elite drivo II
|
||||||
* QUARQ Red DZero Powermeter
|
* QUARQ Red DZero Powermeter
|
||||||
* Tacx Satori Smart
|
* Tacx Satori Smart
|
||||||
* Wahoo Kickr v4.0
|
* Wahoo Kickr v4.0
|
||||||
* Rotor 2INpower DM Road (only supports power measurement, cadence measurement is propietary @ firmware v1.061)
|
* Rotor 2INpower DM Road (only supports power measurement, cadence measurement is proprietary @ firmware v1.061)
|
||||||
|
|
||||||
For running:
|
For running:
|
||||||
* Stryd
|
* Stryd
|
||||||
@@ -67,12 +63,12 @@ There are smartphones that have a barometric sensor that OpenTracks uses to comp
|
|||||||
|
|
||||||
In our tests there are smartphones whose barometric sensor works well and others don't. Here is a list of the smartphones tested:
|
In our tests there are smartphones whose barometric sensor works well and others don't. Here is a list of the smartphones tested:
|
||||||
|
|
||||||
|Brand|Model|Android Version|Tests|
|
| Brand | Model | Android Version | Tests |
|
||||||
|-----|-----|---------------|-----------|
|
|--------|--------------------|-----------------|--------------------------------------------------------------------------------|
|
||||||
|Google|Pixel|LineageOS 17.1|Ok|
|
| Google | Pixel | LineageOS 17.1 | Ok |
|
||||||
|Google|Pixel 2 XL|LineageOS 17.1|Ok on the bike handlebars but it fails when I carry it in a pocket or backpack|
|
| Google | Pixel 2 XL | LineageOS 17.1 | Ok on the bike handlebars but it fails when I carry it in a pocket or backpack |
|
||||||
|Google|Pixel 3|Android 11|Failure|
|
| Google | Pixel 3 | Android 11 | Failure |
|
||||||
|Google|Pixel 3a|Android 11|Ok|
|
| Google | Pixel 3a | Android 11 | Ok |
|
||||||
|Google|Pixel 3a|Lineage 18.1|Ok|
|
| Google | Pixel 3a | Lineage 18.1 | Ok |
|
||||||
|Google|Pixel 4a|Android 11|Ok|
|
| Google | Pixel 4a | Android 11 | Ok |
|
||||||
|Sony|Xperia XZ1 Compact|LineageOS 16.1|Failure|
|
| Sony | Xperia XZ1 Compact | LineageOS 16.1 | Failure |
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ set -e
|
|||||||
# Folder where svg screenshots are expected.
|
# Folder where svg screenshots are expected.
|
||||||
SRC_DIR="screenshots-svg/"
|
SRC_DIR="screenshots-svg/"
|
||||||
# Folder where png files will be saved.
|
# Folder where png files will be saved.
|
||||||
DST_DIR="fastlane/metadata/android/en-US/phoneScreenshots/"
|
DST_DIR="fastlane/metadata/android/en-US/images/phoneScreenshots/"
|
||||||
|
|
||||||
echo "Exporting svg files to png..."
|
echo "Exporting svg files to png..."
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.1.3'
|
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdkVersion 31
|
compileSdk 33
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
@@ -59,16 +59,18 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "de.dennisguse.opentracks"
|
applicationId "de.dennisguse.opentracks"
|
||||||
versionCode 4816
|
versionCode 5168
|
||||||
versionName "v3.27.0"
|
versionName "v4.3.1"
|
||||||
|
|
||||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||||
|
|
||||||
minSdkVersion 21
|
minSdk 21
|
||||||
targetSdkVersion 31
|
targetSdk 33
|
||||||
|
|
||||||
testInstrumentationRunner "de.dennisguse.opentracks.TestRunner"
|
testInstrumentationRunner "de.dennisguse.opentracks.TestRunner"
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
|
|
||||||
|
resConfigs "ar", "bg", "ca", "cs", "da", "de", "el", "en", "es", "et", "eu", "fa", "fi", "fr", "ga", "gl", "hi", "hr", "hu", "in", "it", "iw", "ja", "ko", "lt", "lv", "mo", "ms", "nb", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tl", "tr", "uk", "vi", "zh"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
nightly {
|
nightly {
|
||||||
@@ -81,6 +83,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace 'de.dennisguse.opentracks'
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
@@ -100,6 +104,7 @@ android {
|
|||||||
releasePlayStore {
|
releasePlayStore {
|
||||||
applicationIdSuffix ".playstore"
|
applicationIdSuffix ".playstore"
|
||||||
versionNameSuffix "-PlayStore"
|
versionNameSuffix "-PlayStore"
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,20 +122,23 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
implementation 'androidx.preference:preference:1.2.0'
|
implementation 'androidx.preference:preference:1.2.0'
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
|
implementation 'com.google.android.material:material:1.8.0'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
|
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||||
|
implementation 'androidx.mediarouter:mediarouter:1.3.1'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test:core:1.4.0'
|
androidTestImplementation 'androidx.test:core:1.5.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
androidTestImplementation 'androidx.test:rules:1.5.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
androidTestImplementation 'androidx.test:runner:1.5.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
androidTestImplementation 'org.mockito:mockito-android:4.5.1'
|
androidTestImplementation 'org.mockito:mockito-android:5.2.0'
|
||||||
|
|
||||||
androidTestUtil 'androidx.test:orchestrator:1.4.1'
|
androidTestUtil 'androidx.test:orchestrator:1.4.2'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,19 @@
|
|||||||
type="xsd:float">
|
type="xsd:float">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation xml:lang="en">
|
<xsd:documentation xml:lang="en">
|
||||||
Accuracy in meters of the current TrackPoint; 68% chance that the actual location is
|
Horizontal accuracy in meters of the current TrackPoint; 68% chance that the actual
|
||||||
|
location is
|
||||||
|
within this radius around the measured location.
|
||||||
|
Only used in GPX.
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="accuracy_vertical"
|
||||||
|
type="xsd:float">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation xml:lang="en">
|
||||||
|
Vertical accuracy in meters of the current TrackPoint; 68% chance that the actual
|
||||||
|
location is
|
||||||
within this radius around the measured location.
|
within this radius around the measured location.
|
||||||
Only used in GPX.
|
Only used in GPX.
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
|
|||||||
@@ -1,37 +1,119 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg xmlns:cc="http://creativecommons.org/ns#"
|
<svg xmlns:cc="http://creativecommons.org/ns#"
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
enable-background="new 0 0 95.334 100"
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
height="100"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
id="Ebene_1"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
version="1.1"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
viewBox="0 0 100 100"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
width="100"
|
enable-background="new 0 0 95.334 100"
|
||||||
x="0px"
|
height="100"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
id="Ebene_1"
|
||||||
y="0px"
|
version="1.1"
|
||||||
xml:space="preserve"><metadata
|
viewBox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="LOGO.svg"
|
||||||
|
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1011"
|
||||||
|
id="namedview10"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="7.94"
|
||||||
|
inkscape:cx="50"
|
||||||
|
inkscape:cy="50"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Ebene_1" /><metadata
|
||||||
id="metadata16"><rdf:RDF><cc:Work
|
id="metadata16"><rdf:RDF><cc:Work
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata>
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
<defs id="defs14" />
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata>
|
||||||
<g id="g9"
|
<defs
|
||||||
transform="translate(-1.0593197,1.9067775)">
|
id="defs14"><linearGradient
|
||||||
<linearGradient gradientUnits="userSpaceOnUse"
|
inkscape:collect="always"
|
||||||
id="SVGID_1_"
|
id="linearGradient862"><stop
|
||||||
x1="28.7554"
|
style="stop-color:#ff6d00;stop-opacity:1;"
|
||||||
x2="82.789497"
|
offset="0"
|
||||||
y1="81.535202"
|
id="stop858" /><stop
|
||||||
y2="9.2979002">
|
style="stop-color:#ff6d00;stop-opacity:0;"
|
||||||
<stop style="stop-color:#FBB22F"
|
offset="1"
|
||||||
id="stop2"
|
id="stop860" /></linearGradient><linearGradient
|
||||||
offset="0" />
|
gradientUnits="userSpaceOnUse"
|
||||||
<stop style="stop-color:#F58820"
|
id="SVGID_1_"
|
||||||
id="stop4"
|
x1="28.7554"
|
||||||
offset="1" />
|
x2="82.789497"
|
||||||
|
y1="81.535202"
|
||||||
|
y2="9.2979002"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient849)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#FBB22F;fill-opacity:1;fill:url(#linearGradient849)"
|
||||||
|
id="stop853"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#F58820;fill-opacity:1;fill:url(#linearGradient849)"
|
||||||
|
id="stop855"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient847"><stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop843" /><stop
|
||||||
|
style="stop-color:#000000;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop845" /></linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient847"
|
||||||
|
id="linearGradient849"
|
||||||
|
x1="83.161415"
|
||||||
|
y1="8.9067831"
|
||||||
|
x2="10.194695"
|
||||||
|
y2="92.068085"
|
||||||
|
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient862"
|
||||||
|
id="linearGradient866"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="62.43222"
|
||||||
|
y1="35.349697"
|
||||||
|
x2="9.7942638"
|
||||||
|
y2="93.02298" /></defs>
|
||||||
|
<g
|
||||||
|
id="g9"
|
||||||
|
transform="translate(-1.0593197,1.9067775)"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient849)">
|
||||||
|
<linearGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="SVGID_1_-3"
|
||||||
|
x1="28.7554"
|
||||||
|
x2="82.789497"
|
||||||
|
y1="81.535202"
|
||||||
|
y2="9.2979002"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient849)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#FBB22F;fill-opacity:1;fill:url(#linearGradient849)"
|
||||||
|
id="stop2"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#F58820;fill-opacity:1;fill:url(#linearGradient849)"
|
||||||
|
id="stop4"
|
||||||
|
offset="1" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<path style="fill:url(#SVGID_1_)"
|
<path
|
||||||
d="M 83.548,10.927 C 84.255,8.511 83.102,7.649 80.985,9.01 L 11.146,53.921 c -2.117,1.361 -1.795,2.628 0.714,2.815 L 40.865,58.9 c 2.51,0.188 5.291,2.267 6.18,4.621 l 10.282,27.208 c 0.89,2.354 2.195,2.304 2.902,-0.111 z"
|
style="fill:url(#linearGradient866);fill-opacity:1"
|
||||||
id="path7" />
|
d="M 83.548,10.927 C 84.255,8.511 83.102,7.649 80.985,9.01 L 11.146,53.921 c -2.117,1.361 -1.795,2.628 0.714,2.815 L 40.865,58.9 c 2.51,0.188 5.291,2.267 6.18,4.621 l 10.282,27.208 c 0.89,2.354 2.195,2.304 2.902,-0.111 z"
|
||||||
|
id="path7" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
enable-background="new 0 0 95.334 100"
|
||||||
|
height="100"
|
||||||
|
id="Ebene_1"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
x="0px"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
y="0px"
|
||||||
|
xml:space="preserve"><metadata
|
||||||
|
id="metadata16"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata>
|
||||||
|
<defs id="defs14" />
|
||||||
|
<g id="g9"
|
||||||
|
transform="translate(-1.0593197,1.9067775)">
|
||||||
|
<linearGradient gradientUnits="userSpaceOnUse"
|
||||||
|
id="SVGID_1_"
|
||||||
|
x1="28.7554"
|
||||||
|
x2="82.789497"
|
||||||
|
y1="81.535202"
|
||||||
|
y2="9.2979002">
|
||||||
|
<stop style="stop-color:#FBB22F"
|
||||||
|
id="stop2"
|
||||||
|
offset="0" />
|
||||||
|
<stop style="stop-color:#F58820"
|
||||||
|
id="stop4"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_1_)"
|
||||||
|
d="M 83.548,10.927 C 84.255,8.511 83.102,7.649 80.985,9.01 L 11.146,53.921 c -2.117,1.361 -1.795,2.628 0.714,2.815 L 40.865,58.9 c 2.51,0.188 5.291,2.267 6.18,4.621 l 10.282,27.208 c 0.89,2.354 2.195,2.304 2.902,-0.111 z"
|
||||||
|
id="path7" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
height="125"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 125 125"
|
||||||
|
width="125"
|
||||||
|
sodipodi:docname="ic_button_done.svg"
|
||||||
|
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1011"
|
||||||
|
id="namedview9"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="2.2457711"
|
||||||
|
inkscape:cx="104.26334"
|
||||||
|
inkscape:cy="71.321036"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<defs
|
||||||
|
id="defs6" />
|
||||||
|
<circle
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ff6d00;stroke-width:5.03185;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
cx="62.5"
|
||||||
|
cy="62.5"
|
||||||
|
id="path12"
|
||||||
|
r="59.984074" />
|
||||||
|
<metadata
|
||||||
|
id="metadata8">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:title></dc:title>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<circle
|
||||||
|
style="fill:#ff6d00;fill-opacity:1;stroke:none;stroke-width:6.91728;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
cx="62.5"
|
||||||
|
cy="62.5"
|
||||||
|
id="path835"
|
||||||
|
r="50" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:6.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 38.620483,63.865643 52.899055,78.144215 86.379516,44.663754"
|
||||||
|
id="path1000" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
height="125"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 125 125"
|
||||||
|
width="125"
|
||||||
|
sodipodi:docname="ic_button_resume.svg"
|
||||||
|
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1011"
|
||||||
|
id="namedview9"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="3.176"
|
||||||
|
inkscape:cx="85.245821"
|
||||||
|
inkscape:cy="70.9649"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<defs
|
||||||
|
id="defs6" />
|
||||||
|
<circle
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ff6d00;stroke-width:5.03185;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
cx="62.5"
|
||||||
|
cy="62.5"
|
||||||
|
id="path12"
|
||||||
|
r="59.984074" />
|
||||||
|
<circle
|
||||||
|
style="fill:#ff6d00;fill-opacity:1;stroke:none;stroke-width:6.91728;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
cx="62.5"
|
||||||
|
cy="62.5"
|
||||||
|
id="path835"
|
||||||
|
r="50" />
|
||||||
|
<metadata
|
||||||
|
id="metadata8">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:title></dc:title>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6.67087;stroke-linecap:round;stroke-opacity:1"
|
||||||
|
id="path837"
|
||||||
|
sodipodi:sides="3"
|
||||||
|
sodipodi:cx="61.453945"
|
||||||
|
sodipodi:cy="62.5"
|
||||||
|
sodipodi:r1="26.146271"
|
||||||
|
sodipodi:r2="13.073136"
|
||||||
|
sodipodi:arg1="0"
|
||||||
|
sodipodi:arg2="1.0471976"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="M 87.600216,62.5 67.990513,73.821668 48.38081,85.143335 l -10e-7,-22.643336 10e-7,-22.643334 19.609704,11.321667 z"
|
||||||
|
inkscape:transform-center-x="-6.5365678" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -7,5 +7,5 @@ Changes:
|
|||||||
Bugfix:
|
Bugfix:
|
||||||
- Speech announcements use MAY_DUCK (again)
|
- Speech announcements use MAY_DUCK (again)
|
||||||
- ChartView shows markers (again)
|
- ChartView shows markers (again)
|
||||||
- Fixed landscape layout of TrackListActivity
|
- Fixed landscape recordingLayout of TrackListActivity
|
||||||
- Request legacy file API behavior (necessary for Android 10)
|
- Request legacy file API behavior (necessary for Android 10)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
v3.28.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Configurable filename for export/sharing (default: {starttime}_{name}.{suffix})
|
||||||
|
- Vertical GPS accuracy is now stored and can be exported/imported
|
||||||
|
(API level >= 26).
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
v4.0.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- UI refactoring with a Bottom App Bar.
|
||||||
|
- Public API: implemented STOP properly.
|
||||||
|
- Cleanup: use explicit preference identifiers for TrackFileFormat.
|
||||||
|
- Improvements on BLE handler.
|
||||||
|
- Add exception handler and show error activity so users can send reports about bugs.
|
||||||
|
- Android 13: launcher icon, provide a themed icon.
|
||||||
|
- Change track title capitalization to sentences.
|
||||||
|
- Translations updated.
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Sharing track added file suffix twice.
|
||||||
|
- Unit system not loaded correctly.
|
||||||
|
- File format template was not loaded (NPE).
|
||||||
|
- Public API: respect post-workout export.
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Move to androix.constraintlayout.
|
||||||
|
- UI tests slightly more robust.
|
||||||
|
- Refactor permission request.
|
||||||
|
- Upgrade to gradlew 7.4.2
|
||||||
|
- Bump material from 1.5.0 to 1.6.0
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
v4.0.1: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Voice announcements are now configurable
|
||||||
|
- Fullscreen mode now also hides Android's navigation bar
|
||||||
|
- Connection to BLE sensors should now be faster
|
||||||
|
- Allow to reset settings while recording
|
||||||
|
- Allow to change import/export settings while recording
|
||||||
|
- KML/KMZ: do not use icons to be loaded from Google
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- TrackStoppedActivity now works on smaller screens
|
||||||
|
- Requests permissions on track list
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
v4.0.2: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Add nautical miles
|
||||||
|
- Settings can be reset while recording
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Voice announcement rounding
|
||||||
|
- Chart: elevation was weirdly smoothed
|
||||||
|
- Export was not checking if file exists
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.0.3: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Max. speed as reported by sensor (GPS or BLE)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Prevent crash if OSM Dashboard is not installed
|
||||||
|
- GPX track export: do not export empty track segments
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
v4.0.4: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Store BLE sensor data even without distance (every 10s)
|
||||||
|
- Public API: allows setting name, category, and description
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Crash when taking a picture and rotating the phone
|
||||||
|
-
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Target SDK 33
|
||||||
|
- Barometer uses interval of 5s
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.0.5: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- PlayStore relase get's another logo
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Interval list shows "-" if gain/loss is not present
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
v4.0.6: OpenTracks
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- EGM2008 offset computed wrong for negative longitudes
|
||||||
|
- PublicAPI crashed if OpenTracks was in background (API26+)
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v4.0.7: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- GPS signal lost timeout: 30s
|
||||||
|
- Android13: request permission to show notifications
|
||||||
|
- Faster deletion of tracks (vacuum database only if needed)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- PublicAPI stop command resulted in crash (introduced in v4.0.6)
|
||||||
|
- Permissions: request all permissions during on startup
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v4.0.8: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Altitude always shown in m/ft
|
||||||
|
- Show track timezone if different than device timezone
|
||||||
|
- PublicAPI: support setting the track icon explicitly
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Introduced DistanceFormatter
|
||||||
|
- Upgrade to AGP 7.3/desugar for Duration.class
|
||||||
|
- Android12+: do splashscreen via Androidx
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.1.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Export KML/KMZ version 2.3 only (was 2.2)
|
||||||
|
- For crank-based powermeters: fetch cadence
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Workaround for crash on "import all"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
v4.1.1: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Add introduction screen (show once)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Do not crash if no GPS device is present
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v4.1.2: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Voice announcements only use on decimal for distance
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Crash when stopping (race condition)
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Github actions: disabled instrumentation testing (too slow)
|
||||||
|
- Tests are done with only fake GPS data
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.2.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Show heartrate zone information
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Migrated to hosted.weblate.org
|
||||||
|
- Recording UI uses Views directly
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.2.1: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Speed sensor: acceptable wheel diameter is 100mm-4000mm
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Reconnect to a sensor if connection is lost
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
v4.2.2: OpenTracks
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Track icon wrongly shown in dialog
|
||||||
|
- Textcolor for heartrate zone 1 was ignoring theme
|
||||||
|
- Not all activityTypes were shown in dropdownlist
|
||||||
|
- Crash due to color not found
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
v4.3.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Allow backups (incl. encrypted to the Google)
|
||||||
|
- Android 13: allow app-specific language settings
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.3.1: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Setting to skip voice announcements on device speaker
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- GPS disabled warning was falsely shown
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 574 KiB After Width: | Height: | Size: 560 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 812 KiB |
|
Before Width: | Height: | Size: 456 KiB After Width: | Height: | Size: 462 KiB |
|
Before Width: | Height: | Size: 630 KiB After Width: | Height: | Size: 695 KiB |
|
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 467 KiB |
|
Before Width: | Height: | Size: 508 KiB After Width: | Height: | Size: 509 KiB |
|
Before Width: | Height: | Size: 798 KiB After Width: | Height: | Size: 872 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
v3.20.2 : OpenTracks
|
||||||
|
|
||||||
|
Changements :
|
||||||
|
- Le gain et la perte d'altitude sont des entiers au lieu de floats
|
||||||
|
- Demander la permission avant d'utiliser Bluetooth par un message Toast
|
||||||
|
|
||||||
|
Correction d'un bug :
|
||||||
|
- Définir FLAG_IMMUTABLE pour PendingIntents pour éviter un crash sur Android 12
|
||||||
|
- Le capteur de cadence renvoie 0 au lieu de None lorsque l'utilisateur ne pédale pas.
|
||||||
|
- Le capteur de vitesse renvoie 0 au lieu de la dernière vitesse connue quand c'est arrêté
|
||||||
|
- Avec les capteurs, le temps de déplacement s'arrête lorsqu'il n'est pas en mouvement
|
||||||
@@ -7,5 +7,11 @@ Fonctionnalités :
|
|||||||
* Dénivelé positif et négatif: via capteur de pression barométrique
|
* Dénivelé positif et négatif: via capteur de pression barométrique
|
||||||
* Synthèse vocale
|
* Synthèse vocale
|
||||||
* Prise en charge des capteurs Bluetooth LE : rythme cardiaque, vitesse et distance (vélo), cadence de pédalage (vélo), et capteur de puissance (vélo)
|
* Prise en charge des capteurs Bluetooth LE : rythme cardiaque, vitesse et distance (vélo), cadence de pédalage (vélo), et capteur de puissance (vélo)
|
||||||
* Export : export des traces au format KMZ (photos incluses), KML ou GPX
|
* Export : export des traces au format KMZ (photos incluses), KML ou GPX
|
||||||
* Pas d'accès internet requis : Internet n'est pas nécessaire pour le fonctionnement de l'application
|
* Pas d'accès internet requis : Internet n'est pas nécessaire pour le fonctionnement de l'application
|
||||||
|
* Thème sombre ou claire, avec le respect des paramètres du système
|
||||||
|
* Pas de publicités
|
||||||
|
|
||||||
|
Logiciel Open Source
|
||||||
|
Vous pouvez utiliser, étudier, changer et partager le code source.
|
||||||
|
Licence Apache 2.0
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.18.6: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- "Taispeáin ar léarscáil" - feidhmiúlacht trí KML in ionad KMZ
|
||||||
|
- Ní chuimsíonn fógra gutha ainm na haipe
|
||||||
|
- Agus é ag taifeadadh: déantar gnóthachan/caillteanas ingearchló a nuashonrú gach soicind
|
||||||
|
- Tuairiscí an tsiopa aistrithe
|
||||||
|
|
||||||
|
Maoláin:
|
||||||
|
- Aistriúcháin fógartha gutha seasta neamhbhailí
|
||||||
|
|
||||||
|
Forbróir:
|
||||||
|
- ceadanna Android12 (BLUETOOTH_SCAN)
|
||||||
|
- ceadanna Android12 (ACCESS_COARSE_LOCATION)
|
||||||
|
- Ag dearbhú do Trackpoints (tástáil)
|
||||||
|
- Aistriúcháin neamhúsáidte bainte
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v3.19.1: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Aistriúcháin nuashonraithe.
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Easpórtáil Gach Rianta fabht seasta.
|
||||||
|
- Lean bug Track socraithe.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
v3.20.0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Agus tú ag taifeadadh: tá UI staitisticí inchumraithe anois
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Níor tugadh aird ar athrú ainm/catagóir an traic le linn an taifeadta (a tugadh isteach i v3.19.0)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
v3.20.1: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Is féidir fógraí a úsáid anois de réir achair agus ama
|
||||||
|
- Bíp fógraí mura bhfuil aon bhogearraí Téacs-go-hurlabhra suiteáilte
|
||||||
|
- Baineadh minicíocht oiriúnaitheach suíomh GPS
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v3.22.0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Ní stórálfar láithreacha ach amháin má thaistilítear > an t-eatramh faid a thaifeadtar
|
||||||
|
(feidhmiúlacht fágtha bainte den bhrath díomhaoin/neamhdhíomhaoin)
|
||||||
|
- Is féidir Chomhéadain a chumrú chun clog a thaispeáint
|
||||||
|
- Is féidir luas díomhaoin a chumrú anois
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Eatraimh: tuairteála nuair a stóráiltear gnóthachan ach ní caillteanas
|
||||||
|
- Agus tú ag taifeadadh: seachain tuairteáil agus fógraí gutha á ndíchumasú
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
v3.23.0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Cuireadh próifílí Chomhéadain leis
|
||||||
|
- Staitisticí comhiomlánaithe le haghaidh rianta roghnaithe
|
||||||
|
- TrackPoints díomhaoin/neamhdhomhaoin athfhorfheidhmithe de réir mar a stop an t-am bogtha ag obair (tugtha isteach in v3.22.0)
|
||||||
|
|
||||||
|
Ceartúcháin fhabht:
|
||||||
|
- Braiteoirí BLE: sonraí soiléire maidir le dínascadh
|
||||||
|
- Ní mór an t-easpórtáil uathoibríoch a cheadú go fóill
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v3.25.0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Tá GPS roghnach anois lena n-áirítear. Rabhadh GPS díchumasaithe
|
||||||
|
- PublicAPI: is féidir le feidhmchláir eile sonraí taifeadta a fháil anois má thosaíonn siad ar thaifeadadh (curtha i bhfeidhm do Gadgetbridge)
|
||||||
|
- Gníomhaíochtaí nua: snámh, snámh oscailte, agus workout
|
||||||
|
- Baineadh feidhmiúlacht pic sciar
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Chomhéadain: luas / airde nuair a léim idir 0.0 agus an luach iarbhír
|
||||||
|
- Is féidir rianta le emojis a onnmhairiú
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
v3.25.1: OpenTracks
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Easpórtáil uathoibríoch: tá súil againn teipeanna ciúine a chosc
|
||||||
|
- Easpórtáil uathoibríoch: cosc tuairteála
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v3.26.0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Is féidir fógraí gutha a chumrú
|
||||||
|
- Fógraí gutha faoi ráta croí
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Tuairteála mar gheall ar riocht cine
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
v3.26.1: OpenTracks
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Níor sháraigh barra gníomhaíochta comhthéacsúla an barra uirlisí i dtéama na hoíche.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
v4.0.1: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Is féidir fógraí gutha a chumrú anois
|
||||||
|
- Folaíonn mód lánscáileáin anois barra nascleanúna Android freisin
|
||||||
|
- Ba cheart go mbeadh nasc le braiteoirí BLE níos tapúla anois
|
||||||
|
- Ceadaigh socruithe a athshocrú agus tú ag taifeadadh
|
||||||
|
- Ceadaigh socruithe iompórtála/easpórtála a athrú agus tú ag taifeadadh
|
||||||
|
- KML/KMZ: ná húsáid deilbhíní le luchtú ó Google
|
||||||
|
|
||||||
|
Ceartúchán Bug:
|
||||||
|
- Oibríonn TrackStoppedActivity ar scáileáin níos lú anois
|
||||||
|
- Iarratas ar cheadanna ar an rianliosta
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
v4. 0. 2: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- - Agus muirmhíle
|
||||||
|
- Is féidir socruithe a athshocrú agus taifeadadh á dhéanamh
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Fógra gutha slánú
|
||||||
|
- Cairt: bhí ingearchló smoothed weirdly
|
||||||
|
- Ní raibh easpórtáil ag seiceáil an bhfuil an comhad ann
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4.0. 3: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
Sonraíocht: Max. luas mar a thuairiscigh braiteoir (GPS nó BLE)
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Cosc ar thuairteáil mura bhfuil Painéal Na Nionstraimí OSM suiteáilte
|
||||||
|
- Easpórtáil rian GPX: ná heaspórtáil deighleáin an amhráin folamh
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
v4. 0. 4: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Stóráil sonraí braiteoir BLE fiú gan achar (gach 10s)
|
||||||
|
- PUBLIC API: ceadaíonn leagan ainm, catagóir, agus cur síos
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Tuairteála nuair a ghlacadh pictiúr agus rothlach an fón
|
||||||
|
-
|
||||||
|
|
||||||
|
Forbróir:
|
||||||
|
Sprioc-SDK 33
|
||||||
|
- Baraiméadar úsáideann eatramh de 5s
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
v4. 0. 5: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- - PlayStore release faigh lógó eile
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Taispeánann liosta eatramh " - " mura bhfuil gnóthachan/caillteanas i láthair
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
v4.0. 6: OpenTracks
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Egm2008 fhritháireamh mícheart ríomh le haghaidh domhanfhad diúltach
|
||||||
|
- - Crashed API poiblí má Bhí Rianta Oscailte sa chúlra (26 AIBREÁN+)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
v4. 0. 7: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Gps comhartha caillte teorainn ama: 30s
|
||||||
|
- - Android 13: cead a iarraidh chun fógraí a thaispeáint
|
||||||
|
- Scrios rianta níos tapúla (bunachar sonraí folúis amháin más gá)
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- PublicAPI stop ordú mar thoradh ar tuairteála (a tugadh isteach i v4. 0. 6)
|
||||||
|
- Ceadanna: ceadanna a iarraidh le linn tosaithe
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v4. 0. 8: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Airde a thaispeántar i gcónaí i m/ft
|
||||||
|
- Taispeáin crios ama an riain mura bhfuil sé éagsúil le crios ama na feiste
|
||||||
|
- PublicAPI: tacaíocht deilbhín an riain a shocrú go sainráite
|
||||||
|
|
||||||
|
Forbróir:
|
||||||
|
- A Tugadh Isteach Cianfhormáideoir
|
||||||
|
- Uasghrádú GO AGP 7.3/desugar Ar Feadh Ré.aicme
|
||||||
|
- Android12+: déan splancscáileán trí Androidx
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v4. 1. 0: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Easpórtáil leagan KML/KMZ 2. 3 amháin (2. 2)
|
||||||
|
- Le haghaidh crank-bhunaithe powermeters: faigh cadence
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Workaround do tuairteála ar "iompórtáil gach rud"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
v4.1. 1: OpenTracks
|
||||||
|
|
||||||
|
Athruithe:
|
||||||
|
- Cuir scáileán réamhrá leis (taispeáin uair amháin)
|
||||||
|
|
||||||
|
Ceartúcháin:
|
||||||
|
- Ná tuairteála mura bhfuil gléas GPS i láthair
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
Cairde rianaithe spóirt a bhfuil meas aige ar do phríobháideachas.
|
||||||
|
|
||||||
|
Tugann gníomhaíochtaí spóirt agus lasmuigh sonas, scil agus muinín.
|
||||||
|
|
||||||
|
Cuir luach ar do shláinte trí súil a choinneáil ar d'oiliúint.
|
||||||
|
Taifeadann tú de réir mar a théann tú ag rith nó ag siúl, agus tugann sé ríomhaire rothar duit le scáileán níos mó le haghaidh rothaíochta.
|
||||||
|
Marcáil láithreacha suimiúla ar do bhealach le pictiúir.
|
||||||
|
Coinnigh staitisticí taifeadta go mion go leor le haghaidh anailíse.
|
||||||
|
Comhroinn ach na sonraí a theastaíonn uait a bheith ag daoine eile.
|
||||||
|
|
||||||
|
* Fógraí gutha.
|
||||||
|
* Tacaíonn braiteoirí Bluetooth LE: ráta croí, luas agus fad (rothaíocht), deireadh (rothaíocht), agus méadar cumhachta (rothaíocht).
|
||||||
|
* Gnóthachan agus caillteanas airde: trí bhraiteoir barometric.
|
||||||
|
* Airde léirithe in EGM2008 (os cionn meánleibhéal na farraige); onnmhairiú mar WGS84.
|
||||||
|
* Easpórtáil sonraí mar rianta mar KMZ (grianghraif san áireamh), KML, nó GPX.
|
||||||
|
* Gan rochtain ar an Idirlíon nó ceadanna breise.
|
||||||
|
* Téama dorcha agus éadrom, ag urramú socruithe an chórais.
|
||||||
|
* Gan fógraí.
|
||||||
|
|
||||||
|
Bogearraí Libre / Bogearraí Saor in Aisce / Foinse Oscailte
|
||||||
|
rud a chiallaíonn gur féidir leat an cód foinse a úsáid, a staidéar, a athrú agus a roinnt.
|
||||||
|
Ceadúnaithe Apache 2.0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Cairde rianaithe spóirt a bhfuil meas aige ar do phríobháideachas.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
OpenTracks
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.18.6: OpenTracks
|
||||||
|
|
||||||
|
Wijzigingen:
|
||||||
|
- "Toon op kaart"-functionaliteit via KML in plaats van KMZ
|
||||||
|
- Spraakaankondigingen bevatten geen app naam
|
||||||
|
- Tijdens opname: hoogtewinst/-verlies wordt elke seconde bijgewerkt
|
||||||
|
- Winkel beschrijvingen vertaald
|
||||||
|
|
||||||
|
Bufixes:
|
||||||
|
- Ongeldige vertalingen van stemboodschappen opgelost
|
||||||
|
|
||||||
|
Ontwikkelaar:
|
||||||
|
- Android12-toestemmingen (BLUETOOTH_SCAN)
|
||||||
|
- Android12-toestemmingen (ACCESS_COARSE_LOCATION)
|
||||||
|
- Assertiviteit voor TrackPoints (testen)
|
||||||
|
- Ongebruikte vertalingen verwijderd
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.19.0: OpenTracks
|
||||||
|
|
||||||
|
Wijzigingen:
|
||||||
|
- Ondersteuning voor Running Speed en Cadence (RCS) sensoren
|
||||||
|
- Bij het delen van een track wordt een afbeelding gemaakt
|
||||||
|
- Niet trillen bij starten van opnemen
|
||||||
|
- Bij opnemen: UI toont recentst ontvangen hoogte, snelheid en richting (ook al is deze niet opgeslagen)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Berekening van totale tijd mag geen pauze-tijd bevatten (vereist opnieuw importeren)
|
||||||
|
- (opnieuw) Gebruik aangepaste overzichten indien aanwezig
|
||||||
|
|
||||||
|
Ontwikkelaar:
|
||||||
|
- Upgrade naar SDK31 en AGP7.0.0 (vereist JDK11)
|
||||||
|
- TrackRecordingService: sensorfusie (TrackPointCreator) en TrackPoint-opslag (TrackRecordingManager) geëxtraheerd
|
||||||
|
- ExportImportTest is nu deterministisch/constant
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.27.0: OpenTracks
|
||||||
|
|
||||||
|
Mudanças:
|
||||||
|
- Anúncios de voz: adicionado 100m, 200m e 500m
|
||||||
|
- Intervalo: adicionado 100m e 500m
|
||||||
|
- O relógio mostra agora também os segundos
|
||||||
|
- GPX, KML, KMZ: uma maior precisão horizontal de exportação e importação
|
||||||
|
- GPX: exporta a distância acumulada via extensão clustrust
|
||||||
|
- CSV: exportação básica (apenas TrackPoints; não para backup)
|
||||||
|
- Solução alternativa para o Tickr X, pois relata SPM em vez de RPM
|
||||||
|
|
||||||
|
Correções de bugs:
|
||||||
|
- Foi Aderido ao intervalo de distância de gravação; Os TrackPoints foram registrados embora estivessem muito próximos
|
||||||
|
- Prevenir travamento ao parar de gravar (condição de corrida)
|
||||||
|
- Evite acidentes ao usar vários sensores (condição de corrida)
|
||||||
|
- Evite travamentos ao abrir o OpenTracks via notificação
|
||||||
@@ -1 +1 @@
|
|||||||
Um rastreador esportivo que respeita totalmente a sua privacidade.
|
Um rastreador esportivo que respeita a sua privacidade.
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
Gizliliğinize saygı duyan bir spor takipçisi.
|
||||||
|
|
||||||
|
Spor ve açık hava etkinlikleri mutluluk, beceri ve güven verir.
|
||||||
|
|
||||||
|
Antrenmanınızı takip ederek sağlığınıza değer verin.
|
||||||
|
Koşarken veya yürürken kaydeder ve size bisiklet sürmek için daha büyük ekranlı bir bisiklet bilgisayarı verir.
|
||||||
|
Yol boyunca ilginç yerleri resimlerle işaretleyin.
|
||||||
|
Analiz için kaydedilen istatistikleri çok ayrıntılı tutun.
|
||||||
|
Yalnızca başkalarının sahip olmasını istediğiniz verileri paylaşın.
|
||||||
|
|
||||||
|
* Sesli duyurular.
|
||||||
|
* Bluetooth LE sensörlerini destekler: kalp atış hızı, hız ve mesafe (bisiklet), tempo (bisiklet) ve güç ölçer (bisiklet).
|
||||||
|
* İrtifa kazancı ve kaybı: barometrik sensör aracılığıyla.
|
||||||
|
* EGM2008'de gösterilen rakım (ortalama deniz seviyesinin üzerinde); WGS84 olarak dışa aktarılır.
|
||||||
|
* Verileri KMZ (fotoğraflar dahil), KML veya GPX olarak parça olarak dışa aktarın.
|
||||||
|
* İnternet erişimi veya ekstra izin yok.
|
||||||
|
* Sistem ayarlarına uygun olarak koyu ve açık tema.
|
||||||
|
* Reklamsız.
|
||||||
|
|
||||||
|
Libre yazılımı / Özgür Yazılım / Açık Kaynak
|
||||||
|
yani kaynak kodunu kullanabilir, inceleyebilir, değiştirebilir ve paylaşabilirsiniz.
|
||||||
|
Lisanslı Apache 2.0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Gizliliğinize saygı duyan bir spor takipçisi.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.18.6: OpenTracks
|
||||||
|
|
||||||
|
Thay đổi:
|
||||||
|
- Tính năng "Hiện trên bản đồ" thông qua KML thay vì KMZ
|
||||||
|
- Thông báo bằng giọng nói không bao gồm tên ứng dụng
|
||||||
|
- Trong lúc ghi: Tăng/ giảm độ cao được cập nhật mỗi giây
|
||||||
|
- Thông tin cửa hàng được cập nhật
|
||||||
|
|
||||||
|
Sửa lỗi:
|
||||||
|
- Sửa lỗi các bản dịch Thông báo giọng nói không hợp lệ
|
||||||
|
|
||||||
|
Phát triển:
|
||||||
|
- Quyền Android 12 (BLUETOOTH_SCAN)
|
||||||
|
- Quyền Android 12 (ACCESS_COARSE_LOCATION)
|
||||||
|
- Khẳng định cho TrackPoints (thử nghiệm)
|
||||||
|
- Loại bỏ các bản dịch thừa
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
OpenTracks là một môn thể thao theo dõi ứng dụng hoàn toàn tôn trọng sự riêng tư.
|
OpenTracks là một ứng dụng theo dõi thể theo tôn trọng sự riêng tư của bạn.
|
||||||
|
|
||||||
Tính năng:
|
Thể thao và các hoạt động ngoài trời cho bạn niềm vui, kĩ năng và sự tự tin.
|
||||||
* Thể theo dõi theo dõi thể thao và hoạt động ngoài trời
|
|
||||||
* Ảnh và đánh dấu: đánh dấu địa điểm thú vị trong khi theo dõi
|
Quý trọng sức khỏe của bạn bằng cách theo dõi tập luyện của bạn.
|
||||||
* Độ cao được và mất: thông qua khí quyển cảm biến
|
Ghi lại quá trình khi bạn chạy bộ hoặc đi bộ, và cho bạn một màn hình xe đạp khi đạp xe.
|
||||||
* Độ cao thể hiện trong EGM2008 (trên mực nước biển); xuất khẩu như WGS84
|
Đánh dấu những địa điểm thú vị trong lúc bạn di chuyển bằng hình ảnh.
|
||||||
* Tiếng nói thông báo
|
Giữ các thống kê chi tiết để phân tích kĩ càng.
|
||||||
* Hỗ trợ Bluetooth LE cảm biến: tim, tốc độ và khoảng cách (đi xe đạp), nhịp (đi xe đạp), và đồng hồ điện (đi xe đạp)
|
Chỉ chia sẻ những dữ liệu bạn muốn chia sẻ.
|
||||||
* Xuất dữ liệu: xuất bài hát hoặc là BIỂU (bao gồm. ảnh) DÕI hay C
|
|
||||||
* Không có Internet: Internet là không được sử dụng
|
* Thông báo bằng giọng nói.
|
||||||
|
* Hỗ trợ Bluetooth LE cảm biến: nhịp tim, tốc độ và khoảng cách (đi xe đạp), nhịp (đi xe đạp), và đồng hồ sức mạnh (đi xe đạp)
|
||||||
|
* Tăng hoặc giảm độ cao: thông qua cảm biến khí áp.
|
||||||
|
* Độ cao được hiển thị dưới EGM2009 (trên nghĩa là trên mực nước biển), KML hoặc GPX.
|
||||||
|
* Xuất dữ liệu được lại dưới KMZ (gồm hình ảnh), KML hoặc GPX.
|
||||||
|
* Không cần Internet hoặc các quyền không cần thiết.
|
||||||
|
* Chế độ tối hoặc sáng, theo cài đặt hệ thống.
|
||||||
|
* Không quảng cáo.
|
||||||
|
|
||||||
|
Phần mềm Libre / Free Software / Mã nguồn mở
|
||||||
|
có nghĩa là bạn có thể dùng, học tập, thay đổi và chia sẻ mã nguồn.
|
||||||
|
Licensed Apache 2.0
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Một môn thể thao theo dõi mà hoàn toàn tôn trọng sự riêng tư.
|
Một người bạn theo dõi mà tôn trọng sự riêng tư của bạn.
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
OpenTracks是一个完全尊重你的隐私的运动跟踪应用程序。
|
一款尊重您的隐私的运动追踪应用。
|
||||||
|
|
||||||
|
健康幸福的生活总少不了各种运动和户外活动。
|
||||||
|
|
||||||
|
使用本应用,您可以保持对您的训练数据的有效追踪,为您的健康助力。
|
||||||
|
本应用可以在您跑步或散步时记录数据,也可以在您骑车时作为一个大屏幕自行车电脑。
|
||||||
|
您可以为路上的有趣位置创建标记,还可以用图片作为标记。
|
||||||
|
您的数据会被详尽地记录下来,供您查阅分析。
|
||||||
|
您的数据只会分享给您想要分享给的人。
|
||||||
|
|
||||||
特点。
|
|
||||||
* 运动追踪:追踪你的运动和户外活动
|
|
||||||
* 照片和标记:在跟踪时标记有趣的地点
|
|
||||||
* 海拔增减:通过气压传感器
|
|
||||||
* 高度显示为EGM2008(平均海平面以上);导出为WGS84
|
|
||||||
* 语音播报
|
* 语音播报
|
||||||
* 支持蓝牙LE传感器:心率、速度和距离(骑车)、节奏(骑车)和功率计(骑车)。
|
* 支持蓝牙LE传感器:心率、速度和距离(骑车)、踏频(骑车)和功率计(骑车)。
|
||||||
* 导出数据:以KMZ(包括照片)、KML或GPX形式导出轨迹
|
* 海拔增减:通过气压传感器。
|
||||||
* 没有互联网接入。不使用互联网
|
* EGM2008 海拔显示(平均海平面以上);导出为 WGS84。
|
||||||
|
* 导出路线数据,支持 KMZ(包括照片)、KML 和 GPX 格式。
|
||||||
|
* 不需要联网,不需要额外权限。
|
||||||
|
* 深色和浅色主题,跟随系统设置。
|
||||||
|
* 没有广告。
|
||||||
|
|
||||||
|
本应用是开源软件
|
||||||
|
意味着您可以使用、学习、修改和分发本应用的源代码。
|
||||||
|
本应用使用 Apache 2.0 协议发布。
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
一个完全尊重你隐私的运动追踪器。
|
一款尊重您的隐私的运动追踪应用。
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
android.enableJetifier=true
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=256m
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -205,6 +205,12 @@ set -- \
|
|||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -75,13 +75,15 @@ set CLASSPATH=%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
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 862 KiB After Width: | Height: | Size: 474 KiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 338 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 665 KiB After Width: | Height: | Size: 565 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 661 KiB After Width: | Height: | Size: 588 KiB |
|
Before Width: | Height: | Size: 1001 KiB After Width: | Height: | Size: 1012 KiB |
@@ -3,48 +3,25 @@ package de.dennisguse.opentracks;
|
|||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onData;
|
import static androidx.test.espresso.Espresso.onData;
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.Espresso.pressBack;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
import static androidx.test.espresso.action.ViewActions.click;
|
||||||
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
import static androidx.test.espresso.action.ViewActions.longClick;
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static org.hamcrest.Matchers.allOf;
|
import static org.hamcrest.Matchers.allOf;
|
||||||
import static org.hamcrest.Matchers.anything;
|
import static org.hamcrest.Matchers.anything;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.childAtPosition;
|
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.veryLongTouch;
|
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.withListSize;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.Instrumentation;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import androidx.test.espresso.IdlingRegistry;
|
|
||||||
import androidx.test.espresso.IdlingResource;
|
|
||||||
import androidx.test.espresso.ViewInteraction;
|
|
||||||
import androidx.test.espresso.assertion.ViewAssertions;
|
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
|
||||||
import androidx.test.rule.GrantPermissionRule;
|
import androidx.test.rule.GrantPermissionRule;
|
||||||
|
|
||||||
import org.hamcrest.Description;
|
|
||||||
import org.hamcrest.TypeSafeMatcher;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.services.TrackDeleteService;
|
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class EspressoDeleteTrackTest {
|
public class EspressoDeleteTrackTest {
|
||||||
@@ -55,150 +32,33 @@ public class EspressoDeleteTrackTest {
|
|||||||
@Rule
|
@Rule
|
||||||
public GrantPermissionRule mGrantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);
|
public GrantPermissionRule mGrantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);
|
||||||
|
|
||||||
private MyIdlingResource idlingResource;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void registerIntentServiceIdlingResource() {
|
|
||||||
Instrumentation instrumentation
|
|
||||||
= InstrumentationRegistry.getInstrumentation();
|
|
||||||
idlingResource = new MyIdlingResource(instrumentation.getTargetContext());
|
|
||||||
IdlingRegistry.getInstance().register(idlingResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void unregisterIntentServiceIdlingResource() {
|
|
||||||
IdlingRegistry.getInstance().unregister(idlingResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore("Test fails permanently")
|
|
||||||
@Deprecated
|
|
||||||
@Test
|
@Test
|
||||||
public void espressoDeleteTrackTest() {
|
public void espressoDeleteTrackTest() {
|
||||||
int countBefore;
|
// TrackListActivity: start recording
|
||||||
|
onView(withId(R.id.track_list_fab_action)).perform(click());
|
||||||
|
|
||||||
{
|
// TrackRecordingActivity
|
||||||
// TrackListActivity: start recording
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
// wait; stay recording
|
||||||
trackControllerRecordButton.perform(click());
|
.perform(waitFor(5000))
|
||||||
}
|
// stop;
|
||||||
|
.perform(longClick());
|
||||||
|
|
||||||
{
|
// TrackStoppedActivity
|
||||||
// TrackRecordingActivity
|
onView(withId(R.id.finish_button)).perform(click());
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
|
||||||
|
|
||||||
// wait; stay recording
|
|
||||||
trackControllerRecordButton.perform(waitFor(5000));
|
|
||||||
|
|
||||||
// stop;
|
|
||||||
trackControllerStopButton.perform(veryLongTouch(1600));
|
|
||||||
}
|
|
||||||
|
|
||||||
// back
|
|
||||||
pressBack();
|
|
||||||
|
|
||||||
// get number of items before deleting a track
|
|
||||||
countBefore = numberOfItemsListView();
|
|
||||||
|
|
||||||
// select track
|
// select track
|
||||||
onData(anything()).inAdapterView(withId(R.id.track_list)).atPosition(0).perform(veryLongTouch(5000));
|
onData(anything()).inAdapterView(withId(R.id.track_list)).atPosition(0).perform(longClick());
|
||||||
|
|
||||||
// open menu and delete selected track
|
// open menu and delete selected track
|
||||||
ViewInteraction overflowMenuButton = onView(
|
onView(allOf(withContentDescription("More options"), isDisplayed()))
|
||||||
allOf(withContentDescription("More options"),
|
.perform(click());
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withId(R.id.toolbar),
|
|
||||||
2),
|
|
||||||
2),
|
|
||||||
isDisplayed()));
|
|
||||||
overflowMenuButton.perform(click());
|
|
||||||
|
|
||||||
ViewInteraction appCompatTextView = onView(
|
onView(withText("Delete")).perform(click());
|
||||||
allOf(withId(R.id.title), withText("Delete"),
|
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withId(R.id.content),
|
|
||||||
0),
|
|
||||||
0),
|
|
||||||
isDisplayed()));
|
|
||||||
appCompatTextView.perform(click());
|
|
||||||
|
|
||||||
ViewInteraction appCompatButton = onView(
|
onView(withText("OK")).perform(click());
|
||||||
allOf(withId(android.R.id.button1), withText("Yes"),
|
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withId(R.id.buttonPanel),
|
|
||||||
0),
|
|
||||||
3)));
|
|
||||||
appCompatButton.perform(scrollTo(), click());
|
|
||||||
|
|
||||||
// check number of items after delete
|
// tracklist is empty now
|
||||||
onView(withId(R.id.track_list)).check(ViewAssertions.matches(withListSize(countBefore - 1)));
|
onView(allOf(withText("Start recording your next adventure here"), isDisplayed()));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private int numberOfItemsListView() {
|
|
||||||
final int[] counts = new int[1];
|
|
||||||
onView(withId(R.id.track_list)).check(matches(new TypeSafeMatcher<View>() {
|
|
||||||
@Override
|
|
||||||
public boolean matchesSafely(View view) {
|
|
||||||
ListView listView = (ListView) view;
|
|
||||||
|
|
||||||
counts[0] = listView.getCount();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void describeTo(Description description) {
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
return counts[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static class MyIdlingResource implements IdlingResource {
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private ResourceCallback resourceCallback;
|
|
||||||
|
|
||||||
public MyIdlingResource(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return MyIdlingResource.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerIdleTransitionCallback(IdlingResource.ResourceCallback resourceCallback) {
|
|
||||||
this.resourceCallback = resourceCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIdleNow() {
|
|
||||||
boolean idle = !isDeleteServiceRunning();
|
|
||||||
if (idle && resourceCallback != null) {
|
|
||||||
resourceCallback.onTransitionToIdle();
|
|
||||||
}
|
|
||||||
return idle;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDeleteServiceRunning() {
|
|
||||||
ActivityManager manager =
|
|
||||||
(ActivityManager) context.getSystemService(
|
|
||||||
Context.ACTIVITY_SERVICE);
|
|
||||||
for (ActivityManager.RunningServiceInfo info :
|
|
||||||
manager.getRunningServices(Integer.MAX_VALUE)) {
|
|
||||||
if (TrackDeleteService.class.getName().equals(
|
|
||||||
info.service.getClassName())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,14 @@ import static androidx.test.espresso.Espresso.onView;
|
|||||||
import static androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu;
|
import static androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
import static androidx.test.espresso.action.ViewActions.click;
|
||||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.longClick;
|
||||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||||
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
|
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
|
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static org.hamcrest.Matchers.allOf;
|
import static org.hamcrest.Matchers.allOf;
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.childAtPosition;
|
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.veryLongTouch;
|
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
||||||
|
|
||||||
import androidx.test.espresso.ViewInteraction;
|
import androidx.test.espresso.ViewInteraction;
|
||||||
@@ -25,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
import androidx.test.rule.GrantPermissionRule;
|
import androidx.test.rule.GrantPermissionRule;
|
||||||
|
|
||||||
import org.hamcrest.core.IsInstanceOf;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -50,16 +45,15 @@ public class EspressoEditTrackRecordingTest {
|
|||||||
public void espressoEditTrackRecordingTest() {
|
public void espressoEditTrackRecordingTest() {
|
||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
ViewInteraction fabRecordButton = onView(withId(R.id.track_list_fab_action));
|
||||||
trackControllerRecordButton.perform(click());
|
fabRecordButton.perform(click());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TrackRecordingActivity
|
// TrackRecordingActivity
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_recording_fab_action));
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
|
||||||
|
|
||||||
// wait; stay recording
|
// wait; stay recording
|
||||||
trackControllerRecordButton.perform(waitFor(15000));
|
trackControllerStopButton.perform(waitFor(4000));
|
||||||
|
|
||||||
// open menu
|
// open menu
|
||||||
openContextualActionModeOverflowMenu();
|
openContextualActionModeOverflowMenu();
|
||||||
@@ -68,58 +62,24 @@ public class EspressoEditTrackRecordingTest {
|
|||||||
onView(withText(R.string.menu_edit)).perform(click());
|
onView(withText(R.string.menu_edit)).perform(click());
|
||||||
|
|
||||||
// change name for "New Name"
|
// change name for "New Name"
|
||||||
ViewInteraction textInputEditText = onView(
|
ViewInteraction textInputEditText = onView(withId(R.id.track_edit_name));
|
||||||
allOf(withId(R.id.track_edit_name),
|
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withClassName(is("com.google.android.material.textfield.TextInputLayout")),
|
|
||||||
0),
|
|
||||||
1)));
|
|
||||||
textInputEditText.perform(scrollTo(), replaceText("New Name"));
|
textInputEditText.perform(scrollTo(), replaceText("New Name"));
|
||||||
|
|
||||||
ViewInteraction textInputEditText2 = onView(
|
ViewInteraction textInputEditText2 = onView(allOf(withId(R.id.track_edit_name), withText("New Name"), isDisplayed()));
|
||||||
allOf(withId(R.id.track_edit_name), withText("New Name"),
|
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withClassName(is("com.google.android.material.textfield.TextInputLayout")),
|
|
||||||
0),
|
|
||||||
1),
|
|
||||||
isDisplayed()));
|
|
||||||
textInputEditText2.perform(closeSoftKeyboard());
|
textInputEditText2.perform(closeSoftKeyboard());
|
||||||
|
|
||||||
// save edition
|
// save edition
|
||||||
ViewInteraction appCompatButton = onView(
|
ViewInteraction appCompatButton = onView(withId(R.id.track_edit_save));
|
||||||
allOf(withId(R.id.track_edit_save),
|
|
||||||
childAtPosition(
|
|
||||||
childAtPosition(
|
|
||||||
withClassName(is("android.widget.LinearLayout")),
|
|
||||||
3),
|
|
||||||
1),
|
|
||||||
isDisplayed()));
|
|
||||||
appCompatButton.perform(click());
|
appCompatButton.perform(click());
|
||||||
|
|
||||||
//pause
|
|
||||||
trackControllerRecordButton.perform(veryLongTouch(1600));
|
|
||||||
|
|
||||||
// wait; stay paused
|
|
||||||
trackControllerRecordButton.perform(waitFor(1000));
|
|
||||||
|
|
||||||
// resume
|
|
||||||
trackControllerRecordButton.perform(click());
|
|
||||||
|
|
||||||
// wait; stay recording
|
|
||||||
trackControllerRecordButton.perform(waitFor(1000));
|
|
||||||
|
|
||||||
// stop;
|
// stop;
|
||||||
trackControllerStopButton.perform(veryLongTouch(1600));
|
trackControllerStopButton.perform(longClick());
|
||||||
|
|
||||||
// check track's name is "New Name"
|
// it's on track stopped activity and there are two buttons
|
||||||
ViewInteraction textView = onView(
|
ViewInteraction resumeButton = onView(withId(R.id.resume_button));
|
||||||
allOf(withId(R.id.stats_name_value),
|
resumeButton.check(matches(isDisplayed()));
|
||||||
withParent(withParent(IsInstanceOf.instanceOf(android.widget.ScrollView.class))),
|
ViewInteraction finishButton = onView(withId(R.id.finish_button));
|
||||||
isDisplayed()));
|
finishButton.check(matches(isDisplayed()));
|
||||||
textView.check(matches(withText("New Name")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,26 +3,22 @@ package de.dennisguse.opentracks;
|
|||||||
import static androidx.test.espresso.Espresso.onData;
|
import static androidx.test.espresso.Espresso.onData;
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
import static androidx.test.espresso.action.ViewActions.click;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.longClick;
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
|
import static org.hamcrest.Matchers.allOf;
|
||||||
import static org.hamcrest.Matchers.anything;
|
import static org.hamcrest.Matchers.anything;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.selectTabAtIndex;
|
import static de.dennisguse.opentracks.util.EspressoUtils.selectTabAtIndex;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitFor;
|
||||||
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.test.espresso.UiController;
|
|
||||||
import androidx.test.espresso.ViewAction;
|
|
||||||
import androidx.test.espresso.ViewInteraction;
|
import androidx.test.espresso.ViewInteraction;
|
||||||
import androidx.test.espresso.action.MotionEvents;
|
|
||||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
import androidx.test.rule.GrantPermissionRule;
|
import androidx.test.rule.GrantPermissionRule;
|
||||||
|
|
||||||
import org.hamcrest.Matcher;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -39,34 +35,30 @@ public class EspressoUITest {
|
|||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@Test
|
@Test
|
||||||
public void record_pause_resume_stop() {
|
public void record_stop_resume_stop_finish() {
|
||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_list_fab_action));
|
||||||
trackControllerRecordButton.perform(click());
|
trackControllerRecordButton.perform(click());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TrackRecordingActivity
|
// TrackRecordingActivity: wait to record some time and then stop
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
.perform(waitFor(5000))
|
||||||
|
.perform(longClick());
|
||||||
|
|
||||||
// wait; stay recording
|
// TrackStoppedActivity: resume
|
||||||
trackControllerRecordButton.perform(waitFor(5000));
|
onView(allOf(withId(R.id.resume_button), isClickable()))
|
||||||
|
.perform(click());
|
||||||
|
|
||||||
//pause
|
// TrackRecordingActivity: wait and then stop
|
||||||
trackControllerRecordButton.perform(veryLongTouch(1600));
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
|
.perform(waitFor(5000))
|
||||||
|
.perform(longClick());
|
||||||
|
|
||||||
// wait; stay paused
|
// TrackStoppedActivity
|
||||||
trackControllerRecordButton.perform(waitFor(1000));
|
onView(withId(R.id.finish_button))
|
||||||
|
.perform(click());
|
||||||
// resume
|
|
||||||
trackControllerRecordButton.perform(click());
|
|
||||||
|
|
||||||
// wait; stay recording
|
|
||||||
trackControllerRecordButton.perform(waitFor(1000));
|
|
||||||
|
|
||||||
// stop;
|
|
||||||
trackControllerStopButton.perform(veryLongTouch(1600));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +67,13 @@ public class EspressoUITest {
|
|||||||
public void record_move_through_tabs() {
|
public void record_move_through_tabs() {
|
||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_list_fab_action));
|
||||||
trackControllerRecordButton.perform(click());
|
trackControllerRecordButton.perform(click());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TrackRecordingActivity
|
// TrackRecordingActivity
|
||||||
ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout));
|
ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout));
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_recording_fab_action));
|
||||||
|
|
||||||
tabLayout.perform(selectTabAtIndex(1));
|
tabLayout.perform(selectTabAtIndex(1));
|
||||||
tabLayout.perform(waitFor(1000));
|
tabLayout.perform(waitFor(1000));
|
||||||
@@ -96,7 +88,7 @@ public class EspressoUITest {
|
|||||||
tabLayout.perform(waitFor(1000));
|
tabLayout.perform(waitFor(1000));
|
||||||
|
|
||||||
// stop
|
// stop
|
||||||
trackControllerStopButton.perform(veryLongTouch(1600));
|
trackControllerStopButton.perform(longClick());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,36 +96,6 @@ public class EspressoUITest {
|
|||||||
@Test
|
@Test
|
||||||
public void selectAndDeleteTrack() {
|
public void selectAndDeleteTrack() {
|
||||||
onView(withId(R.id.track_list)).check(matches(isDisplayed()));
|
onView(withId(R.id.track_list)).check(matches(isDisplayed()));
|
||||||
onData(anything()).inAdapterView(withId(R.id.track_list)).atPosition(0).perform(veryLongTouch(2000));
|
onData(anything()).inAdapterView(withId(R.id.track_list)).atPosition(0).perform(longClick());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ViewAction veryLongTouch(final int duration_ms) {
|
|
||||||
return new ViewAction() {
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Perform long touch.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Matcher<View> getConstraints() {
|
|
||||||
return isDisplayed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void perform(UiController uiController, final View view) {
|
|
||||||
// Get view absolute position
|
|
||||||
int[] location = new int[2];
|
|
||||||
view.getLocationOnScreen(location);
|
|
||||||
|
|
||||||
// Offset coordinates by view position
|
|
||||||
float[] coordinates = new float[]{location[0] + 1, location[1] + 1};
|
|
||||||
|
|
||||||
// Send down event, pause, and send up
|
|
||||||
MotionEvent down = MotionEvents.sendDown(uiController, coordinates, new float[]{1f, 1f}).down;
|
|
||||||
uiController.loopMainThreadForAtLeast(duration_ms);
|
|
||||||
MotionEvents.sendUp(uiController, down, coordinates);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ import org.junit.runner.Description;
|
|||||||
import org.junit.runners.model.Statement;
|
import org.junit.runners.model.Statement;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
public class PreferenceMetricUnitRule implements TestRule {
|
public class PreferenceUnitSystemRule implements TestRule {
|
||||||
private final boolean metricUnits;
|
private final UnitSystem unit;
|
||||||
|
|
||||||
public PreferenceMetricUnitRule(boolean metricUnits) {
|
public PreferenceUnitSystemRule(UnitSystem unit) {
|
||||||
this.metricUnits = metricUnits;
|
this.unit = unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -18,13 +19,13 @@ public class PreferenceMetricUnitRule implements TestRule {
|
|||||||
return new Statement() {
|
return new Statement() {
|
||||||
@Override
|
@Override
|
||||||
public void evaluate() throws Throwable {
|
public void evaluate() throws Throwable {
|
||||||
final boolean previousMetricUnits = PreferencesUtils.isMetricUnits();
|
final UnitSystem previousUnitSystem = PreferencesUtils.getUnitSystem();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PreferencesUtils.setMetricUnits(metricUnits);
|
PreferencesUtils.setUnit(unit);
|
||||||
base.evaluate();
|
base.evaluate();
|
||||||
} finally {
|
} finally {
|
||||||
PreferencesUtils.setMetricUnits(previousMetricUnits);
|
PreferencesUtils.setUnit(previousUnitSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -14,6 +14,7 @@ import de.dennisguse.opentracks.data.models.Altitude;
|
|||||||
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.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -26,7 +27,7 @@ public class ChartPointTest {
|
|||||||
statistics.setTotalTime(Duration.ofSeconds(1000));
|
statistics.setTotalTime(Duration.ofSeconds(1000));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), Altitude.EGM2008.of(0), false, false);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), false, UnitSystem.IMPERIAL);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(1000000, (long) point.getTimeOrDistance());
|
assertEquals(1000000, (long) point.getTimeOrDistance());
|
||||||
@@ -39,7 +40,7 @@ public class ChartPointTest {
|
|||||||
statistics.setTotalDistance(Distance.of(1000));
|
statistics.setTotalDistance(Distance.of(1000));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), Altitude.EGM2008.of(0), true, true);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), true, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(1, (long) point.getTimeOrDistance());
|
assertEquals(1, (long) point.getTimeOrDistance());
|
||||||
@@ -49,9 +50,11 @@ public class ChartPointTest {
|
|||||||
public void create_get_altitude_speed_and_pace() {
|
public void create_get_altitude_speed_and_pace() {
|
||||||
// given
|
// given
|
||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint()
|
||||||
|
.setAltitude(Altitude.EGM2008.of(50));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(50, point.getAltitude(), 0.01);
|
assertEquals(50, point.getAltitude(), 0.01);
|
||||||
@@ -63,9 +66,10 @@ public class ChartPointTest {
|
|||||||
public void create_sensorNotAvailable() {
|
public void create_sensorNotAvailable() {
|
||||||
// given
|
// given
|
||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint()
|
||||||
|
.setAltitude(Altitude.EGM2008.of(50));
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertNull(point.getHeartRate());
|
assertNull(point.getHeartRate());
|
||||||
@@ -76,15 +80,16 @@ public class ChartPointTest {
|
|||||||
@Test
|
@Test
|
||||||
public void create_sensorAvailable() {
|
public void create_sensorAvailable() {
|
||||||
// given
|
// given
|
||||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint()
|
||||||
trackPoint.setHeartRate(100f);
|
.setAltitude(Altitude.EGM2008.of(50))
|
||||||
trackPoint.setCadence(101f);
|
.setHeartRate(100f)
|
||||||
trackPoint.setPower(102f);
|
.setCadence(101f)
|
||||||
|
.setPower(102f);
|
||||||
|
|
||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(100.0, point.getHeartRate(), 0.01);
|
assertEquals(100.0, point.getHeartRate(), 0.01);
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package de.dennisguse.opentracks.chart;
|
package de.dennisguse.opentracks.chart;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
@@ -25,10 +29,6 @@ import org.junit.runner.RunWith;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link ChartValueSeries}.
|
* Tests {@link ChartValueSeries}.
|
||||||
*
|
*
|
||||||
@@ -47,6 +47,7 @@ public class ChartValueSeriesTest {
|
|||||||
new int[]{1, 100, 1000},
|
new int[]{1, 100, 1000},
|
||||||
R.string.description_altitude_metric,
|
R.string.description_altitude_metric,
|
||||||
R.string.description_altitude_imperial,
|
R.string.description_altitude_imperial,
|
||||||
|
R.string.description_altitude_imperial,
|
||||||
R.color.chart_altitude_fill,
|
R.color.chart_altitude_fill,
|
||||||
R.color.chart_altitude_border,
|
R.color.chart_altitude_border,
|
||||||
15,
|
15,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.util.Pair;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
@@ -24,22 +23,17 @@ public class ShareContentProviderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateAndParseURI_valid() {
|
public void testCreateAndParseURI_valid() {
|
||||||
Set<Track.Id> trackIds = new HashSet<>();
|
Set<Track.Id> trackIds = Set.of(new Track.Id(1), new Track.Id(3), new Track.Id(5));
|
||||||
trackIds.add(new Track.Id(1));
|
|
||||||
trackIds.add(new Track.Id(3));
|
|
||||||
trackIds.add(new Track.Id(5));
|
|
||||||
|
|
||||||
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "TrackName", TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA);
|
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "filename.suffix", TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA);
|
||||||
|
|
||||||
assertEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
assertEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateURIescapeFilename() {
|
public void testCreateURIescapeFilename() {
|
||||||
Set<Track.Id> trackIds = new HashSet<>();
|
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(Set.of(new Track.Id(1)), "../../&1=1", TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA);
|
||||||
trackIds.add(new Track.Id(1));
|
|
||||||
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "../../&1=1", TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA);
|
|
||||||
|
|
||||||
assertEquals(Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/kml_with_trackdetail_and_sensordata/1/..%2F..%2F%261%3D1.kml"), shareURIandMIME.first);
|
assertEquals(Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/KML_WITH_TRACKDETAIL_AND_SENSORDATA/1/..%2F..%2F%261%3D1"), shareURIandMIME.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import junit.framework.TestCase;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
@@ -105,7 +106,7 @@ public class TrackSelectionTest extends TestCase {
|
|||||||
long oneDay = 24 * 60 * 60 * 1000;
|
long oneDay = 24 * 60 * 60 * 1000;
|
||||||
TrackSelection filterWrong1 = new TrackSelection().addDateRange(instant, null);
|
TrackSelection filterWrong1 = new TrackSelection().addDateRange(instant, null);
|
||||||
TrackSelection filterWrong2 = new TrackSelection().addDateRange(null, instant);
|
TrackSelection filterWrong2 = new TrackSelection().addDateRange(null, instant);
|
||||||
TrackSelection filterOk = new TrackSelection().addDateRange(instant, instant.plusMillis(oneDay));
|
TrackSelection filterOk = new TrackSelection().addDateRange(instant, instant.plus(Duration.ofDays(1)));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
SelectionData selectionWrong1 = filterWrong1.buildSelection();
|
SelectionData selectionWrong1 = filterWrong1.buildSelection();
|
||||||
|
|||||||