forked from upstream-mirrors/OpenTracks
Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4bbdd55254 | |||
| 7df625ff0c | |||
| 7d01048a98 | |||
| 70fdb0e877 | |||
| ec61383ffd | |||
| 28e24615b8 | |||
| 4c6abcfecd | |||
| 8fb294ea9e | |||
| 52d52ddcab | |||
| 1769bc26a2 | |||
| e3fab57c43 | |||
| f7030cd3eb | |||
| b5ba8a9f67 | |||
| 6ae7cb49f4 | |||
| 16899004b5 | |||
| 69fe5e8127 | |||
| 65913a1ba2 | |||
| 0b1e72cf58 | |||
| f89a81cb22 | |||
| ece9f3f0b2 | |||
| 3011198b2c | |||
| 77d56a864f | |||
| 0bb468e31d | |||
| 627d7c9288 | |||
| f428096164 | |||
| dfaaf4b022 | |||
| b576ccc4e2 | |||
| 0e0958c5e8 | |||
| 43e1cbcdc6 | |||
| 073b3d2052 | |||
| 01f4359cdf | |||
| 333bc6f31b | |||
| a2a9132658 | |||
| 5857c0032e | |||
| d086aa3c06 | |||
| fba09bcc3a | |||
| 3ce0e2cede | |||
| df0d3ce600 | |||
| c05cbc2fa6 | |||
| 2f07208d9d | |||
| ded98eddb5 | |||
| 45732735d4 | |||
| b43dfd05ef | |||
| c011fd4e60 | |||
| a03825e10e | |||
| e230fb42b8 | |||
| 82c0f3dcc5 | |||
| a5296c4cd9 | |||
| 522d9ebe2e | |||
| 26c660ec5b | |||
| fd9646bb1f | |||
| 4966ba8868 | |||
| 6a8861b41b | |||
| 8dc20c48b7 | |||
| f2b8dc2e07 | |||
| 41ce088a0e | |||
| 782cefb4ff | |||
| 35a02a2f81 | |||
| 8c35bd6f4f | |||
| ad26ce795a | |||
| ed1e47213d | |||
| cbb88fd1ae | |||
| a6b808d5cf | |||
| 9718377307 | |||
| dbf0c3bfc9 | |||
| 8dff211a26 | |||
| 319079162c | |||
| 731c182a12 | |||
| 6c4bb8d536 | |||
| a42aefa752 | |||
| 2f489d73b0 | |||
| babd59f0ea | |||
| 37b7277f1a | |||
| ecb421248c | |||
| 42f53199a3 | |||
| 530b906f73 | |||
| e4ebf97c27 | |||
| e3cdc952a2 | |||
| aaf78e0b74 | |||
| c3a2c0d6d0 | |||
| 05fbfcb914 | |||
| 721b54b06f | |||
| b65230bc5d | |||
| 7c8fae66ef | |||
| ef73f89fc9 | |||
| c4579eb91f | |||
| a015b87cc3 | |||
| 27e38410d7 | |||
| 714f1e715a | |||
| c8183949e2 | |||
| 4313b51e1e | |||
| e4eebb92d3 | |||
| 61f496926a | |||
| ba3c8f6a2d | |||
| a5ba6fb0dc | |||
| e0a28923fe | |||
| 4f05b65f32 | |||
| bec9be8402 | |||
| a46de8f872 | |||
| 993c2a1617 | |||
| cddfbf8b80 | |||
| cba55eab74 | |||
| 0b4a18deb4 | |||
| 7cd054f591 | |||
| 2cc4218dc6 | |||
| d9de56be33 | |||
| fa1496d130 | |||
| 89059caec2 | |||
| 8f1d8e2881 | |||
| 54e456046e | |||
| 1775c52291 | |||
| b50965f0e8 | |||
| d9bba7852c | |||
| 5ff91a98f4 | |||
| 79f62bd3db | |||
| c387729301 | |||
| 1094059fb8 | |||
| affb4e1053 | |||
| 0547a14fbd | |||
| 39d6c9a298 | |||
| 9c51a31b01 | |||
| f7f58141de | |||
| e46d3cd06c | |||
| a40b87efb6 | |||
| e98dff55ae | |||
| f0b7de4c7c | |||
| f0f571480b | |||
| 072fdb12ed | |||
| fda2fae02b | |||
| a09fa93887 | |||
| 8f0ed91f80 | |||
| e5a60a8141 | |||
| c7d3c19919 |
@@ -9,6 +9,9 @@ jobs:
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -19,7 +22,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo ${NIGHTLY_STORE_FILE} | base64 -d > KEY_NIGHTLY.jks
|
||||
./gradlew assembleNightly -Dnightly_store_file=KEY_NIGHTLY.jks -Dnightly_store_password="${NIGHTLY_STORE_PASSWORD}" -Dnightly_key_alias="${NIGHTLY_KEY_ALIAS}" -Dnightly_key_password="${NIGHTLY_STORE_PASSWORD}"
|
||||
./gradlew assembleNightlyRelease -Dnightly_store_file=KEY_NIGHTLY.jks -Dnightly_store_password="${NIGHTLY_STORE_PASSWORD}" -Dnightly_key_alias="${NIGHTLY_KEY_ALIAS}" -Dnightly_key_password="${NIGHTLY_STORE_PASSWORD}"
|
||||
env:
|
||||
NIGHTLY_STORE_FILE: ${{ secrets.NIGHTLY_STORE_FILE }}
|
||||
NIGHTLY_STORE_PASSWORD: ${{ secrets.NIGHTLY_STORE_PASSWORD }}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
name: Linting
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
@@ -10,12 +9,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
|
||||
- run: ./gradlew lint
|
||||
|
||||
@@ -7,18 +7,27 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 45
|
||||
runs-on: macos-latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0 #TODO See https://github.com/actions/checkout/issues/1471
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
|
||||
- name: Enable KVM
|
||||
run: |
|
||||
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
|
||||
- name: run tests
|
||||
uses: reactivecircus/android-emulator-runner@v2.32.0
|
||||
uses: reactivecircus/android-emulator-runner@v2.33.0
|
||||
with:
|
||||
arch: x86_64
|
||||
api-level: 34
|
||||
|
||||
@@ -12,7 +12,7 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://f-droid.org/packages/de.dennisguse.opentracks">
|
||||
<a href="https://f-droid.org/packages/de.dennisguse.opentracks.playstore">
|
||||
<img alt="Get it on F-Droid" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="60" align="middle">
|
||||
</a>
|
||||
</td>
|
||||
@@ -29,7 +29,7 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
||||
</tr>
|
||||
<tr>
|
||||
<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.playstore.svg" align="middle" >
|
||||
</td>
|
||||
<td></td>
|
||||
<td align="center">
|
||||
@@ -109,19 +109,20 @@ The API can be invoked by sending an explicit Intent to start an activity.
|
||||
* Debug: `de.dennisguse.opentracks.debug`
|
||||
* Nightly: `de.dennisguse.opentracks.nightly`
|
||||
|
||||
`Class`:
|
||||
|
||||
`Classes`:
|
||||
* **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording`
|
||||
* 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)).
|
||||
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`
|
||||
* **Stop a recording:** `de.dennisguse.opentracks.publicapi.StopRecording`
|
||||
* **Create a marker:** `de.dennisguse.opentracks.publicapi.CreateMarker`
|
||||
|
||||
For testing via adb: `adb shell am start -e someParameter someValue -n "package/class"`
|
||||
|
||||
`StartRecording` supports the following parameters:
|
||||
|
||||
* 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)).
|
||||
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 Public API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings.
|
||||
|
||||
## File formats compatibility with open-source software
|
||||
|
||||
+19
-27
@@ -2,39 +2,31 @@
|
||||
|
||||
## Craft new releases
|
||||
|
||||
1. Get next _version code_ (main): `git rev-list HEAD --count main`
|
||||
2. Decide on _version name_ (semantic versioning)
|
||||
3. Manually update _version code_ and _version name_ in `build.gradle`
|
||||
4. Create changelog (`_version code_.txt`)
|
||||
5. Create commit with all changes
|
||||
6. Tag newly create commit with _version name_ (e.g., v3.2.1)
|
||||
7. Push commits and tags to public repository
|
||||
8. Add changelog to tag (Github releases)
|
||||
1. Execute use `RELEASE.sh`.
|
||||
2. Push to Github
|
||||
3. Create release on Github (incl. changelog)
|
||||
This actually creates a tag that is later used by F-Droid
|
||||
4. Pull from Github
|
||||
5. Build reproducible release and attach to release
|
||||
6. ... wait until reproducibility is verified by F-Droid
|
||||
|
||||
## F-Droid
|
||||
Application id: de.dennisguse.opentracks
|
||||
Two releases will be created:
|
||||
* Application id: `de.dennisguse.opentracks` (irreproducible)
|
||||
* Application id: `de.dennisguse.opentracks.playstore` (reproducible)
|
||||
|
||||
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).
|
||||
For F-Droid the build status can be found [here](https://monitor.f-droid.org/builds/build).
|
||||
|
||||
The recent build activity can be found [here](https://monitor.f-droid.org/builds/build)
|
||||
## Reproducible builds
|
||||
|
||||
## Google Play Store
|
||||
Application id: `de.dennisguse.opentracks.playstore`
|
||||
A lot of detailed information can be found [here](https://f-droid.org/docs/Reproducible_Builds/)
|
||||
|
||||
Requirement: `gem install fastlane`
|
||||
|
||||
1. Build signed apk
|
||||
(requires keystore)
|
||||
2. Upload signed apk to [Google Play Console](https://play.google.com/apps/publish)
|
||||
3. Update store meta data (e.g., description and screenshots)
|
||||
`fastlane metadata`
|
||||
(requires API key configured in `Appfile`)
|
||||
|
||||
Supported languages: https://support.google.com/googleplay/android-developer/table/4419860
|
||||
Technical requirements:
|
||||
* Must be build using OpenJDK17
|
||||
|
||||
## Translations (localization)
|
||||
|
||||
Translations of the OpenTracks are handled in
|
||||
Weblate: [https://hosted.weblate.org/projects/opentracks/](https://hosted.weblate.org/projects/opentracks)
|
||||
.
|
||||
Weblate: [https://hosted.weblate.org/projects/opentracks/](https://hosted.weblate.org/projects/opentracks).
|
||||
|
||||
## Google Play Store
|
||||
Supported languages: https://support.google.com/googleplay/android-developer/table/4419860
|
||||
@@ -66,6 +66,7 @@ We do not support type of movement (i.e., walking vs running).
|
||||
### 0x2A6D: Environmental Sensing Service
|
||||
Sadly, Bluetooth sensors providing _air pressure_ via Environmental Sensing Service seem to be very rare.
|
||||
|
||||
* [Flybeeper Pressure Sensor](https://market.flybeeper.com/device/ps1)
|
||||
* NoTrustIssues: https://github.com/OpenTracksApp/NoTrustIssues
|
||||
An Android app that exposes the internal barometer via Environmental Sensing Service.
|
||||
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/
|
||||
|
||||
JAVA_VERSION=`java --version`
|
||||
if [[ $JAVA_VERSION != "openjdk 17."* ]]; then
|
||||
echo "OpenJDK version should be 17.X"
|
||||
exit -1;
|
||||
fi
|
||||
|
||||
RELEASE_STORE_PASSWORD=
|
||||
read -s -p "Enter store password: " RELEASE_STORE_PASSWORD
|
||||
echo ""
|
||||
read -s -p "Enter key alias: " RELEASE_KEY_ALIAS
|
||||
echo ""
|
||||
read -s -p "Enter key password: " RELEASE_KEY_PASSWORD
|
||||
echo ""
|
||||
|
||||
./gradlew --no-configuration-cache \
|
||||
clean \
|
||||
assembleReproducibleRelease \
|
||||
-Drelease_store_file=`ls ../*.jks` \
|
||||
-Drelease_store_file="../keystore_opentracks.jks" \
|
||||
-Drelease_store_password="$RELEASE_STORE_PASSWORD" \
|
||||
-Drelease_key_alias="$RELEASE_KEY_ALIAS" \
|
||||
-Drelease_key_password="$RELEASE_KEY_PASSWORD"
|
||||
+66
-33
@@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.7.0'
|
||||
classpath 'com.android.tools.build:gradle:8.8.0'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ def getVersionName = { ->
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
} catch (ignored) {
|
||||
return null
|
||||
throw new GradleException('VersionName could not be read:' + ignored.message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ def getVersionCode = { ->
|
||||
}
|
||||
return Integer.valueOf(stdout.toString().trim())
|
||||
} catch (ignored) {
|
||||
return null
|
||||
throw new GradleException('VersionCode could not be read:' + ignored.message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,25 +63,33 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 5889
|
||||
versionName "v4.14.0"
|
||||
applicationId 'de.dennisguse.opentracks'
|
||||
versionCode 6022
|
||||
versionName "v4.17.6"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
minSdk 26
|
||||
targetSdk 35
|
||||
|
||||
testInstrumentationRunner "de.dennisguse.opentracks.TestRunner"
|
||||
testInstrumentationRunner 'de.dennisguse.opentracks.TestRunner'
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
}
|
||||
signingConfigs {
|
||||
nightly {
|
||||
if (System.getProperty("nightly_store_file") != null) {
|
||||
storeFile file(System.getProperty("nightly_store_file"))
|
||||
storePassword System.getProperty("nightly_store_password")
|
||||
keyAlias System.getProperty("nightly_key_alias")
|
||||
keyPassword System.getProperty("nightly_key_password")
|
||||
if (System.getProperty('nightly_store_file') != null) {
|
||||
storeFile file(System.getProperty('nightly_store_file'))
|
||||
storePassword System.getProperty('nightly_store_password')
|
||||
keyAlias System.getProperty('nightly_key_alias')
|
||||
keyPassword System.getProperty('nightly_key_password')
|
||||
}
|
||||
}
|
||||
release {
|
||||
if (System.getProperty("release_store_file") != null) {
|
||||
storeFile file(System.getProperty("release_store_file"))
|
||||
storePassword System.getProperty("release_store_password")
|
||||
keyAlias System.getProperty("release_key_alias")
|
||||
keyPassword System.getProperty("release_key_password")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,60 +98,85 @@ android {
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
versionNameSuffix "-debug"
|
||||
applicationIdSuffix '.debug'
|
||||
versionNameSuffix '-debug'
|
||||
}
|
||||
|
||||
nightly {
|
||||
signingConfig signingConfigs.nightly
|
||||
applicationIdSuffix ".nightly"
|
||||
}
|
||||
|
||||
release {
|
||||
crunchPngs false
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
releasePlayStore {
|
||||
applicationIdSuffix ".playstore"
|
||||
versionNameSuffix "-PlayStore"
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
flavorDimensions 'version'
|
||||
productFlavors {
|
||||
nightly {
|
||||
dimension 'version'
|
||||
applicationId 'de.dennisguse.opentracks.nightly'
|
||||
signingConfig signingConfigs.nightly
|
||||
}
|
||||
irreproducible {
|
||||
// Non-reproducible: https://f-droid.org/de/packages/de.dennisguse.opentracks/
|
||||
dimension 'version'
|
||||
applicationId 'de.dennisguse.opentracks'
|
||||
versionNameSuffix 'irreproducible'
|
||||
}
|
||||
reproducible {
|
||||
// Developer Binaries: https://github.com/OpenTracksApp/OSMDashboard/releases/download/v%v/de.dennisguse.opentracks.playstore_%v.apk
|
||||
// FDroid: https://f-droid.org/de/packages/de.dennisguse.opentracks.playstore
|
||||
// PlayStore: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
|
||||
dimension 'version'
|
||||
applicationId 'de.dennisguse.opentracks.playstore'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
applicationVariants.configureEach { variant ->
|
||||
variant.resValue "string", "applicationId", variant.applicationId
|
||||
variant.resValue 'string', 'applicationId', variant.applicationId
|
||||
|
||||
if (variant.buildType.name == 'nightly') {
|
||||
variant.outputs.configureEach {
|
||||
variant.outputs.configureEach {
|
||||
if (variant.flavorName == 'nightly') {
|
||||
setVersionCodeOverride(getVersionCode())
|
||||
setVersionNameOverride(getVersionName())
|
||||
}
|
||||
|
||||
if (variant.flavorName == 'reproducible') {
|
||||
outputFileName = "${applicationId}_${variant.versionName}.apk"
|
||||
} else {
|
||||
outputFileName = "${applicationId}_${variant.versionCode}.apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependenciesInfo {
|
||||
// Disables dependency metadata when building APKs.
|
||||
includeInApk = false
|
||||
// Disables dependency metadata when building Android App Bundles.
|
||||
includeInBundle = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.2'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.core:core:1.13.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation 'androidx.core:core:1.15.0'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
implementation 'androidx.mediarouter:mediarouter:1.7.0'
|
||||
implementation 'androidx.core:core-location-altitude:1.0.0-alpha02'
|
||||
implementation 'androidx.core:core-location-altitude:1.0.0-alpha03'
|
||||
|
||||
androidTestImplementation 'androidx.test:core:1.6.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.6.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.6.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
androidTestImplementation 'org.mockito:mockito-android:5.14.1'
|
||||
androidTestImplementation 'org.mockito:mockito-android:5.15.2'
|
||||
|
||||
androidTestUtil 'androidx.test:orchestrator:1.5.0'
|
||||
androidTestUtil 'androidx.test:orchestrator:1.5.1'
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?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#"
|
||||
height="188"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
viewBox="0 0 78 188"
|
||||
width="78"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs id="defs6" />
|
||||
<g id="layer1" />
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer2" />
|
||||
<metadata id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:title />
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
style="fill:#cccccc;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.7019608"
|
||||
d="m 1,150 38,37 39,-37 H 50 V 97 L 29,81 v 69 z"
|
||||
id="path31161" />
|
||||
<path
|
||||
style="fill:#cccccc;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.7019608"
|
||||
d="M 29,51 V 70 L 50,86 V 67 Z"
|
||||
id="path31169" />
|
||||
<path
|
||||
style="fill:#cccccc;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.7019608"
|
||||
d="M 29,23 V 40 L 50,56 V 39 Z"
|
||||
id="path31192" />
|
||||
<path
|
||||
style="fill:#cccccc;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.7019608"
|
||||
d="M 29,0 V 14 L 50,29 V 16 Z"
|
||||
id="path31194" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,7 @@
|
||||
v4.14.0: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Použití dat Androidx EGM2008 (namísto přibalení našeho vlastního řešení).
|
||||
|
||||
Vývojář:
|
||||
- Cíl Android 15 / SDK 35
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.1: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Detekce zastavení může být zakázána
|
||||
|
||||
Oprava chyby:
|
||||
- Rozhraní přidávání obrázků ke značkám bylo skryto
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.14.2: OpenTracks
|
||||
|
||||
Oprava chyby:
|
||||
- Android 15: rozhraní již nepřetéká (edge-to-edge)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.15.0: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Výběr jazyka v aplikaci (Android 14 nebo novější)
|
||||
- Funkce zobrazit na mapě podporuje pouze aplikaci OSM Dashboard (odstraněno KML/KMZ nebo GPX)
|
||||
|
||||
Vývojář:
|
||||
- GitHub Actions nyní používají Ubuntu
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.16.0: OpenTracks
|
||||
|
||||
Oprava chyby:
|
||||
- PublicAPI: spuštění záznamu nezaznamenalo žádná data
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.16.1: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Výběr jazyka v aplikaci je nyní k dispozici pro všechny verze systému Android
|
||||
(na základě velké poptávky)
|
||||
|
||||
Vývojář:
|
||||
- GitHub Actions: při checkoutu se nestahovaly značky (noční aktualizace)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.0: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Veřejné rozhraní API pro vytváření značek (během záznamu)
|
||||
|
||||
Oprava chyby:
|
||||
- Senzory: při nečinnosti nastavena data pohybových senzorů na 0
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.17.1: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Reprodukovatelné sestavení: uvidíme, jestli to bude fungovat.
|
||||
Varianta pro Obchod Play bude odeslána F-Droidu, který ji ověří a zveřejní.
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Reprodukovatelné sestavení: uvidíme, zda to bude fungovat
|
||||
Varianta pro Obchod Play bude odeslána do F-Droidu, kde bude ověřena a zveřejněna.
|
||||
|
||||
Vývojář:
|
||||
- F-Droid vyžaduje použití Product Flavors (namísto Build Types)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Reprodukovatelné sestavení: uvidíme, zda to bude fungovat.
|
||||
|
||||
Vývojář:
|
||||
- Pokus o opravu názvu souboru APK...
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.4: OpenTracks
|
||||
|
||||
|
||||
Změny:
|
||||
- Reprodukovatelné sestavení: uvidíme, jestli to bude fungovat.
|
||||
|
||||
Vývojář:
|
||||
- Odstranění DependencyInfo.
|
||||
@@ -0,0 +1,10 @@
|
||||
v4.17.5: OpenTracks
|
||||
|
||||
Změny:
|
||||
- Reprodukovatelné sestavení: uvidíme, jestli to bude fungovat.
|
||||
|
||||
Oprava chyby:
|
||||
- Reprodukovatelné sestavení používá ikonu z Obchodu Play.
|
||||
|
||||
Vývojář:
|
||||
- Přidán soubor RELEASE_BUILD.sh
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.14.1: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Idle detection can be disabled
|
||||
|
||||
Bugfix:
|
||||
- UI for adding pictures to markers was hidden
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.14.2: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- Android 15: UI is not overflowing anymore (edge-to-edge)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.15.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- In-app language selector (Android 14 or later)
|
||||
- Show-on-map-feature only supports OSM Dashboard (removed KML/KMZ or GPX)
|
||||
|
||||
Developer:
|
||||
- Github actions now uses Ubuntu
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.16.0: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- PublicAPI: starting a recording didn't record no data
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.16.1: OpenTracks
|
||||
|
||||
Changes:
|
||||
- In-app language selector now available for all Android versions
|
||||
(due to some popular demand)
|
||||
|
||||
Developer:
|
||||
- Github actions: checkout was not fetching tags (nightly)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Public API to create markers (while recording)
|
||||
|
||||
Bugfix:
|
||||
- Sensors: on idle, set movement-based sensor data to 0
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.17.1: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Reproducible build: let's see if it works.
|
||||
The PlayStore variant will be submitted to F-Droid, verified and published them.
|
||||
@@ -0,0 +1,9 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Reproducible build: let's see if it works.
|
||||
The PlayStore variant will be submitted to F-Droid, verified and published them.
|
||||
|
||||
Developer:
|
||||
- F-Droid requires to use Product Flavors (instead of Build Types)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
v4.17.3: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Reproducible build: let's see if it works.
|
||||
|
||||
Developer:
|
||||
- Just trying to get the APK filename, right...
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.4: OpenTracks
|
||||
|
||||
|
||||
Changes:
|
||||
- Reproducible build: let's see if it works.
|
||||
|
||||
Developer:
|
||||
- Removing DependencyInfo.
|
||||
@@ -0,0 +1,10 @@
|
||||
v4.17.5: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Reproducible build: let's see if it works.
|
||||
|
||||
Bugfix:
|
||||
- Reproducible build uses PlayStore icon.
|
||||
|
||||
Developer:
|
||||
- Added RELEASE_BUILD.sh
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.17.6: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- UI: GPS data may be not shown regularly (does not affect recorded data)
|
||||
Introduced in v4.17.0
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.1: OpenTracks
|
||||
|
||||
Cambios:
|
||||
- Detección de inactividad se puede desactivar
|
||||
|
||||
Correcciones de errores:
|
||||
- UI para añadir imágenes a los marcadores estaba oculto
|
||||
@@ -0,0 +1,15 @@
|
||||
v3.0.0 : OpenTracks
|
||||
|
||||
Première édition de OpenTracks (c'est-à-dire bifurcation du dépôt depuis MyTracks)
|
||||
|
||||
Changements:
|
||||
- Renommé de MyTracks à OpenTracks
|
||||
- Capteur de fréquence cardiaque par Bluetooth LE ajouté
|
||||
- Toutes les fonctionnalités nécessitant une connexion Internet ont été enlevées
|
||||
- Intégration Google Maps enlevée
|
||||
- Toutes les utilisations des services Google Play ont été enlevées
|
||||
- Capteurs ANT+ enlevés
|
||||
- Capteurs Bluetooth classiques enlevés
|
||||
- Protobuf enlevé
|
||||
- Estimations de calories et d'activité enlevés
|
||||
- API Service MyTracks enlevée (c'est-à-dire, pas d'intégration avec les autres applications)
|
||||
@@ -0,0 +1,17 @@
|
||||
v3.0.1 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Partage des marqueurs
|
||||
− Restructuration des paramètres
|
||||
− Suppression du bouton retour de la barre d'action
|
||||
− Exportation : suppression de l'option de paramétrage de la taille de photo
|
||||
− Exportation : KML est désormais sélectionnable en tant que format
|
||||
|
||||
Correction de bogues :
|
||||
− Le répertoire d'export est désormais /OpenTracks/
|
||||
− Le mode paysage ne plante plus
|
||||
− Correction de l'export KML/KMZ
|
||||
|
||||
Développeurs :
|
||||
− Les tests sont exécutables (mais beaucoup d'échecs)
|
||||
− Activation de l'intégration continue avec TravisCI (pas de tests)
|
||||
@@ -0,0 +1,14 @@
|
||||
v3.1.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Ajout de l'option pour montrer les traces sur une application de carte (testé avec OsmAnd et Maps.ME)
|
||||
− Ajout des statistiques de la trace sans débloquer l'appareil, durant le tracé
|
||||
− Suppression du mode paysage pour la vue détaillée de la trace (était bogué)
|
||||
− Suppression des suggestions pour l'historique de recherche
|
||||
|
||||
Correction de bogue :
|
||||
− Demande des permissions de stockage pour tout importer / tout exporter
|
||||
|
||||
Développeurs :
|
||||
− Mise à niveau vers Gradle 5.6
|
||||
− Ne pas minifier les compilations release
|
||||
@@ -0,0 +1,16 @@
|
||||
v3.2.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Suppression Widget
|
||||
− Introduction des icons material design
|
||||
− Suppression du snowboard et du ski (besoin de nouveaux icons)
|
||||
|
||||
Correction de bogue :
|
||||
− Correction de la fonctionnalité de recherche
|
||||
|
||||
Développeurs :
|
||||
− Correction de (quelques) cas de test
|
||||
− Suppression de fonctionnalités parcelable
|
||||
− Nettoyage majeur et reformatage
|
||||
− Ne pas utiliser la diffusion pour la communication app widget
|
||||
− stats_content.xml ne contient pas d'autres fichiers
|
||||
@@ -0,0 +1,7 @@
|
||||
v3.2.1 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Les paramètres sont désormais une page unique
|
||||
|
||||
Développeurs :
|
||||
− Paramètres passé à Androidx compat (utilisation de fragments)
|
||||
@@ -0,0 +1,13 @@
|
||||
v3.2.2 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Suppression des statistiques agrégées
|
||||
− Migré vers Material Design
|
||||
|
||||
Correction de bogues :
|
||||
− Correction de l'export de données de capteurs
|
||||
− Correction de l'import de données de capteurs incomplètes
|
||||
|
||||
Développeurs :
|
||||
− Remplacement de la barre d'action par une barre d'outil
|
||||
− Migré vers androidx appcompat (incluant Material Design)
|
||||
@@ -0,0 +1,14 @@
|
||||
v3.2.3 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Partage : utilise Android Sharesheet
|
||||
− Partage : partage de plusieurs tracés en tant que fichier individuel
|
||||
− Utilisation d'Android ShareSheet
|
||||
− Capteur de fréquence cardiaque (Bluetooth LE) : reconnexion automatique
|
||||
|
||||
Correction de bogues :
|
||||
− Capteur de fréquence cardiaque (Bluetooth LE) : déconnecte correctement
|
||||
− La fréquence cardiaque n'était pas toujours montrée lors de l'enregistrement
|
||||
|
||||
Développeurs :
|
||||
− Activation des tests d'instrumentation de TravisCI
|
||||
@@ -0,0 +1,5 @@
|
||||
v3.2.4 : OpenTracks
|
||||
|
||||
Correction de bogue :
|
||||
− Plantage activité paramètres
|
||||
Suppression de la possibilité de change la voix / la fréquence de division depuis le menu contextuel
|
||||
@@ -0,0 +1,15 @@
|
||||
v3.2.5 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Désactivation du changement d'activité
|
||||
− Ajout des permissions pour Android 10 : enregistrement des données de localisation
|
||||
|
||||
Correction de bogue :
|
||||
− Correction des paramètres de réinitialisation
|
||||
|
||||
Développeurs :
|
||||
− Préférences
|
||||
− Si les paramètres ne peuvent être chargés, remise à zéro de toutes les préférences
|
||||
− Déplacement de l'accès des préférences vers PreferencesUtil
|
||||
− Déplacement paramètres défaut préférences de code à XML
|
||||
− Utilise SummaryProvider
|
||||
@@ -0,0 +1,8 @@
|
||||
v3.2.6 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Moniteur de fréquence cardiaque : scanne les appareils disponibles
|
||||
− Suppression du raccourci vers les paramètres Bluetooth
|
||||
|
||||
Développeurs :
|
||||
− Préférences : défaut de préférences déplacé de code à XML
|
||||
@@ -0,0 +1,10 @@
|
||||
v3.2.7 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Notification montre la précision GPS
|
||||
− Montre une notification d'avertissement si la précision GPS descend en dessous du seuil
|
||||
− Montre toujours les graphiques en fonction du temps, ainsi que par la distance
|
||||
− Ajout de l'aide (dans les paramètres)
|
||||
|
||||
Correction de bogue :
|
||||
- TrackDetailActivity : désactivation du mode paysage non fonctionnel (temporaire)
|
||||
@@ -0,0 +1,10 @@
|
||||
v3.2.8 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Graphique : zoom en effectuant des gestes
|
||||
|
||||
Correction de bogues :
|
||||
− L'export via KMZ n'exportait pas le nom des images correctement
|
||||
− Le partage de plusieurs tracés n'incluait pas les fichiers KMZ
|
||||
− L'IU de MarkerDetailActivity n'était pas montré
|
||||
− Les paramètres plantaient si les préférences pour le rythme cardiaque n'étaient pas initialisées
|
||||
@@ -0,0 +1,10 @@
|
||||
v3.2.9 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Option pour garder l'écran allumé lors de l'enregistrement
|
||||
− Marqueurs : suppression des marqueurs divisés
|
||||
− L'annonceur vocal fonctionne désormais sans la permission READ_PHONE_STATE
|
||||
|
||||
Correction de bogues :
|
||||
− Statistiques : le rythme cardiaque n'était pas montré
|
||||
− Statistiques : le temps était brièvement remis à 0s
|
||||
@@ -0,0 +1,11 @@
|
||||
v3.2.10 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− ChartView n'est désormais plus configurable
|
||||
− Après redémarrage : suppression du redémarrage automatique d'un enregistrement incomplet
|
||||
|
||||
Correction de bogues :
|
||||
− L'annonceur vocal utilise MAY_DUCK (à nouveau)
|
||||
− ChartView montre les marqueurs (à nouveau)
|
||||
− Correction du paysage de recordingLayout pour TrackListActivity
|
||||
− Demande du comportement de l'API des fichiers obsolètes (nécessaire pour Android 10)
|
||||
@@ -0,0 +1,12 @@
|
||||
v3.2.11 : OpenTracks
|
||||
|
||||
Bogues :
|
||||
− La vitesse maximale est égale à la vitesse moyenne
|
||||
|
||||
Correction de bogue :
|
||||
− Plantage lors de la sélection du capteur de rythme cardiaque
|
||||
|
||||
Développeurs :
|
||||
− Remplacement de TabHost par TabsLayout
|
||||
− Suppression premier point de cheminement spécial
|
||||
− Suppression des traductions dupliquées
|
||||
@@ -0,0 +1,12 @@
|
||||
v3.3.1 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Android 10 : lors de la désinstallation, permet la conservation des données de l'app
|
||||
− Introduction de l'API du tableau de bord : l'icon de la carte peut être utilisé pour ouvrir le tracé actuel dans une app externe
|
||||
(nécessite l'installation d'une app comme OSMDashboard)
|
||||
|
||||
Correction de bogue :
|
||||
− Le label de l'app était cassé (introduit en v3.3.0)
|
||||
|
||||
Développeurs :
|
||||
− La documentation pour l'API du tableau de bord se situe dans README_DEVELOPER.md
|
||||
@@ -0,0 +1,11 @@
|
||||
v3.3.2 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Export : écrase désormais les fichiers
|
||||
|
||||
Correction de bogue :
|
||||
− Supprime toujours la notification d'enregistrement
|
||||
|
||||
Développeurs :
|
||||
− Sur l'API 26+, java.time est utilisé pour analyser et écrire les dates
|
||||
− Réusinage de TrackRecordingService
|
||||
@@ -0,0 +1,12 @@
|
||||
v3.4.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− API tableau de bord : plusieurs tracés
|
||||
− Mise à jour de l'aide
|
||||
|
||||
Correction de bogues :
|
||||
− Correction du plantage lors de la recréation de fragment
|
||||
− Lors d'une pause : empêche l'app de s'arrêter
|
||||
|
||||
Développeurs :
|
||||
− Activation de tests via CI (Github Actions et TravisCI)
|
||||
@@ -0,0 +1,14 @@
|
||||
v3.5.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Marqueur : sélection d'une image depuis la galerie
|
||||
− Marqueur : partager une image
|
||||
− Utilisation du nom de la trace lors du partage
|
||||
− Suppression de l’élévation min et max (était imprécise)
|
||||
|
||||
Correction de bogue :
|
||||
− Les graphiques utilisent les unités et quantités préférées
|
||||
|
||||
Développeurs :
|
||||
− Base de données : suppression des colonnes inutilisées
|
||||
− Base de données : Ajout d'index
|
||||
@@ -0,0 +1,10 @@
|
||||
v3.6.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Les traces arrêtées peuvent être reprises
|
||||
|
||||
Correction de bogue :
|
||||
− L'import de KMZ ne traitait pas les URL de photos correctement
|
||||
|
||||
Développeurs :
|
||||
− Simplification du traitement des données
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Utilisation des données EGM2008 d'Androidx (au lieu d'empaqueter notre propre solution).
|
||||
|
||||
Développeurs :
|
||||
− Cible Android15/ SDK35
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.1 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− La détection d’immobilité peut être désactivée
|
||||
|
||||
Correction de bogue :
|
||||
− L’interface utilisateur pour ajouter des images aux marqueurs était cachée
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.14.2 : OpenTracks
|
||||
|
||||
Correction de bogue :
|
||||
− Android 15 : l’interface utilisateur ne débordera plus (bord-à-bord / edge-to-edge)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.15.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− Sélection de la langue sur l’application (Android 14 ou plus)
|
||||
− La fonctionnalité « montrer sur la carte » prend en charge uniquement OSM Dashboard (suppression de KML/KMZ ou GPX)
|
||||
|
||||
Développeurs :
|
||||
− Les actions Github utilisent désormais Ubuntu
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.0 : OpenTracks
|
||||
|
||||
Changements :
|
||||
− IPA (API) publique pour créer des marqueurs (lors de l’enregistrement)
|
||||
|
||||
Correction de bogue :
|
||||
− Capteurs : quand immobile, les données des capteurs de mouvements sont mises à 0
|
||||
@@ -0,0 +1,10 @@
|
||||
(versionName) : OpenTracks
|
||||
|
||||
Changements :
|
||||
−
|
||||
|
||||
Correction de bogue(s) :
|
||||
−
|
||||
|
||||
Développeurs :
|
||||
−
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.0: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Úsáid sonraí Androidx EGM2008 (in ionad ár réiteach saincheaptha a chuachadh).
|
||||
|
||||
Forbróir:
|
||||
- Dírigh ar Android15/ SDK35
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.1: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Is féidir brath díomhaoin a dhíchumasú
|
||||
|
||||
Ceartúchán Bug:
|
||||
- Bhí Chomhéadain chun pictiúir a chur le marcóirí i bhfolach
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.14.2: OpenTracks
|
||||
|
||||
Ceartúchán Bug:
|
||||
- Android 15: Níl an Chomhéadain ag cur thar maoil níos mó (ó imeall go himeall)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.15.0: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Roghnóir teanga in-app (Android 14 nó níos déanaí)
|
||||
- Ní thacaíonn an ghné taispeáin-ar-mapa ach le Painéal OSM (bainte KML/KMZ nó GPX)
|
||||
|
||||
Forbróir:
|
||||
- Úsáideann gníomhartha Github anois Ubuntu
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.16.0: OpenTracks
|
||||
|
||||
Ceartúchán Bug:
|
||||
- PublicAPI: níor taifeadadh aon sonraí le tosú taifeadta
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.16.1: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Roghnóir teanga in-app ar fáil anois do gach leagan Android
|
||||
(mar gheall ar roinnt éileamh coitianta)
|
||||
|
||||
Forbróir:
|
||||
- Gníomhartha Github: ní raibh an tseiceáil amach ag fáil clibeanna (oíche)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.0: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- API poiblí chun marcóirí a chruthú (agus tú ag taifeadadh)
|
||||
|
||||
Ceartúchán Bug:
|
||||
- Braiteoirí: i gcás díomhaoin, socraigh sonraí braiteora bunaithe ar ghluaiseacht go 0
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.17.1: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Tógáil atáirgthe: féachaimis an n-oibríonn sé.
|
||||
Cuirfear an leagan PlayStore faoi bhráid F-Droid, fíorófar iad agus foilseofar iad.
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Tógáil atáirgthe: féachaimis an n-oibríonn sé.
|
||||
Cuirfear an leagan PlayStore faoi bhráid F-Droid, fíorófar iad agus foilseofar iad.
|
||||
|
||||
Forbróir:
|
||||
- Éilíonn F-Droid Blasanna Táirge a úsáid (in ionad Cineálacha Tógála)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.3: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Tógáil atáirgthe: féachaimis an n-oibríonn sé.
|
||||
|
||||
Forbróir:
|
||||
- Díreach ag iarraidh ainm an chomhaid APK a fháil, ceart ...
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.4: OpenTracks
|
||||
|
||||
|
||||
Athruithe:
|
||||
- Tógáil atáirgthe: féachaimis an n-oibríonn sé.
|
||||
|
||||
Forbróir:
|
||||
- DependencyInfo a bhaint.
|
||||
@@ -0,0 +1,10 @@
|
||||
v4.17.5: OpenTracks
|
||||
|
||||
Athruithe:
|
||||
- Tógáil atáirgthe: féachaimis an n-oibríonn sé.
|
||||
|
||||
Ceartúchán Bug:
|
||||
- Úsáideann tógáil atáirgthe íocón PlayStore.
|
||||
|
||||
Forbróir:
|
||||
- Curtha leis RELEASE_BUILD.sh
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Cambios:
|
||||
- Compilación reproducible: comprobemos se funciona ben.
|
||||
Enviaremos a F-Droid a variante da Play Store, para que a verifiquen e publiquen.
|
||||
|
||||
Desenvolvemento:
|
||||
- F-Droid require que usemos Product Flavors (no lugar de Build Types)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.3: OpenTracks
|
||||
|
||||
Cambios:
|
||||
- Compilación reproducible: agardemos que funcione ben.
|
||||
|
||||
Desenvolvemento:
|
||||
- Intento de que o nome do ficheiro APK sai a ben, vexamos...
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.0: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Gebruik de EGM2008-gegevens van Androidx (in plaats van onze aangepaste oplossing te bundelen).
|
||||
|
||||
Ontwikkelaar:
|
||||
- Target Android15 / SDK35
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.14.1: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Detectie van inactiviteit kan worden uitgeschakeld
|
||||
|
||||
Opgeloste probleemoplossing:
|
||||
- Gebruikersinterface voor het toevoegen van afbeeldingen aan markeringen is verborgen
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.14.2: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- Android 15: gebruikersinterface loopt niet meer over (rand tot rand)
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.15.0: OpenTracks
|
||||
|
||||
Wijzigingen:
|
||||
- In-app taalkiezer (Android 14 of hoger)
|
||||
- Show-on-map-functie ondersteunt alleen OSM Dashboard (verwijderd KML/KMZ of GPX)
|
||||
|
||||
Ontwikkelaar:
|
||||
- Github-acties gebruiken nu Ubuntu
|
||||
@@ -0,0 +1,4 @@
|
||||
v4.16.0: OpenTracks
|
||||
|
||||
Opgelost probleem:
|
||||
- PublicAPI: bij het starten van een opname zijn geen gegevens vastgelegd
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.16.1: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- In-app taalkiezer nu beschikbaar voor alle Android-versies
|
||||
(op veler verzoek)
|
||||
|
||||
Ontwikkelaar:
|
||||
- Github-acties: checkout was not fetching tags (nightly)
|
||||
@@ -0,0 +1,9 @@
|
||||
v4.17.0: OpenTracks
|
||||
|
||||
Aanpassing:
|
||||
|
||||
- Openbare API om markeringen te maken (tijdens opname)
|
||||
|
||||
Opgelost:
|
||||
|
||||
- Sensoren: bij rust de op beweging gebaseerde sensorgegevens op 0 zetten
|
||||
@@ -0,0 +1,5 @@
|
||||
v4.17.1: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Reproduceerbare build: laten we eens kijken of het werkt.
|
||||
De PlayStore-variant wordt ingediend bij F-Droid, geverifieerd en gepubliceerd.
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.2: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Reproduceerbare build: laten we eens kijken of het werkt.
|
||||
De PlayStore-variant wordt ingediend bij F-Droid, geverifieerd en gepubliceerd.
|
||||
|
||||
Ontwikkelaar:
|
||||
- F-Droid vereist het gebruik van productsmaken (in plaats van buildtypes)
|
||||
@@ -0,0 +1,7 @@
|
||||
v4.17.3: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Reproduceerbare build: laten we eens kijken of het werkt.
|
||||
|
||||
Ontwikkelaar:
|
||||
- Ik probeer gewoon de APK-bestandsnaam te krijgen, toch...
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.17.4: OpenTracks
|
||||
|
||||
|
||||
Veranderingen:
|
||||
- Reproduceerbare build: laten we eens kijken of het werkt.
|
||||
|
||||
Ontwikkelaar:
|
||||
- DependencyInfo verwijderen.
|
||||
@@ -0,0 +1,10 @@
|
||||
v4.17.5: OpenTracks
|
||||
|
||||
Veranderingen:
|
||||
- Reproduceerbare build: laten we eens kijken of het werkt.
|
||||
|
||||
Opgelost probleem:
|
||||
- Reproduceerbare build maakt gebruik van het PlayStore-pictogram.
|
||||
|
||||
Ontwikkelaar:
|
||||
- Toegevoegd RELEASE_BUILD.sh
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
Vendored
+2
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
||||
+9
-9
@@ -482,7 +482,7 @@ public class CustomContentProviderUtilsTest {
|
||||
assertEquals(contentProviderUtils.getMarkers(trackId).size(), 1);
|
||||
|
||||
// Get marker id that needs to delete.
|
||||
Marker.Id marker1Id = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker1)));
|
||||
Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1);
|
||||
|
||||
// Delete
|
||||
contentProviderUtils.deleteMarker(context, marker1Id);
|
||||
@@ -509,7 +509,7 @@ public class CustomContentProviderUtilsTest {
|
||||
assertEquals(contentProviderUtils.getMarkers(trackId).size(), 1);
|
||||
|
||||
// Get marker id that needs to delete.
|
||||
Marker.Id marker1Id = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker1)));
|
||||
Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1);
|
||||
|
||||
// Check marker has photo and it's in the external storage.
|
||||
assertTrue(marker1.hasPhoto());
|
||||
@@ -553,11 +553,11 @@ public class CustomContentProviderUtilsTest {
|
||||
// Insert at first.
|
||||
Marker marker1 = new Marker(trackId, contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
marker1.setDescription(MOCK_DESC);
|
||||
Marker.Id marker1Id = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker1)));
|
||||
Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1);
|
||||
|
||||
Marker marker2 = new Marker(trackId, contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
marker2.setDescription(MOCK_DESC);
|
||||
Marker.Id marker2Id = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker2)));
|
||||
Marker.Id marker2Id = contentProviderUtils.insertMarker(marker2);
|
||||
|
||||
// Delete
|
||||
assertNotNull(contentProviderUtils.getMarker(marker1Id));
|
||||
@@ -598,7 +598,7 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
Marker marker = new Marker(trackId, contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
marker.setDescription(TEST_DESC);
|
||||
Marker.Id markerId = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker)));
|
||||
Marker.Id markerId = contentProviderUtils.insertMarker(marker);
|
||||
|
||||
assertEquals(TEST_DESC, contentProviderUtils.getMarker(markerId).getDescription());
|
||||
}
|
||||
@@ -614,7 +614,7 @@ public class CustomContentProviderUtilsTest {
|
||||
// Insert at first.
|
||||
Marker marker = new Marker(trackId, contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
marker.setDescription(TEST_DESC);
|
||||
Marker.Id markerId = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker)));
|
||||
Marker.Id markerId = contentProviderUtils.insertMarker(marker);
|
||||
|
||||
// Update
|
||||
marker = contentProviderUtils.getMarker(markerId);
|
||||
@@ -638,7 +638,7 @@ public class CustomContentProviderUtilsTest {
|
||||
TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||
Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint);
|
||||
marker.setDescription(TEST_DESC);
|
||||
Marker.Id markerId = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker)));
|
||||
Marker.Id markerId = contentProviderUtils.insertMarker(marker);
|
||||
|
||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.id());
|
||||
assertTrue(dir.exists());
|
||||
@@ -673,7 +673,7 @@ public class CustomContentProviderUtilsTest {
|
||||
TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||
Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint);
|
||||
marker.setDescription(TEST_DESC);
|
||||
Marker.Id markerId = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker)));
|
||||
Marker.Id markerId = contentProviderUtils.insertMarker(marker);
|
||||
|
||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.id());
|
||||
assertTrue(dir.exists());
|
||||
@@ -709,7 +709,7 @@ public class CustomContentProviderUtilsTest {
|
||||
marker.setDescription(TEST_DESC);
|
||||
Marker otherMarker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint);
|
||||
otherMarker.setDescription(TEST_DESC);
|
||||
Marker.Id markerId = new Marker.Id(ContentUris.parseId(contentProviderUtils.insertMarker(marker)));
|
||||
Marker.Id markerId = contentProviderUtils.insertMarker(marker);
|
||||
contentProviderUtils.insertMarker(otherMarker);
|
||||
|
||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.id());
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.junit.Test;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import de.dennisguse.opentracks.BuildConfig;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
|
||||
@@ -34,6 +35,7 @@ public class ShareContentProviderTest {
|
||||
public void testCreateURIescapeFilename() {
|
||||
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(Set.of(new Track.Id(1)), "../../&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"), shareURIandMIME.first);
|
||||
|
||||
assertEquals(Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".content/tracks/KML_WITH_TRACKDETAIL_AND_SENSORDATA/1/..%2F..%2F%261%3D1"), shareURIandMIME.first);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -157,7 +157,7 @@ public class ExportImportTest {
|
||||
contentProviderUtils.insertMarker(new Marker("Marker 2", "Marker 2 desc", "Marker 2 category", null, trackId, service.getLastStoredTrackPointWithLocation(), ""));
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:02:18Z");
|
||||
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet();
|
||||
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator);
|
||||
service.endCurrentTrack();
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:03:20Z");
|
||||
@@ -172,7 +172,7 @@ public class ExportImportTest {
|
||||
|
||||
sendLocation(trackPointCreator, "2020-02-02T02:03:50Z", 3, 16.001, 10, 27, 15, 10, 0f);
|
||||
|
||||
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet();
|
||||
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator);
|
||||
trackPointCreator.setClock("2020-02-02T02:04:00Z");
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -550,22 +550,22 @@ public class ExportImportTest {
|
||||
|
||||
AggregatorCyclingPower cyclingPower = Mockito.mock(AggregatorCyclingPower.class);
|
||||
Mockito.when(cyclingPower.hasValue()).thenReturn(true);
|
||||
Mockito.when(cyclingPower.getValue()).thenReturn(Power.of(power));
|
||||
Mockito.when(cyclingPower.getValue(Mockito.any())).thenReturn(Power.of(power));
|
||||
sensorDataSet.add(cyclingPower);
|
||||
|
||||
AggregatorHeartRate agheartRate = Mockito.mock(AggregatorHeartRate.class);
|
||||
Mockito.when(agheartRate.getValue()).thenReturn(HeartRate.of(heartRate));
|
||||
sensorDataSet.add(agheartRate);
|
||||
AggregatorHeartRate avgHeartRate = Mockito.mock(AggregatorHeartRate.class);
|
||||
Mockito.when(avgHeartRate.getValue(Mockito.any())).thenReturn(HeartRate.of(heartRate));
|
||||
sensorDataSet.add(avgHeartRate);
|
||||
|
||||
AggregatorCyclingCadence cyclingCadence = Mockito.mock(AggregatorCyclingCadence.class);
|
||||
Mockito.when(cyclingCadence.hasValue()).thenReturn(true);
|
||||
Mockito.when(cyclingCadence.getValue()).thenReturn(Cadence.of(cadence));
|
||||
Mockito.when(cyclingCadence.getValue(Mockito.any())).thenReturn(Cadence.of(cadence));
|
||||
sensorDataSet.add(cyclingCadence);
|
||||
|
||||
if (distance != null && speed != null) {
|
||||
AggregatorCyclingDistanceSpeed distanceSpeed = Mockito.mock(AggregatorCyclingDistanceSpeed.class);
|
||||
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
|
||||
Mockito.when(distanceSpeed.getValue()).thenReturn(new AggregatorCyclingDistanceSpeed.Data(null, distance, Speed.of(speed)));
|
||||
Mockito.when(distanceSpeed.getValue(Mockito.any())).thenReturn(new AggregatorCyclingDistanceSpeed.Data(null, distance, Speed.of(speed)));
|
||||
sensorDataSet.add(distanceSpeed);
|
||||
} else {
|
||||
sensorDataSet.add(new AggregatorCyclingDistanceSpeed("", ""));
|
||||
@@ -582,7 +582,7 @@ public class ExportImportTest {
|
||||
if (altitudeGain != null) {
|
||||
AggregatorBarometer barometer = Mockito.mock(AggregatorBarometer.class);
|
||||
Mockito.when(barometer.hasValue()).thenReturn(true);
|
||||
Mockito.when(barometer.getValue()).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
|
||||
Mockito.when(barometer.getValue(Mockito.any())).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
|
||||
sensorDataSet.add(barometer);
|
||||
} else {
|
||||
sensorDataSet.add(new AggregatorBarometer("test", null));
|
||||
|
||||
@@ -31,13 +31,7 @@ public class PublicApiTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Test
|
||||
public void StartTest() {
|
||||
PreferencesUtils.setBoolean(R.string.publicapi_enabled_key, true);
|
||||
|
||||
context.startActivity(IntentUtils.newIntent(context, StartRecording.class));
|
||||
}
|
||||
|
||||
//NOTE: this doesn't check if the TrackRecordingService was started in foreground.
|
||||
@Test
|
||||
public void StartStopTest() throws InterruptedException {
|
||||
PreferencesUtils.setBoolean(R.string.publicapi_enabled_key, true);
|
||||
|
||||
+3
-1
@@ -3,13 +3,15 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
|
||||
|
||||
public class AggregatorBarometerTest {
|
||||
|
||||
private static void addSensorValue(AggregatorBarometer aggregatorBarometer, float[] values) {
|
||||
for (float f : values) {
|
||||
aggregatorBarometer.add(new Raw<>(AtmosphericPressure.ofHPA(f)));
|
||||
aggregatorBarometer.add(new Raw<>(Instant.MIN, AtmosphericPressure.ofHPA(f)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-24
@@ -9,6 +9,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
@@ -23,11 +25,11 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 2048)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 2048)));
|
||||
|
||||
// then
|
||||
assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
assertEquals(60, current.getValue(Instant.MIN).getRPM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -35,11 +37,11 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 6184)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 8016)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 6184)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 8016)));
|
||||
|
||||
// then
|
||||
assertEquals(33.53, current.getValue().getRPM(), 0.01);
|
||||
assertEquals(33.53, current.getValue(Instant.MIN).getRPM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -47,11 +49,11 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 2048)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 2048)));
|
||||
|
||||
// then
|
||||
assertEquals(Cadence.of(0), current.getValue());
|
||||
assertEquals(Cadence.of(0), current.getValue(Instant.MIN));
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +62,8 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 1024)));
|
||||
|
||||
// then
|
||||
assertFalse(current.hasValue()); //TODO Cadence should be 0?
|
||||
@@ -72,11 +74,11 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, UintUtils.UINT16_MAX - 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 0)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, UintUtils.UINT16_MAX - 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 0)));
|
||||
|
||||
// then
|
||||
assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
assertEquals(60, current.getValue(Instant.MIN).getRPM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,13 +87,13 @@ public class SensorDataCyclingTest {
|
||||
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(0, 2048)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(0, 2048)));
|
||||
|
||||
// then
|
||||
// TODO See #953
|
||||
// assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
assertNull(current.getValue());
|
||||
assertNull(current.getValue(Instant.MIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,12 +102,12 @@ public class SensorDataCyclingTest {
|
||||
current.setWheelCircumference(Distance.ofMM(2150));
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(1, 6184)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(2, 8016)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(1, 6184)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(2, 8016)));
|
||||
|
||||
// then
|
||||
assertEquals(2.15, current.getValue().distance().toM(), 0.01);
|
||||
assertEquals(1.20, current.getValue().speed().toMPS(), 0.01);
|
||||
assertEquals(2.15, current.getValue(Instant.MIN).distance().toM(), 0.01);
|
||||
assertEquals(1.20, current.getValue(Instant.MIN).speed().toMPS(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -115,14 +117,14 @@ public class SensorDataCyclingTest {
|
||||
current.setWheelCircumference(Distance.ofMM(2000));
|
||||
|
||||
// when
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(0, 2048)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(0, 2048)));
|
||||
|
||||
|
||||
// then
|
||||
// TODO See #953
|
||||
// assertEquals(2, current.getValue().getDistance().toM(), 0.01);
|
||||
// assertEquals(2, current.getValue().getSpeed().toMPS(), 0.01);
|
||||
assertNull(current.getValue());
|
||||
assertNull(current.getValue(Instant.MIN));
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -304,11 +304,11 @@ public class TrackRecordingServiceRecordingTest {
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
|
||||
sensorManager.onChanged(new Raw<>(HeartRate.of(5))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(sensor1, HeartRate.of(5))); //Should be ignored
|
||||
|
||||
String sensor3 = "2020-02-02T02:02:13Z";
|
||||
trackPointCreator.setClock(sensor3);
|
||||
sensorManager.onChanged(new Raw<>(HeartRate.of(7)));
|
||||
sensorManager.onChanged(new Raw<>(sensor3, HeartRate.of(7)));
|
||||
|
||||
String stopTime = "2020-02-02T02:02:15Z";
|
||||
trackPointCreator.setClock(stopTime);
|
||||
@@ -646,12 +646,12 @@ public class TrackRecordingServiceRecordingTest {
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(0)))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(sensor1, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(0)))); //Should be ignored
|
||||
|
||||
// when
|
||||
String sensor2 = "2020-02-02T02:02:04Z";
|
||||
trackPointCreator.setClock(sensor2);
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(2))));
|
||||
sensorManager.onChanged(new Raw<>(sensor2, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(2))));
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:05Z";
|
||||
@@ -660,12 +660,12 @@ public class TrackRecordingServiceRecordingTest {
|
||||
// when
|
||||
String sensor3 = "2020-02-02T02:02:06Z";
|
||||
trackPointCreator.setClock(sensor3);
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(12))));
|
||||
sensorManager.onChanged(new Raw<>(sensor3, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(12))));
|
||||
|
||||
// when
|
||||
String sensor4 = "2020-02-02T02:02:07Z";
|
||||
trackPointCreator.setClock(sensor4);
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(14)))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(sensor4, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(14)))); //Should be ignored
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:08Z";
|
||||
@@ -674,7 +674,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
// when
|
||||
String sensor5 = "2020-02-02T02:02:10Z";
|
||||
trackPointCreator.setClock(sensor5);
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(16)))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(sensor5, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(16)))); //Should be ignored
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:12Z";
|
||||
@@ -730,7 +730,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
|
||||
AggregatorBarometer barometer = Mockito.mock(AggregatorBarometer.class);
|
||||
Mockito.when(barometer.hasValue()).thenReturn(true);
|
||||
Mockito.when(barometer.getValue()).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
|
||||
Mockito.when(barometer.getValue(Mockito.any())).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
|
||||
|
||||
trackPointCreator.getSensorManager().sensorDataSet.barometer = barometer;
|
||||
}
|
||||
|
||||
+153
-34
@@ -1,9 +1,11 @@
|
||||
package de.dennisguse.opentracks.services.announcement;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@@ -13,8 +15,10 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -26,6 +30,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
@@ -45,6 +50,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
public void setUp() {
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
|
||||
PreferencesUtils.setVoiceAnnounceHeartRateCurrent(false);
|
||||
PreferencesUtils.setVoiceAnnounceLapHeartRate(false);
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(false);
|
||||
PreferencesUtils.setVoiceAnnounceTotalDistance(true);
|
||||
@@ -53,68 +59,101 @@ public class VoiceAnnouncementUtilsTest {
|
||||
PreferencesUtils.setVoiceAnnounceLapSpeedPace(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sdkRequirement() {
|
||||
assertFalse("Due to DateTimeFormatter using NBSP, these tests only work in SDK34+", Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Average moving speed 18.4 kilometers per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Average moving speed 18.4 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed_rounding_check() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusSeconds(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 20.0 kilometers. 1 hour 1 second. Average moving speed 20.0 kilometers per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 1 second. Average moving speed 20.0 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_distance_rounding_check() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(19999));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 20.0 kilometers. 1 hour. Average moving speed 20.0 kilometers per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour. Average moving speed 20.0 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_distance_rounding_check_two() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(19900));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 19.9 kilometers. 1 hour. Average moving speed 19.9 kilometers per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 19.9 kilometers. 1 hour. Average moving speed 19.9 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -132,27 +171,40 @@ public class VoiceAnnouncementUtilsTest {
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_pace() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, false, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, false, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Pace 3 minutes 15 seconds per kilometer.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Pace 3 minutes 15 seconds per kilometer.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -170,69 +222,103 @@ public class VoiceAnnouncementUtilsTest {
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, false, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, false, lastInterval, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 14.2 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_speed() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Average moving speed 11.4 miles per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Average moving speed 11.4 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofMile(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_meter_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofMile(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_METER, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_METER, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofKilometer(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 1.1 kilometers. 1 hour. Average moving speed 1.1 kilometers per hour.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 1.1 kilometers. 1 hour. Average moving speed 1.1 kilometers per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -250,27 +336,40 @@ public class VoiceAnnouncementUtilsTest {
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
|
||||
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_pace() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_FEET, false, null, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, false, null, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
|
||||
assertEquals("12:00 AM. Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -288,11 +387,17 @@ public class VoiceAnnouncementUtilsTest {
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
|
||||
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -314,17 +419,25 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null, null);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
|
||||
// then
|
||||
assertEquals("Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Current heart rate 133 bpm.", announcement);
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_only_lap_heart_rate() {
|
||||
public void getAnnouncement_heart_rate() {
|
||||
PreferencesUtils.setVoiceAnnounceHeartRateCurrent(true);
|
||||
PreferencesUtils.setVoiceAnnounceLapHeartRate(true);
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(false);
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(true);
|
||||
|
||||
PreferencesUtils.setVoiceAnnounceTotalDistance(false);
|
||||
PreferencesUtils.setVoiceAnnounceMovingTime(false);
|
||||
PreferencesUtils.setVoiceAnnounceAverageSpeedPace(false);
|
||||
@@ -344,11 +457,17 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null, null);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, stats, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
|
||||
// then
|
||||
assertEquals(" Current heart rate 133 bpm.", announcement);
|
||||
assertEquals("12:16 AM. Current heart rate 60 bpm. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -98,6 +98,14 @@ limitations under the License.
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".publicapi.CreateMarker"
|
||||
android:exported="true"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- NOTE: the name of the MAIN/LAUNCHER is used by icon packs; if this is changed, icon packs break.-->
|
||||
<activity
|
||||
@@ -401,6 +409,16 @@ limitations under the License.
|
||||
android:name=".services.TrackDeleteService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||
|
||||
<!--Necessary for SDK < 33 to (re-)store per app locale information-->
|
||||
<service
|
||||
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||
android:enabled="false"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="autoStoreLocales"
|
||||
android:value="true" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
|
||||
@@ -286,6 +286,11 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.getItemId() == R.id.track_list_about) {
|
||||
startActivity(IntentUtils.newIntent(this, AboutActivity.class));
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user