mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-25 18:44:45 +01:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2692cc553c | |||
| 3db4dc9422 | |||
| 01bb4429ad | |||
| ca817e789e | |||
| 7bf2110a54 | |||
| 78662a330f | |||
| 8bfaa1d542 | |||
| 5a1bee13f9 | |||
| b01045abe4 | |||
| d7fbae9321 | |||
| ab5e6cbfcd | |||
| 0848897ed0 | |||
| 1e4e7b8c15 | |||
| 7ca6925e7d | |||
| 5c06c7548f | |||
| 8001c03a74 | |||
| 30f9b6ffdc | |||
| a7fd6b8dfa | |||
| cc93384d1f | |||
| 78519883c0 | |||
| 29051ac978 | |||
| cf32c81035 | |||
| 094c97f78d | |||
| 8dca84456b | |||
| f962f27309 | |||
| 2f0826baf6 | |||
| b7ff0e2fac | |||
| fe6ef29f75 | |||
| 152cf72e8a | |||
| 4fd66a3830 | |||
| 9f715207e1 | |||
| e63ddbc7ae | |||
| 06e5545ac0 | |||
| 65413e0304 | |||
| 5e268463e1 | |||
| d31ffad2c9 | |||
| 46925a4c67 | |||
| 2a1aeb5dd8 | |||
| 454d5d16b5 | |||
| 45f51ff2dd | |||
| 785511913c | |||
| b937e8ad9b | |||
| 40534cd7f5 | |||
| f50b1c2f6c | |||
| 7c19621bfb | |||
| 7c06327084 | |||
| 19a958ccbb | |||
| 2dc362c105 | |||
| 708245bd50 | |||
| f4c07463b3 | |||
| d8ffc1318f | |||
| 5998f9127d | |||
| 40fb9b05bc | |||
| 8219bfe428 | |||
| bcdea5b08b | |||
| 5e49a38dce | |||
| 32e07c9d1f | |||
| efc37527f3 | |||
| 90a2710138 | |||
| bf4dd96235 |
@@ -1,6 +1,8 @@
|
||||
name: Linting
|
||||
|
||||
on: [ push ]
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
analyse:
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#https://github.com/marketplace/actions/android-emulator-runner
|
||||
name: Test
|
||||
on: [ push ]
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 45
|
||||
@@ -20,7 +23,7 @@ jobs:
|
||||
java-version: '11'
|
||||
|
||||
- name: run tests
|
||||
uses: reactivecircus/android-emulator-runner@v2.22.0
|
||||
uses: reactivecircus/android-emulator-runner@v2.23.0
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
Generated
+6
@@ -3,6 +3,12 @@
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
<map>
|
||||
<entry key="src/main/res/drawable/ic_activity_bike_24dp.xml" value="0.1765" />
|
||||
<entry key="src/main/res/drawable/ic_activity_sailing_24dp.xml" value="0.1935" />
|
||||
<entry key="src/main/res/drawable/ic_activity_snowboarding_24dp.xml" value="0.1935" />
|
||||
<entry key="src/main/res/drawable/ic_activity_swimming_24dp.xml" value="0.1935" />
|
||||
<entry key="src/main/res/drawable/ic_activity_swimming_open_24dp.xml" value="0.1935" />
|
||||
<entry key="src/main/res/drawable/ic_activity_workout_24dp.xml" value="0.1935" />
|
||||
<entry key="src/main/res/menu/aggregated_statistics.xml" value="0.10208333333333333" />
|
||||
<entry key="src/main/res/xml/settings_gps.xml" value="0.22604166666666667" />
|
||||
<entry key="src/main/res/xml/settings_sensors.xml" value="0.2101851851851852" />
|
||||
|
||||
@@ -118,27 +118,33 @@ __Only required permission:__
|
||||
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
||||
|
||||
### API
|
||||
The following functionalities by sending from an external 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 Intent to start an activity.
|
||||
Package (depends on the variant installed):
|
||||
|
||||
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.
|
||||
|
||||
`Package` (depends on the variant installed):
|
||||
* F-Droid: `de.dennisguse.opentracks`
|
||||
* GooglePlay: `de.dennisguse.opentracks.playStore`
|
||||
* Debug: `de.dennisguse.opentracks.debug`
|
||||
* Nightly: `de.dennisguse.opentracks.nightly`
|
||||
|
||||
Activity:
|
||||
`Class`:
|
||||
* **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording`
|
||||
|
||||
* For testing via adb: `adb shell am start -n "package/activity"`
|
||||
For testing via adb: `adb shell am start -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.
|
||||
|
||||
## Custom Dashboards (incl. map)
|
||||
As of v3.3.1, OpenTracks supports custom dashboards.
|
||||
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which presents an OpenStreetMap map (showing the current track, incl. updates).
|
||||
The developer documentation is in [README_API.md](README_API.md).
|
||||
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).
|
||||
|
||||
## Project history
|
||||
|
||||
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
|
||||
|
||||
+13
-6
@@ -4,11 +4,13 @@
|
||||
OpenTracks by itself only provides basic features for data visualization and also lacks functionality for analytics.
|
||||
By itself OpenTracks provides a basic dashboard that can show summary of a track (while recording as well as afterwards).
|
||||
Although this might be (mostly) sufficient, it has some limitations.
|
||||
This include limited configurability (e.g., ordering of shown elements) and the lack of Internet access.
|
||||
In fact, the later is considered a feature but severely limits the implementation presenting a map (at least in an easy way).
|
||||
This includes limited configurability (e.g., ordering of shown elements) and the lack of internet access.
|
||||
In fact, the latter is considered a feature but severely limits the implementation presenting a map (at least in an easy way).
|
||||
|
||||
For the time being, the OpenTracks Data API can be used to implement mainly custom dashboards.
|
||||
|
||||
The Data API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings.
|
||||
|
||||
## Implementation
|
||||
OpenTracks by default does not expose any data to 3rd-party applications.
|
||||
On the request of the user (i.e., pressing a button), an Intent is created that exposes the `Track` data (it's summary), the `TrackPoint`s, and the `Waypoint`s of one or more selected tracks.
|
||||
@@ -17,11 +19,16 @@ These URIs notify observers if on content changes (e.g., a new `TrackPoint` was
|
||||
|
||||
Limitations:
|
||||
* only tracks selected by the user are exposed,
|
||||
* `Waypoints` are not exposed,
|
||||
* `Waypoint`s are not exposed,
|
||||
* access is only granted temporarily and automatically revoked (see `FLAG_GRANT_READ_URI_PERMISSION`),
|
||||
* no write access is possible, and
|
||||
* neither track recordings can be started, paused, or stopped.
|
||||
* no write access is possible
|
||||
|
||||
The Data API can also be started automatically by leveraging Extra fields in the explicit Intent for the Start/Stop API.
|
||||
An application that's starting a recording with an explicit Intent can add the `STATS_TARGET_PACKAGE` and `STATS_TARGET_CLASS` Extra fields to let OpenTracks know it wants to receive the Data API URIs.
|
||||
OpenTracks will then (if enabled in the settings) automatically return an explicit Intent to the Package + Class as defined in the received Extra fields, including the Data API URIs and read permissions.
|
||||
|
||||
By using explicit Intents for the calls and URIs with specific temporary read permissions, OpenTracks tries to protect against data leaking as much as possible.
|
||||
|
||||
All required information can be found in `IntentDashboardUtils.java`.
|
||||
|
||||
A _reference implementation_ is the [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard).
|
||||
A _reference implementation_ is the [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard).
|
||||
|
||||
+6
-10
@@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath 'com.android.tools.build:gradle:7.1.1'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,18 +57,13 @@ android {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
cruncherEnabled = false
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 4692
|
||||
versionName "v3.24.1"
|
||||
versionCode 4752
|
||||
versionName "v3.25.0"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
|
||||
@@ -98,6 +93,7 @@ android {
|
||||
}
|
||||
|
||||
release {
|
||||
crunchPngs false
|
||||
minifyEnabled false
|
||||
}
|
||||
|
||||
@@ -124,7 +120,7 @@ dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
|
||||
@@ -134,7 +130,7 @@ dependencies {
|
||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:4.2.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:4.3.1'
|
||||
|
||||
androidTestUtil 'androidx.test:orchestrator:1.4.1'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="22"
|
||||
width="22"
|
||||
fill="#000000"
|
||||
version="1.0"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 21.84952 21.99934"
|
||||
enable-background="new 0 0 99.316 99.997"
|
||||
xml:space="preserve"
|
||||
id="svg10"
|
||||
sodipodi:docname="ic_activity_swimming.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||
inkscape:export-filename="/home/peter/StudioProjects/OpenTracks/drawable-svg/ic_activity_swimming.png"
|
||||
inkscape:export-xdpi="1309.09"
|
||||
inkscape:export-ydpi="1309.09"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><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" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs14" /><sodipodi:namedview
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1831"
|
||||
inkscape:window-height="1039"
|
||||
id="namedview12"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:zoom="31.780381"
|
||||
inkscape:cx="10.368032"
|
||||
inkscape:cy="10.069105"
|
||||
inkscape:window-x="33"
|
||||
inkscape:window-y="3"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg10"
|
||||
inkscape:document-rotation="0" /><path
|
||||
id="path2"
|
||||
style="fill:#ffffff;stroke-width:0.20758"
|
||||
d="m 18.327285,15.516652 c -1.017125,-0.01824 -1.903328,0.770666 -2.945647,0.500454 -0.952298,-0.271819 -1.950516,-0.765534 -2.949277,-0.338881 -0.938402,0.492101 -2.078868,0.493759 -3.0170251,0 C 8.4157577,15.251421 7.4164572,15.744755 6.4634103,16.017106 5.261142,16.31195 4.2317908,15.256338 3.0296629,15.558611 2.2388959,15.806745 1.0534821,16.11293 1.0534821,16.11293 v 1.764949 c 1.0226762,0.01947 1.9128198,-0.776355 2.9601398,-0.498166 1.4912769,0.589492 1.7842151,0.623743 2.7777974,0.375279 0.9553792,-0.44042 2.0942104,-0.606317 3.0559286,-0.07975 0.9566571,0.429062 1.9815791,0.09313 2.8934291,-0.263824 1.038124,-0.339466 1.95525,0.382078 2.955963,0.461915 1.087184,0.105691 2.019821,-0.784126 3.121615,-0.493622 0.55673,-0.01509 1.943197,1.034046 1.977683,0.148315 v -1.471252 c -0.878739,0.05089 -1.592095,-0.588897 -2.468753,-0.540124 z"
|
||||
sodipodi:nodetypes="scccccccccccccccss" /><path
|
||||
id="path2-1"
|
||||
style="fill:#ffffff;stroke-width:0.20758"
|
||||
d="m 18.327285,12.592022 c -1.017125,-0.01824 -1.903328,0.770666 -2.945647,0.500454 -0.952298,-0.271819 -1.950516,-0.765534 -2.949277,-0.338881 -0.938402,0.492101 -2.078868,0.493759 -3.0170249,0 C 8.4157578,12.326791 7.4164573,12.820125 6.4634104,13.092476 5.2611421,13.38732 4.2317909,12.331708 3.029663,12.633981 2.238896,12.882115 1.0534822,13.1883 1.0534822,13.1883 v 1.764949 c 1.0226762,0.01947 1.9128198,-0.776355 2.9601398,-0.498166 1.4912769,0.589492 1.7842151,0.623743 2.7777974,0.375279 0.9553792,-0.44042 2.0942104,-0.606317 3.0559286,-0.07975 0.956657,0.429062 1.981579,0.09313 2.893429,-0.263824 1.038124,-0.339466 1.95525,0.382078 2.955963,0.461915 1.087184,0.105691 2.019821,-0.784126 3.121615,-0.493622 0.55673,-0.01509 1.943197,1.034046 1.977683,0.148315 v -1.471252 c -0.878739,0.05089 -1.592095,-0.588897 -2.468753,-0.540124 z"
|
||||
sodipodi:nodetypes="scccccccccccccccss" /><path
|
||||
id="path851"
|
||||
style="fill:#ffffff;stroke-width:1.16861"
|
||||
d="m 15.771645,8.3604958 c 0.05505,1.1807818 -1.406378,2.0132882 -2.394197,1.3656158 -1.044532,-0.5537235 -1.017922,-2.2353035 0.04332,-2.7559408 1.018447,-0.5919723 2.378758,0.20782 2.350877,1.390325 z" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.18448px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 4.3145569,12.014368 9.3210561,8.9478742 6.786081,6.2628496 11.908511,3.5970428 c 0.936726,-0.3746046 1.601464,0.5528762 1.096915,1.1662478 L 9.4152098,6.6598661 15.504839,12.51419 c -1.334475,-0.390685 -1.595745,-1.008768 -2.663055,-0.656789 -2.818488,0.929488 -2.219707,0.0047 -4.240291,0.02086 -2.2836952,0.01821 -1.8989609,1.154049 -4.2869361,0.136107 z"
|
||||
id="path2791"
|
||||
sodipodi:nodetypes="cccccccssc" /></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="22"
|
||||
width="22"
|
||||
fill="#000000"
|
||||
version="1.0"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 21.84952 21.99934"
|
||||
enable-background="new 0 0 99.316 99.997"
|
||||
xml:space="preserve"
|
||||
id="svg10"
|
||||
sodipodi:docname="ic_activity_swimming_open.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||
inkscape:export-filename="/home/peter/StudioProjects/OpenTracks/drawable-svg/ic_activity_swimming_open.png"
|
||||
inkscape:export-xdpi="1309.09"
|
||||
inkscape:export-ydpi="1309.09"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><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" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs14" /><sodipodi:namedview
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1047"
|
||||
id="namedview12"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:zoom="15.890191"
|
||||
inkscape:cx="10.006173"
|
||||
inkscape:cy="13.719156"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10"
|
||||
inkscape:document-rotation="0" /><path
|
||||
id="path2"
|
||||
style="fill:#ffffff;stroke-width:0.150857"
|
||||
d="m 2.8183594,17.572266 c -0.1057708,4.65e-4 -0.2130618,0.01356 -0.3222656,0.04102 -0.5746803,0.180329 -1.4355469,0.402344 -1.4355469,0.402344 v 1.28125 c 0.7432174,0.01415 1.3912167,-0.563498 2.1523437,-0.361328 1.0837672,0.428407 1.295504,0.454005 2.0175782,0.273437 0.6943098,-0.32007 1.5217861,-0.441266 2.2207031,-0.05859 0.6952388,0.311815 1.4408397,0.06801 2.1035156,-0.191407 0.7544435,-0.246702 1.4211805,0.277917 2.1484375,0.335938 0.621051,-0.0088 1.351954,-0.399393 1.818402,-0.396552 0.536698,0.02254 1.051376,0.234242 1.498081,0.382763 0.357762,0.07663 0.717881,0.02104 0.970698,-0.07223 0.717277,-0.264623 1.521787,-0.441266 2.220704,-0.05859 0.695237,0.311815 1.440839,0.06801 2.103515,-0.191407 0.229629,-0.07509 0.450663,-0.07784 0.667969,-0.04492 v -1.314453 c -0.295925,-0.04096 -0.594072,-0.02791 -0.892578,0.09961 -0.681973,0.357628 -1.511565,0.358833 -2.19336,0 -0.726431,-0.310175 -1.451915,0.04817 -2.144531,0.246093 -0.116646,0.02861 -0.230986,0.0388 -0.34375,0.03711 v -0.0078 c -0.304634,0.02335 -0.610512,-0.122847 -0.878909,-0.189453 -1.061726,-0.598921 -2.285933,0.148857 -3.056646,0.16011 -0.510364,-0.111475 -1.41674,-0.556159 -2.1425779,-0.246093 -0.6819724,0.357628 -1.5115649,0.358833 -2.1933593,0 C 6.410287,17.389044 5.6848033,17.747388 4.9921875,17.945312 4.2276707,18.132803 3.558755,17.569011 2.8183594,17.572266 Z"
|
||||
transform="matrix(0.99997,0,0,0.99997,-0.07491,0)"
|
||||
sodipodi:nodetypes="sccccccccccsccccccccccccccs" /><path
|
||||
id="path2-1-1"
|
||||
style="fill:#ffffff;stroke-width:0.150857"
|
||||
d="m 10.229667,15.445213 c -0.2340521,-0.01177 -0.6643302,0.02851 -0.8995889,0.129006 -0.6819724,0.357628 -1.5115649,0.358834 -2.1933593,0 C 6.410287,15.264044 5.6848033,15.622386 4.9921875,15.820312 4.1184541,16.034604 3.3697256,15.266655 2.4960938,15.486328 1.9214135,15.666657 1.0605469,15.890625 1.0605469,15.890625 v 1.28125 c 0.7432175,0.01415 1.3912167,-0.563498 2.1523437,-0.361328 1.0837672,0.428406 1.2955041,0.454006 2.0175782,0.273437 0.6943098,-0.320069 1.5217861,-0.441275 2.2207031,-0.05859 0.3325161,0.149133 0.6767832,0.169105 1.0175781,0.123047 1.1763193,-0.377141 1.78456,-0.510947 3.130219,0.05666 0.64547,0.05184 1.34431,-0.445591 2.223297,-0.423842 0.264657,-0.01332 1.092167,0.246652 1.478515,0.365234 h 0.002 c 0.560757,0.08029 1.135035,-0.115511 1.658204,-0.320312 0.754443,-0.246704 1.42118,0.277917 2.148437,0.335937 0.679991,0.06611 1.277834,-0.402757 1.941406,-0.40039 v -1.3125 c -0.0096,3.1e-4 -0.01967,-5.36e-4 -0.0293,0 -0.739183,-0.01326 -1.383132,0.559654 -2.140625,0.363281 -0.69207,-0.197542 -1.41674,-0.556158 -2.142578,-0.246094 -1.655465,0.798879 -2.131536,-0.136064 -3.123047,-0.109375 -0.566651,-0.01017 -1.078155,0.324314 -1.626953,0.392578 -0.768304,0.02005 -1.124822,-0.242268 -1.758614,-0.404396 z"
|
||||
transform="matrix(0.99997,0,0,0.99997,-0.07491,0)"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccc" /><path
|
||||
id="path851"
|
||||
style="fill:#ffffff;stroke-width:0.849248"
|
||||
d="m 11.681761,12.380821 c 0.04001,0.858093 -1.022037,1.463089 -1.7399012,0.992415 -0.759078,-0.4024 -0.73974,-1.624431 0.03148,-2.002787 0.7401222,-0.430195 1.7286822,0.151027 1.7084202,1.010372 z" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.860781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.355712,15.036148 3.6383028,-2.22847 -1.842207,-1.95125 3.722552,-1.9372846 c 0.680734,-0.2722312 1.1638102,0.4017839 0.797146,0.8475309 l -2.609068,1.3782717 4.4254312,4.254431 c -0.969784,-0.283917 -1.159653,-0.733088 -1.9352852,-0.477299 -2.04824,0.675474 -1.613096,0.0034 -3.081487,0.01516 -1.659598,0.01323 -1.380005,0.838666 -3.1153848,0.09891 z"
|
||||
id="path2791"
|
||||
sodipodi:nodetypes="cccccccssc" /><path
|
||||
id="rect4320"
|
||||
style="fill:#ffffff;stroke-width:1.00154;stroke-linecap:square;paint-order:markers fill stroke"
|
||||
d="m 21.108524,13.306347 c -0.260342,0.07218 -0.504886,-0.363252 -0.886457,-0.333843 -0.682913,0.05263 -0.688525,0.273741 -1.170401,0.333103 -0.56376,-0.01179 -0.705141,-0.39106 -1.323093,-0.385461 -0.797244,0.05005 -0.816589,0.344784 -1.506419,0.327831 -0.635156,-0.006 -0.584758,-0.400757 -1.137589,-0.37363 -0.445887,0 -0.423469,0.363096 -1.030167,0.33682 0.804394,-1.992062 7.313411,-2.472785 7.054126,0.09518 z"
|
||||
sodipodi:nodetypes="cscccccc" /><path
|
||||
id="rect4573"
|
||||
style="fill:#ffffff;stroke-width:1.00154;stroke-linecap:square;paint-order:markers fill stroke"
|
||||
d="m 15.952342,6.3416747 0.804782,0.00553 c 0.791609,0.9558102 1.568049,2.3417023 2.288114,5.3258424 l -1.791332,0.368162 c 0.0085,-1.595974 -0.327662,-3.5171502 -1.301564,-5.6995303 z"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
id="rect5178"
|
||||
style="fill:#ffffff;stroke-width:1.00154;stroke-linecap:square;paint-order:markers fill stroke"
|
||||
d="M 15.714534,5.7993213 16.460602,5.694421 C 17.892566,5.5299173 18.930384,6.2178215 19.826278,7.1622728 18.315795,6.5191329 17.758674,6.2722082 16.194793,6.4666796 14.820535,6.8297473 13.804944,7.2159692 13.25106,7.9257197 13.396619,7.3313592 13.938011,6.4826988 15.714534,5.7993213 Z"
|
||||
sodipodi:nodetypes="cccccc" /><path
|
||||
id="rect5178-8"
|
||||
style="fill:#ffffff;stroke-width:0.961457;stroke-linecap:square;paint-order:markers fill stroke"
|
||||
d="m 16.165622,5.4722594 c -0.08973,0.080465 -0.17851,0.1681115 -0.26532,0.2648771 l -0.0964,0.1131325 0.390891,0.6164106 C 17.150623,5.4034465 17.686156,5.2561052 19.060064,4.8593949 18.032481,4.6520987 17.033002,4.6944293 16.165622,5.4722594 Z" /><path
|
||||
id="rect5178-5"
|
||||
style="fill:#ffffff;stroke-width:0.928756;stroke-linecap:square;paint-order:markers fill stroke"
|
||||
d="M 16.314771,5.73079 C 16.294181,5.717361 16.273991,5.703711 16.252891,5.690635 L 15.674258,5.3521611 c -1.591186,-0.4463567 -2.388606,-0.054483 -2.781886,0.3520817 0.738652,-0.2696642 1.645743,-0.011014 2.795776,0.4705547 0.09419,0.057052 0.180726,0.1118664 0.264194,0.1668772 z" /></svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,469 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
sodipodi:docname="ic_activity_workout.01.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 5.8208333 5.8208333"
|
||||
height="22"
|
||||
width="22"
|
||||
inkscape:export-filename="/home/peter/StudioProjects/OpenTracks/drawable-svg/ic_activity_workout.01.png"
|
||||
inkscape:export-xdpi="1309.09"
|
||||
inkscape:export-ydpi="1309.09"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect3162"
|
||||
effect="spiro" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect3149"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect2514"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
radius="0"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect950"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect946"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect918"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect912"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect894"
|
||||
effect="fillet_chamfer" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="1047"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="false"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox="true"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="10.326952"
|
||||
inkscape:cx="15.790447"
|
||||
inkscape:zoom="31.664715"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="1"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#232629"
|
||||
id="base"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:snap-grids="false">
|
||||
<inkscape:grid
|
||||
dotted="true"
|
||||
empspacing="22"
|
||||
id="grid833"
|
||||
type="xygrid" />
|
||||
<inkscape:grid
|
||||
originy="0.26458333"
|
||||
originx="0.26458333"
|
||||
spacingx="1.0583333"
|
||||
spacingy="1.0583333"
|
||||
empspacing="1"
|
||||
id="grid835"
|
||||
type="xygrid" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide887"
|
||||
orientation="0.96592583,0.25881905"
|
||||
position="4.195,4.2333333" />
|
||||
<sodipodi:guide
|
||||
id="guide900"
|
||||
orientation="0,-1"
|
||||
position="0.26458333,1.9843751" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<g
|
||||
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)"
|
||||
id="g954">
|
||||
<rect
|
||||
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect919"
|
||||
width="68.791664"
|
||||
height="79.375"
|
||||
x="-357.1875"
|
||||
y="-7.9375" />
|
||||
<rect
|
||||
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect851"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-354.54169"
|
||||
y="-5.2916665" />
|
||||
<rect
|
||||
y="-5.2916665"
|
||||
x="-343.95834"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect853"
|
||||
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect855"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-333.375"
|
||||
y="-5.2916665" />
|
||||
<rect
|
||||
y="-5.2916665"
|
||||
x="-322.79169"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect857"
|
||||
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect859"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-312.20834"
|
||||
y="-5.2916665" />
|
||||
<rect
|
||||
y="5.291667"
|
||||
x="-354.54169"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect861"
|
||||
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect863"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-343.95834"
|
||||
y="5.291667" />
|
||||
<rect
|
||||
y="5.291667"
|
||||
x="-333.375"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect865"
|
||||
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect867"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-322.79169"
|
||||
y="5.291667" />
|
||||
<rect
|
||||
y="5.291667"
|
||||
x="-312.20834"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect869"
|
||||
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
y="21.166666"
|
||||
x="-354.54169"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect871"
|
||||
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect873"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-343.95834"
|
||||
y="21.166666" />
|
||||
<rect
|
||||
y="21.166666"
|
||||
x="-333.375"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect875"
|
||||
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect877"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-322.79169"
|
||||
y="21.166666" />
|
||||
<rect
|
||||
y="21.166666"
|
||||
x="-312.20834"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect879"
|
||||
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect881"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-354.54169"
|
||||
y="31.75" />
|
||||
<rect
|
||||
y="31.75"
|
||||
x="-343.95834"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect883"
|
||||
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect885"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-333.375"
|
||||
y="31.75" />
|
||||
<rect
|
||||
y="31.75"
|
||||
x="-322.79169"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect887"
|
||||
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect889"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-312.20834"
|
||||
y="31.75" />
|
||||
<rect
|
||||
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect891"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-301.625"
|
||||
y="21.166666" />
|
||||
<rect
|
||||
y="31.75"
|
||||
x="-301.625"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect893"
|
||||
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect895"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-354.54166"
|
||||
y="47.625" />
|
||||
<rect
|
||||
y="47.625"
|
||||
x="-343.95831"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect897"
|
||||
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect899"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-333.37497"
|
||||
y="47.625" />
|
||||
<rect
|
||||
y="47.625"
|
||||
x="-322.79166"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect901"
|
||||
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect903"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-312.20831"
|
||||
y="47.625" />
|
||||
<rect
|
||||
y="58.208336"
|
||||
x="-354.54166"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect905"
|
||||
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect907"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-343.95831"
|
||||
y="58.208336" />
|
||||
<rect
|
||||
y="58.208336"
|
||||
x="-333.37497"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect909"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
<rect
|
||||
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||
id="rect911"
|
||||
width="10.583333"
|
||||
height="10.583333"
|
||||
x="-322.79166"
|
||||
y="58.208336" />
|
||||
<rect
|
||||
y="58.208336"
|
||||
x="-312.20831"
|
||||
height="10.583333"
|
||||
width="10.583333"
|
||||
id="rect913"
|
||||
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||
</g>
|
||||
<path
|
||||
id="path17"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.730205;stroke-opacity:1"
|
||||
d="m 12.521484,5.0957031 c -0.795342,0 -1.447265,0.6634257 -1.447265,1.4746094 0,0.811183 0.651923,1.4746094 1.447265,1.4746094 0.795342,0 1.445313,-0.663426 1.445313,-1.4746094 0,-0.8111837 -0.649971,-1.4746094 -1.445313,-1.4746094 z m 5.697266,2.2871094 c -1.005293,9.03e-5 -1.820222,0.8150191 -1.820312,1.8203125 0.001,0.2581612 0.02839,0.6283924 0.303378,0.93547 L 15.712713,10.886411 13.488221,8.9477292 10.263672,8.5957031 7.5078513,10.338038 5.7695312,12.576172 c -0.3754732,0.661347 0.1816517,1.249724 0.7773438,0.966797 l 1.7128929,-2.075723 1.9003931,-1.220112 -0.5761766,4.110288 -2.5878906,5.929687 1.484375,-0.0293 c 0.4801983,-0.907334 2.5996092,-5.441406 2.5996092,-5.441406 l 2.054688,0.941406 v 4.423829 h 1.445312 v -5.53125 L 12.75,13.876953 l 0.650391,-3.398437 2.285156,2.103515 1.747452,-1.734477 c 0.31097,0.238627 0.542791,0.17537 0.785751,0.175884 1.005294,-9e-5 1.820222,-0.815019 1.820312,-1.820313 -9e-5,-1.0052934 -0.815019,-1.8202222 -1.820312,-1.8203125 z m 0.0059,1.3535156 c 0.274357,9.402e-4 0.496232,0.2236881 0.496094,0.4980469 1.38e-4,0.2743588 -0.221737,0.4971067 -0.496094,0.4980469 C 17.94953,9.7325585 17.726466,9.5094953 17.726603,9.234375 17.726466,8.9592547 17.94953,8.7361915 18.22465,8.7363281 Z"
|
||||
transform="scale(0.26458333)"
|
||||
sodipodi:nodetypes="sssssccccccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
id="path9403"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers fill stroke"
|
||||
d="M 1.0131059,0.53415337 C 0.73729957,0.54114168 0.64785326,0.76400686 0.64775351,1.04575 c 0.001003,0.049428 0.006811,0.095893 0.0170532,0.1405599 H 1.1996578 L 1.3303992,1.4400412 1.6714636,0.85558076 1.9071081,1.1801088 2.1840938,1.1826926 C 2.1968962,1.1377378 2.2034247,1.0922518 2.2032141,1.04575 2.2031128,0.75953474 2.1266608,0.53477144 1.8404456,0.53467013 1.540136,0.53761574 1.5284374,0.67900891 1.4327185,0.76204643 1.3421819,0.69057893 1.2614053,0.53055962 1.0265417,0.53415337 c -0.00447,1.59e-6 -0.00906,-1.1091e-4 -0.013436,0 z M 2.1840938,1.1826926 c -0.016723,0.058723 -0.044375,0.116296 -0.079582,0.173116 l 0.4873088,-0.00258 V 1.1863099 Z M 2.1045121,1.3558086 1.7965206,1.3573589 1.6740474,1.16874 1.3009436,1.7361472 1.0828691,1.3532248 H 0.7273352 C 0.8490025,1.5865985 1.0981629,1.7800149 1.3903438,2.0580913 1.669028,1.8167708 1.9577231,1.5927143 2.1045121,1.3558086 Z M 0.7273352,1.3532248 C 0.69965645,1.3001334 0.67827264,1.2450376 0.66480673,1.1863099 H 0.25914674 v 0.1669149 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,11 @@
|
||||
v3.25.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- GPS is now optional incl. GPS disabled warning
|
||||
- PublicAPI: other applications can now receive recorded data if they start a recording (implemented for Gadgetbridge)
|
||||
- New activities: swimming, swimming open, and workout
|
||||
- Removed share pic functionality
|
||||
|
||||
Bugfix:
|
||||
- UI: speed/elevation where jumping between 0.0 and the actual value
|
||||
- Tracks with emojis can be exported
|
||||
@@ -1,11 +1,22 @@
|
||||
OpenTracks on spordi jälgimise rakendus, mis austab täielikult teie privaatsust.
|
||||
Spordijälgija, mis austab teie privaatsust.
|
||||
|
||||
Omadused:
|
||||
* Spordi jälgimine: jälgige oma spordi- ja vabaõhutegevust.
|
||||
* Fotod ja markerid: märkige jälgimise ajal huvipakkuvad kohad.
|
||||
* Kõrguse suurenemine ja vähenemine: baromeetrilise anduri abil
|
||||
* Kõrgus näitab EGM2008 (üle keskmise merepinna); eksporditakse WGS84 kujul.
|
||||
* Häälteated
|
||||
* Toetab Bluetooth LE andureid: südame löögisagedus, kiirus ja distants (jalgrattasõit), takistus (jalgrattasõit) ja jõumõõtja (jalgrattasõit).
|
||||
* Andmete eksport: eksportida rajad kas KMZ (sh fotod), KML või GPX kujul.
|
||||
* Interneti-ühendus puudub: Internetti ei kasutata
|
||||
Sport ja välitegevused garanteerivad õnnelikkuse, vilumuse ja kindlustunde.
|
||||
|
||||
Väärtusta oma tervist, jälgides on treeninguid.
|
||||
Salvestab kui lähed jooksma või jalutama ja annab teile jalgrattasõiduks suurema ekraani.
|
||||
Märgi huvitavad asukohad oma teel, koos piltidega.
|
||||
Hoia salvestatud statistika analüüsimiseks.
|
||||
Jaga ainult neid andmeid, mida soovid, et teised näeksid.
|
||||
|
||||
* Häälteated.
|
||||
* Toetab Bluetooth LE andureid: pulss, kiirus, distants (jalgrattasõit), rütm (jalgrattasõit) ja jõumõõtja (jalgrattasõit).
|
||||
* Kõrguse tõus ja langus: baromeetrilise anduri abil.
|
||||
* Kõrgus näitab EGM2008 (üle keskmise merepinna); eksporditakse WGS84-na.
|
||||
* Ekspordit teekond kas KMZ- (koos fotodega), KML- või GPX-vormingus.
|
||||
* Ei vaja internetile ligipääsu ega lisalubasid.
|
||||
* Tume ja hele teema, austab süsteemi sätteid.
|
||||
* Reklaamivaba.
|
||||
|
||||
Vabavara / Avatud Lähtekoodiga Tarkvara
|
||||
mis tähendab, et võite lähtekoodi kasutada, uurida, muuta ja jagada.
|
||||
Litsentsitud Apache 2.0
|
||||
|
||||
@@ -1 +1 @@
|
||||
Spordijälgija, mis austab täielikult teie privaatsust.
|
||||
Spordijälgija, mis austab teie privaatsust.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#Wed Jul 28 23:10:13 CEST 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<issue id="ExtraTranslation" severity="error" />
|
||||
<issue id="GifUsage" severity="error" />
|
||||
<issue id="InconsistentArrays" severity="error" />
|
||||
<issue id="MissingQuantity"
|
||||
severity="warning" />
|
||||
<issue id="MissingTranslation" severity="warning" />
|
||||
<issue id="Proguard" severity="warning" />
|
||||
<issue id="ScrollViewCount" severity="error" />
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ public class ExportImportTest {
|
||||
tmpFile = File.createTempFile("test", "test", context.getFilesDir());
|
||||
tmpFileUri = Uri.fromFile(tmpFile);
|
||||
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(10), Distance.of(200), true);
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(200), true);
|
||||
|
||||
TrackRecordingServiceTestUtils.resetService(mServiceRule, context);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class GPXImportTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(10), Distance.of(200), true);
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(200), true);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -42,7 +42,7 @@ public class KMLImportTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(10), Distance.of(200), true);
|
||||
trackImporter = new TrackImporter(context, contentProviderUtils, Distance.of(200), true);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
+8
-8
@@ -123,7 +123,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue());
|
||||
|
||||
// when
|
||||
service.tryStartGps();
|
||||
service.tryStartSensors();
|
||||
Thread.sleep(1000);
|
||||
|
||||
// then
|
||||
@@ -132,7 +132,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
|
||||
// when
|
||||
service.stopGps(true);
|
||||
service.stopSensorsAndShutdown();
|
||||
Thread.sleep(1000);
|
||||
|
||||
// then
|
||||
@@ -153,7 +153,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
|
||||
// then
|
||||
assertTrue(service.isRecording());
|
||||
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
|
||||
@@ -165,7 +165,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
// then
|
||||
assertTrue(service.isRecording());
|
||||
assertTrue(service.isPaused());
|
||||
assertEquals(new TrackRecordingService.RecordingStatus(trackId, true), service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(new RecordingStatus(trackId, true), service.getRecordingStatusObservable().getValue());
|
||||
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue()); //TODO The GPS is kept in pause, right? Might be a bug.
|
||||
|
||||
@@ -177,7 +177,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
// then
|
||||
assertTrue(service.isRecording());
|
||||
assertFalse(service.isPaused());
|
||||
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
|
||||
@@ -201,7 +201,7 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
// then
|
||||
assertTrue(service.isRecording());
|
||||
assertFalse(service.isPaused());
|
||||
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening
|
||||
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
@@ -252,13 +252,13 @@ public class TrackRecordingServiceTestStateMachine {
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
|
||||
// when
|
||||
service.stopGps(false); //TODO Should be ignored as service is recording
|
||||
service.stopSensors(); //TODO Should be ignored as service is recording
|
||||
Thread.sleep(1000);
|
||||
|
||||
// then
|
||||
assertTrue(service.isRecording());
|
||||
assertFalse(service.isPaused());
|
||||
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
|
||||
Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening
|
||||
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ public class TrackRecordingServiceTestUtils {
|
||||
service.getTrackPointCreator().setRemoteSensorManager(new BluetoothRemoteSensorManager(context, service.getTrackPointCreator()));
|
||||
service.getTrackPointCreator().setClock(Clock.systemUTC());
|
||||
service.endCurrentTrack();
|
||||
service.sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null);
|
||||
}
|
||||
|
||||
static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) {
|
||||
|
||||
+4
-4
@@ -60,11 +60,11 @@ public class VoiceAnnouncementManagerTest {
|
||||
// when
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setTotalDistance(Distance.ofKilometer(13));
|
||||
voiceAnnouncementManager.restore(statistics);
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
assertEquals(Distance.of(15000), voiceAnnouncementManager.getNextTotalDistance());
|
||||
|
||||
statistics.setTotalDistance(Distance.of(15100));
|
||||
voiceAnnouncementManager.restore(statistics);
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
assertEquals(Distance.of(20000), voiceAnnouncementManager.getNextTotalDistance());
|
||||
}
|
||||
|
||||
@@ -80,11 +80,11 @@ public class VoiceAnnouncementManagerTest {
|
||||
// when
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setTotalTime(Duration.ofSeconds(91));
|
||||
voiceAnnouncementManager.restore(statistics);
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
assertEquals(Duration.ofSeconds(95), voiceAnnouncementManager.getNextTotalTime());
|
||||
|
||||
statistics.setTotalTime(Duration.ofSeconds(95));
|
||||
voiceAnnouncementManager.restore(statistics);
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
assertEquals(Duration.ofSeconds(100), voiceAnnouncementManager.getNextTotalTime());
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -62,7 +62,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(trackPointIterator.getCount(), numberOfPoints);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(trackPointIterator.getCount(), numberOfPoints);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(trackPointIterator.getCount(), numberOfPoints);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(trackPointIterator.getCount(), numberOfPoints);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackStatisticsUpdaterTest {
|
||||
|
||||
private static final Distance GPS_DISTANCE = Distance.of(50);
|
||||
|
||||
@Test
|
||||
public void empty() {
|
||||
// when
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ public class IntervalStatisticsTest {
|
||||
}
|
||||
|
||||
private void whenAndThen(Pair<Track.Id, TrackStatistics> trackWithStats, int numberOfPoints, float distanceInterval) {
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(distanceInterval), Distance.of(0));
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(distanceInterval));
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics trackStatistics = trackWithStats.second;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package de.dennisguse.opentracks.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
@@ -22,8 +24,6 @@ import org.junit.runners.JUnit4;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link FileUtils}.
|
||||
*
|
||||
@@ -101,6 +101,13 @@ public class FileUtilsTest {
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitizeFileName_emoji() {
|
||||
String name = "\uD83C\uDF5B-Food";
|
||||
String expected = "_-Food";
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#truncateFileName(File, String, String)}.
|
||||
* Verifies the a long file name is truncated.
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||
@@ -39,7 +39,7 @@ public class StatisticDataBuilderTest extends TestCase {
|
||||
private TrackStatistics trackStatisticsMock;
|
||||
|
||||
@Mock
|
||||
private TrackRecordingService.RecordingData recordingDataMock;
|
||||
private RecordingData recordingDataMock;
|
||||
|
||||
@Mock
|
||||
private SensorStatistics sensorStatisticsMock;
|
||||
|
||||
@@ -33,6 +33,8 @@ import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.ui.util.ActivityUtils;
|
||||
@@ -57,8 +59,8 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
||||
private TransitionDrawable transition;
|
||||
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
private TrackRecordingService.RecordingStatus recordingStatus;
|
||||
private TrackRecordingService.RecordingData recordingData;
|
||||
private RecordingStatus recordingStatus;
|
||||
private RecordingData recordingData;
|
||||
|
||||
private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> {
|
||||
service.getRecordingStatusObservable()
|
||||
@@ -237,7 +239,7 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
||||
void recordStop();
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
|
||||
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
|
||||
@@ -254,7 +256,7 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
|
||||
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
private void onTotalTimeChanged(TrackRecordingService.RecordingData recordingData) {
|
||||
private void onTotalTimeChanged(RecordingData recordingData) {
|
||||
this.recordingData = recordingData;
|
||||
|
||||
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(this.recordingData.getTrackStatistics().getTotalTime()));
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||
import android.location.LocationManager;
|
||||
@@ -33,15 +31,11 @@ import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
@@ -58,6 +52,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.databinding.TrackListBinding;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||
@@ -95,7 +90,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
private boolean metricUnits = true;
|
||||
|
||||
private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT;
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
|
||||
// Callback when an item is selected in the contextual action mode
|
||||
private final ActivityUtils.ContextualActionModeCallback contextualActionModeCallback = new ActivityUtils.ContextualActionModeCallback() {
|
||||
@@ -144,7 +139,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
}
|
||||
|
||||
//TODO Not cool to do this in a callback that might be called more than once!
|
||||
service.tryStartGps();
|
||||
service.tryStartSensors();
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -212,8 +207,6 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
ActivityUtils.configureListViewContextualMenu(viewBinding.trackList, contextualActionModeCallback);
|
||||
|
||||
loadData(getIntent());
|
||||
|
||||
requestGPSPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -300,7 +293,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
} else {
|
||||
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||
if (trackRecordingService != null) {
|
||||
trackRecordingService.stopGpsAndShutdown(); //TODO Handle this in TrackRecordingServiceConnection
|
||||
trackRecordingService.stopSensorsAndShutdown(); //TODO Handle this in TrackRecordingServiceConnection
|
||||
}
|
||||
trackRecordingServiceConnection.unbindAndStop(this);
|
||||
}
|
||||
@@ -391,26 +384,6 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
return recordingStatus.getTrackId();
|
||||
}
|
||||
|
||||
private void requestGPSPermissions() {
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
||||
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
|
||||
Boolean coarseLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false);
|
||||
if (fineLocationGranted == null || !fineLocationGranted
|
||||
|| coarseLocationGranted == null || !coarseLocationGranted) {
|
||||
Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
);
|
||||
String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
|
||||
locationPermissionRequest.launch(permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the menu items with the icon specified.
|
||||
*
|
||||
@@ -569,7 +542,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
||||
updateGpsMenuItem(true, recordingStatus.isRecording());
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
@@ -40,10 +39,10 @@ import de.dennisguse.opentracks.data.TrackDataHub;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.databinding.TrackRecordedBinding;
|
||||
import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackDeleteService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||
import de.dennisguse.opentracks.share.ShareUtils;
|
||||
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
|
||||
@@ -76,22 +75,13 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
private TrackRecordedBinding viewBinding;
|
||||
|
||||
private Track.Id trackId;
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
|
||||
private final TrackRecordingServiceConnection.Callback bindCallback = service -> service.getRecordingStatusObservable()
|
||||
.observe(TrackRecordedActivity.this, this::onRecordingStatusChanged);
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.recording_distance_interval_key, key)) {
|
||||
trackDataHub.setRecordingDistanceInterval(PreferencesUtils.getRecordingDistanceInterval());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -119,8 +109,6 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
|
||||
trackDataHub.start();
|
||||
}
|
||||
|
||||
@@ -143,7 +131,6 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
super.onStop();
|
||||
trackRecordingServiceConnection.unbind(this);
|
||||
trackDataHub.stop();
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,7 +300,7 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -11,12 +11,16 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import java.util.List;
|
||||
@@ -29,8 +33,10 @@ import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.databinding.TrackRecordingBinding;
|
||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||
import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalsFragment;
|
||||
@@ -38,6 +44,7 @@ import de.dennisguse.opentracks.ui.markers.MarkerEditActivity;
|
||||
import de.dennisguse.opentracks.ui.markers.MarkerListActivity;
|
||||
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
import de.dennisguse.opentracks.util.PermissionUtils;
|
||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||
import de.dennisguse.opentracks.util.TrackUtils;
|
||||
|
||||
@@ -57,6 +64,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
|
||||
private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key";
|
||||
|
||||
private Snackbar snackbar;
|
||||
|
||||
// The following are setFrequency in onCreate
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
@@ -68,50 +77,43 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
@Deprecated
|
||||
private Track.Id trackId;
|
||||
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
|
||||
private final TrackRecordingServiceConnection.Callback bindChangedCallback = new TrackRecordingServiceConnection.Callback() {
|
||||
@Override
|
||||
public void onConnected(TrackRecordingService service) {
|
||||
private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> {
|
||||
service.getRecordingStatusObservable()
|
||||
.observe(TrackRecordingActivity.this, this::onRecordingStatusChanged);
|
||||
|
||||
service.getRecordingStatusObservable()
|
||||
.observe(TrackRecordingActivity.this, status -> onRecordingStatusChanged(status));
|
||||
service.getGpsStatusObservable()
|
||||
.observe(TrackRecordingActivity.this, this::onGpsStatusChanged);
|
||||
|
||||
if (!service.isRecording()) {
|
||||
if (trackId == null) {
|
||||
// trackId isn't initialized -> leads a new recording.
|
||||
trackId = service.startNewTrack();
|
||||
} else {
|
||||
// trackId is initialized -> resumes the track.
|
||||
service.resumeTrack(trackId);
|
||||
}
|
||||
|
||||
// A recording track is on.
|
||||
trackDataHub.loadTrack(trackId);
|
||||
trackDataHub.setRecordingStatus(recordingStatus);
|
||||
if (!service.isRecording()) {
|
||||
if (trackId == null) {
|
||||
// trackId isn't initialized -> leads a new recording.
|
||||
trackId = service.startNewTrack();
|
||||
} else {
|
||||
// trackId is initialized -> resumes the track.
|
||||
service.resumeTrack(trackId);
|
||||
}
|
||||
|
||||
// A recording track is on.
|
||||
trackDataHub.loadTrack(trackId);
|
||||
trackDataHub.setRecordingStatus(recordingStatus);
|
||||
}
|
||||
};
|
||||
|
||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.stats_show_on_lockscreen_while_recording_key, key)) {
|
||||
setLockscreenPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.stats_keep_screen_on_while_recording_key, key)) {
|
||||
setScreenOnPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.stats_fullscreen_while_recording_key, key)) {
|
||||
setFullscreenPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.recording_distance_interval_key, key)) {
|
||||
trackDataHub.setRecordingDistanceInterval(PreferencesUtils.getRecordingDistanceInterval());
|
||||
}
|
||||
if (key == null) return;
|
||||
|
||||
runOnUiThread(TrackRecordingActivity.this::invalidateOptionsMenu);
|
||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
||||
if (PreferencesUtils.isKey(R.string.stats_show_on_lockscreen_while_recording_key, key)) {
|
||||
setLockscreenPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.stats_keep_screen_on_while_recording_key, key)) {
|
||||
setScreenOnPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.stats_fullscreen_while_recording_key, key)) {
|
||||
setFullscreenPolicy();
|
||||
}
|
||||
if (key == null) return;
|
||||
|
||||
runOnUiThread(TrackRecordingActivity.this::invalidateOptionsMenu); //TODO Should not be necessary
|
||||
};
|
||||
|
||||
private MenuItem insertMarkerMenuItem;
|
||||
@@ -144,6 +146,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
if (savedInstanceState != null) {
|
||||
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
||||
}
|
||||
|
||||
requestGPSPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -320,10 +324,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
setTitle(getString(isPaused ? R.string.generic_paused : R.string.generic_recording));
|
||||
}
|
||||
|
||||
public void chooseActivityType(String category) {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChooseActivityTypeDone(String iconValue) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
@@ -398,7 +398,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
}
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
|
||||
trackDataHub.setRecordingStatus(recordingStatus);
|
||||
@@ -406,4 +406,38 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
setLockscreenPolicy();
|
||||
setScreenOnPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
private void requestGPSPermissions() {
|
||||
if (PermissionUtils.hasGPSPermission(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
||||
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
|
||||
Boolean coarseLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false);
|
||||
if (fineLocationGranted == null || !fineLocationGranted
|
||||
|| coarseLocationGranted == null || !coarseLocationGranted) {
|
||||
Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
);
|
||||
String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
|
||||
locationPermissionRequest.launch(permissions);
|
||||
}
|
||||
|
||||
private void onGpsStatusChanged(GpsStatusValue gpsStatusValue) {
|
||||
if (gpsStatusValue.isGpsStarted() && snackbar != null && snackbar.isShown()) {
|
||||
snackbar.dismiss();
|
||||
return;
|
||||
}
|
||||
if (gpsStatusValue != GpsStatusValue.GPS_DISABLED) {
|
||||
return;
|
||||
}
|
||||
snackbar = Snackbar
|
||||
.make(viewBinding.trackRecordingCoordinatorLayout,
|
||||
getString(R.string.gps_recording_status, getString(gpsStatusValue.message), getString(R.string.gps_recording_without_signal)),
|
||||
Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(getString(R.string.generic_dismiss), v -> {});
|
||||
snackbar.show();
|
||||
}
|
||||
}
|
||||
@@ -66,8 +66,6 @@ public class ShareContentProvider extends CustomContentProvider {
|
||||
|
||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA.getName() + "/*/*", URI_KMZ_WITH_TRACKDETAIL_AND_SENSORDATA);
|
||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getName() + "/*/*", URI_KMZ_WITH_TRACKDETAIL_SENSORDATA_AND_PICTURES);
|
||||
|
||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.SHARE_PICTURE_PNG.getName() + "/*/*", URI_SHARE_PICTURE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +94,7 @@ public class ShareContentProvider extends CustomContentProvider {
|
||||
Uri uri = Uri.parse(TracksColumns.CONTENT_URI + "/" + trackFileFormat.getName() + "/" + trackIdBuilder + "/" + Uri.encode(trackName) + "." + trackFileFormat.getExtension());
|
||||
String mime = getTypeMime(uri);
|
||||
|
||||
Log.d(TAG, "Created uri " + uri.toString() + " with MIME " + mime);
|
||||
Log.d(TAG, "Created uri " + uri + " with MIME " + mime);
|
||||
|
||||
return new Pair<>(uri, mime);
|
||||
}
|
||||
@@ -148,9 +146,6 @@ public class ShareContentProvider extends CustomContentProvider {
|
||||
case URI_KMZ_WITH_TRACKDETAIL_SENSORDATA_AND_PICTURES:
|
||||
return TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES;
|
||||
|
||||
case URI_SHARE_PICTURE:
|
||||
return TrackFileFormat.SHARE_PICTURE_PNG;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Could not derive TrackFileFormat from Uri " + uri);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
@@ -41,6 +40,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
@@ -84,9 +84,7 @@ public class TrackDataHub {
|
||||
|
||||
private Track.Id selectedTrackId;
|
||||
|
||||
private Distance recordingDistanceInterval;
|
||||
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
|
||||
// Track points sampling state
|
||||
private int numLoadedPoints;
|
||||
@@ -410,14 +408,10 @@ public class TrackDataHub {
|
||||
return handlerThread != null;
|
||||
}
|
||||
|
||||
public void setRecordingStatus(TrackRecordingService.RecordingStatus recordingStatus) {
|
||||
public void setRecordingStatus(RecordingStatus recordingStatus) {
|
||||
this.recordingStatus = recordingStatus;
|
||||
}
|
||||
|
||||
public void setRecordingDistanceInterval(Distance recordingDistanceInterval) {
|
||||
this.recordingDistanceInterval = recordingDistanceInterval;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,20 +27,10 @@ import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class extends the standard Android location with extra information.
|
||||
* Sensor and/or location information for a specific point in time.
|
||||
* <p>
|
||||
* NOTE: default location will be latitude=0.0 and longitude=0.0.
|
||||
* For {@link TrackPoint}s with `type == null` this is not meaningful.
|
||||
* <p>
|
||||
* NOTE: For Locations provided by the GPS.
|
||||
* We are replacing the GPS-provided time using the system time.
|
||||
* Then we have the same timestamps for the user-driven events (aka start, pause, resume) and restore {@link de.dennisguse.opentracks.stats.TrackStatistics}.
|
||||
* Drawbacks:
|
||||
* * GPS-provided timestamp might be more precise (but also have GPS week rollover)
|
||||
* * System clock might be changed (and thus non-monotonic)
|
||||
* TODO: if these might be a problem, we need to store both timestamps.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* Time is created using the {@link de.dennisguse.opentracks.services.handlers.MonotonicClock}, because system time jump backwards.
|
||||
* GPS time is ignored as for non-GPS events, we could not create timestamps.
|
||||
*/
|
||||
public class TrackPoint {
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ import java.util.List;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.adapters.StatisticsAdapter;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
@@ -44,8 +44,9 @@ public class StatisticsRecordingFragment extends Fragment {
|
||||
}
|
||||
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
private TrackRecordingService.RecordingData recordingData = TrackRecordingService.NOT_RECORDING;
|
||||
private TrackPoint latestTrackPoint;
|
||||
|
||||
private RecordingData recordingData = TrackRecordingService.NOT_RECORDING;
|
||||
|
||||
private Layout layout;
|
||||
|
||||
private StatisticsRecordingBinding viewBinding;
|
||||
@@ -75,8 +76,10 @@ public class StatisticsRecordingFragment extends Fragment {
|
||||
}
|
||||
};
|
||||
|
||||
private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> service.getRecordingDataObservable()
|
||||
.observe(StatisticsRecordingFragment.this, this::onRecordingDataChanged);
|
||||
private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> {
|
||||
service.getRecordingDataObservable()
|
||||
.observe(StatisticsRecordingFragment.this, this::onRecordingDataChanged);
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -158,7 +161,7 @@ public class StatisticsRecordingFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private void onRecordingDataChanged(TrackRecordingService.RecordingData recordingData) {
|
||||
private void onRecordingDataChanged(RecordingData recordingData) {
|
||||
String oldCategory = this.recordingData.getTrackCategory();
|
||||
String newCategory = recordingData.getTrackCategory();
|
||||
this.recordingData = recordingData;
|
||||
@@ -167,11 +170,6 @@ public class StatisticsRecordingFragment extends Fragment {
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, getString(R.string.stats_rate_key));
|
||||
}
|
||||
|
||||
latestTrackPoint = recordingData.getLatestTrackPoint();
|
||||
if (latestTrackPoint != null && latestTrackPoint.hasLocation() && !latestTrackPoint.isRecent()) {
|
||||
latestTrackPoint = null;
|
||||
}
|
||||
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.dennisguse.opentracks.io.file;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -10,7 +9,6 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.io.file.exporter.GPXTrackExporter;
|
||||
import de.dennisguse.opentracks.io.file.exporter.KMLTrackExporter;
|
||||
import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter;
|
||||
import de.dennisguse.opentracks.io.file.exporter.SharePictureTrackExporter;
|
||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||
|
||||
/**
|
||||
@@ -102,22 +100,6 @@ public enum TrackFileFormat {
|
||||
public String getExtension() {
|
||||
return "gpx";
|
||||
}
|
||||
},
|
||||
|
||||
SHARE_PICTURE_PNG {
|
||||
@Override
|
||||
public TrackExporter createTrackExporter(Context context) {
|
||||
return new SharePictureTrackExporter(context, Bitmap.CompressFormat.PNG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return "image/png";
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return "png";
|
||||
}
|
||||
};
|
||||
|
||||
private static final String MIME_KMZ = "application/vnd.google-earth.kmz";
|
||||
|
||||
@@ -310,37 +310,31 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
|
||||
viewBinding.exportProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_dialog_success_24dp));
|
||||
viewBinding.exportProgressAlertMsg.setText(getString(R.string.generic_completed));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
if (resultData == null) {
|
||||
throw new RuntimeException(TAG + ": onReceiveResult resultData NULL");
|
||||
}
|
||||
|
||||
Track.Id trackId = resultData.getParcelable(ExportServiceResultReceiver.RESULT_EXTRA_TRACK_ID);
|
||||
public void onExportSuccess(Track.Id trackId) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
switch (resultCode) {
|
||||
case ExportServiceResultReceiver.RESULT_CODE_ERROR:
|
||||
trackExportErrorCount++;
|
||||
trackErrors.add(track.getName());
|
||||
break;
|
||||
case ExportServiceResultReceiver.RESULT_CODE_SUCCESS:
|
||||
if (ExportUtils.isExportFileExists(track.getUuid(), trackFileFormat.getExtension(), directoryFiles)) {
|
||||
trackExportOverwrittenCount++;
|
||||
} else {
|
||||
trackExportSuccessCount++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(TAG + ": export service result code invalid: " + resultCode);
|
||||
if (ExportUtils.isExportFileExists(track.getUuid(), trackFileFormat.getExtension(), directoryFiles)) {
|
||||
trackExportOverwrittenCount++;
|
||||
} else {
|
||||
trackExportSuccessCount++;
|
||||
}
|
||||
|
||||
onExportCompleted(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExportError(Track.Id trackId) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
trackExportErrorCount++;
|
||||
trackErrors.add(track.getName());
|
||||
|
||||
onExportCompleted(track);
|
||||
}
|
||||
|
||||
private void conflict(Track track) {
|
||||
PendingConflict newConflict = new PendingConflict(track);
|
||||
conflictsQueue.add(newConflict);
|
||||
|
||||
+16
-2
@@ -6,6 +6,8 @@ import android.os.ResultReceiver;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
|
||||
/**
|
||||
* Create a new ResultReceive to receive results.
|
||||
* Your {@link #onReceiveResult} method will be called from the thread running <var>handler</var> if given, or from an arbitrary thread if null.
|
||||
@@ -26,10 +28,22 @@ public class ExportServiceResultReceiver extends ResultReceiver {
|
||||
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
receiver.onReceiveResult(resultCode, resultData);
|
||||
Track.Id trackId = resultData.getParcelable(ExportServiceResultReceiver.RESULT_EXTRA_TRACK_ID);
|
||||
switch (resultCode) {
|
||||
case RESULT_CODE_SUCCESS:
|
||||
receiver.onExportSuccess(trackId);
|
||||
case RESULT_CODE_ERROR:
|
||||
receiver.onExportError(trackId);
|
||||
default:
|
||||
throw new RuntimeException("Unknown resultCode.");
|
||||
}
|
||||
}
|
||||
|
||||
public interface Receiver {
|
||||
void onReceiveResult(int resultCode, Bundle resultData);
|
||||
default void onExportSuccess(Track.Id trackId) {
|
||||
}
|
||||
|
||||
default void onExportError(Track.Id trackId) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
package de.dennisguse.opentracks.io.file.exporter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.databinding.TrackSharePictureBinding;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Create a share picture for a track.
|
||||
* Here a layout is inflated and converted to PNG.
|
||||
* <p>
|
||||
* TODO
|
||||
* If this classes is used with non-visual context (e.g., ApplicationContext), it may not work in the future.
|
||||
* API31 introduces `ncorrectContextUseViolation`, which may thrown during runtime.
|
||||
* This code was tested on API30.
|
||||
* Some more information: https://stackoverflow.com/questions/68539083/inflate-layout-from-applicationcontext-i-e-in-a-contentprovider/68567186#68567186
|
||||
* <p>
|
||||
* Future plan: draw directly on a view.
|
||||
*/
|
||||
public class SharePictureTrackExporter implements TrackExporter {
|
||||
|
||||
private static final String TAG = SharePictureTrackExporter.class.getSimpleName();
|
||||
|
||||
private final static int imageWidth = 1024;
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final Bitmap.CompressFormat compressFormat;
|
||||
|
||||
public SharePictureTrackExporter(Context context, Bitmap.CompressFormat compressFormat) {
|
||||
this.context = context;
|
||||
this.compressFormat = compressFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTrack(Track[] tracks, @NonNull OutputStream outputStream) {
|
||||
if (tracks.length > 1) {
|
||||
Log.e(TAG, "Not yet implemented.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeTrack(tracks[0], outputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTrack(Track track, @NonNull OutputStream outputStream) {
|
||||
int imageHeight = imageWidth / 4 * 3;
|
||||
|
||||
TrackSharePictureBinding viewBinding = TrackSharePictureBinding.inflate(LayoutInflater.from(context));
|
||||
viewBinding.sharePictureCategory.setText(track.getCategory());
|
||||
|
||||
boolean metricUnits = PreferencesUtils.isMetricUnits();
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
|
||||
viewBinding.sharePictureTotalTime.setText(StringUtils.formatElapsedTimeWithHour(track.getTrackStatistics().getTotalTime()));
|
||||
viewBinding.sharePictureTotalDistance.setText(StringUtils.formatDistance(context, track.getTrackStatistics().getTotalDistance(), metricUnits));
|
||||
viewBinding.sharePictureGain.setText(StringUtils.formatAltitudeChange(context, trackStatistics.getTotalAltitudeGain(), metricUnits));
|
||||
|
||||
// prepare rendering
|
||||
View view = viewBinding.getRoot();
|
||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(imageWidth, View.MeasureSpec.EXACTLY);
|
||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(imageHeight, View.MeasureSpec.EXACTLY);
|
||||
view.measure(widthSpec, heightSpec);
|
||||
view.layout(0, 0, imageWidth, imageHeight);
|
||||
|
||||
// draw
|
||||
Canvas canvas = new Canvas();
|
||||
Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
|
||||
canvas.setBitmap(bitmap);
|
||||
|
||||
view.draw(canvas);
|
||||
|
||||
// store
|
||||
return bitmap.compress(compressFormat, 100, outputStream);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class ImportService extends JobIntentService {
|
||||
Distance recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval();
|
||||
boolean preventReimport = PreferencesUtils.getPreventReimportTracks();
|
||||
|
||||
TrackImporter trackImporter = new TrackImporter(this, new ContentProviderUtils(this), recordingDistanceInterval, maxRecordingDistance, preventReimport);
|
||||
TrackImporter trackImporter = new TrackImporter(this, new ContentProviderUtils(this), maxRecordingDistance, preventReimport);
|
||||
|
||||
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
|
||||
trackIds.addAll(new XMLImporter(new GpxTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
|
||||
|
||||
@@ -51,7 +51,6 @@ public class TrackImporter {
|
||||
private final Context context;
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
|
||||
private final Distance recordingDistanceInterval;
|
||||
private final Distance maxRecordingDistance;
|
||||
private final boolean preventReimport;
|
||||
|
||||
@@ -62,10 +61,9 @@ public class TrackImporter {
|
||||
private final List<TrackPoint> trackPoints = new LinkedList<>();
|
||||
private final List<Marker> markers = new LinkedList<>();
|
||||
|
||||
public TrackImporter(Context context, ContentProviderUtils contentProviderUtils, Distance recordingDistanceInterval, Distance maxRecordingDistance, boolean preventReimport) {
|
||||
public TrackImporter(Context context, ContentProviderUtils contentProviderUtils, Distance maxRecordingDistance, boolean preventReimport) {
|
||||
this.context = context;
|
||||
this.contentProviderUtils = contentProviderUtils;
|
||||
this.recordingDistanceInterval = recordingDistanceInterval;
|
||||
this.maxRecordingDistance = maxRecordingDistance;
|
||||
this.preventReimport = preventReimport;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
package de.dennisguse.opentracks.publicapi;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||
|
||||
public class StartRecording extends AbstractAPIActivity {
|
||||
private static final String TAG = StartRecording.class.getSimpleName();
|
||||
|
||||
protected void execute(TrackRecordingService service) {
|
||||
service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
if ((trackId != null) && (PreferencesUtils.isPublicAPIDashboardEnabled())) {
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
if (bundle != null) {
|
||||
String targetPackage = bundle.getString("STATS_TARGET_PACKAGE", null);
|
||||
String targetClass = bundle.getString("STATS_TARGET_CLASS", null);
|
||||
IntentDashboardUtils.startDashboard(this, true, targetPackage, targetClass, trackId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
public class RecordingData {
|
||||
|
||||
private final Track track;
|
||||
|
||||
private final TrackPoint latestTrackPoint;
|
||||
|
||||
private final SensorDataSet sensorDataSet;
|
||||
|
||||
/**
|
||||
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
|
||||
*/
|
||||
public RecordingData(Track track, TrackPoint lastTrackPoint, SensorDataSet sensorDataSet) {
|
||||
this.track = track;
|
||||
this.latestTrackPoint = lastTrackPoint;
|
||||
this.sensorDataSet = sensorDataSet;
|
||||
}
|
||||
|
||||
public Track getTrack() {
|
||||
return track;
|
||||
}
|
||||
|
||||
public String getTrackCategory() {
|
||||
if (track == null) {
|
||||
return "";
|
||||
}
|
||||
return track.getCategory();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
if (track == null) {
|
||||
return new TrackStatistics();
|
||||
}
|
||||
|
||||
return track.getTrackStatistics();
|
||||
}
|
||||
|
||||
public TrackPoint getLatestTrackPoint() {
|
||||
return latestTrackPoint;
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorDataSet() {
|
||||
return sensorDataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RecordingData that = (RecordingData) o;
|
||||
return Objects.equals(track, that.track) && Objects.equals(latestTrackPoint, that.latestTrackPoint) && Objects.equals(sensorDataSet, that.sensorDataSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(track, latestTrackPoint, sensorDataSet);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecordingData{" +
|
||||
"track=" + track +
|
||||
", latestTrackPoint=" + latestTrackPoint +
|
||||
", sensorDataSet=" + sensorDataSet +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
|
||||
public class RecordingStatus {
|
||||
private final Track.Id trackId;
|
||||
private final boolean paused;
|
||||
|
||||
@VisibleForTesting
|
||||
RecordingStatus(Track.Id trackId, boolean paused) {
|
||||
this.trackId = trackId;
|
||||
this.paused = paused;
|
||||
}
|
||||
|
||||
public Track.Id getTrackId() {
|
||||
return trackId;
|
||||
}
|
||||
|
||||
public boolean isRecording() {
|
||||
return trackId != null;
|
||||
}
|
||||
|
||||
public boolean isPaused() {
|
||||
return paused;
|
||||
}
|
||||
|
||||
public boolean isRecordingAndNotPaused() {
|
||||
return isRecording() && !isPaused();
|
||||
}
|
||||
|
||||
static RecordingStatus notRecording() {
|
||||
return new RecordingStatus(null, false);
|
||||
}
|
||||
|
||||
static RecordingStatus record(@NonNull Track.Id trackId) {
|
||||
return new RecordingStatus(trackId, false);
|
||||
}
|
||||
|
||||
RecordingStatus pause() {
|
||||
return new RecordingStatus(getTrackId(), true);
|
||||
}
|
||||
|
||||
public RecordingStatus stop() {
|
||||
return TrackRecordingService.STATUS_DEFAULT;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecordingStatus{" +
|
||||
"trackId=" + trackId +
|
||||
", paused=" + paused +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RecordingStatus that = (RecordingStatus) o;
|
||||
return paused == that.paused && Objects.equals(trackId, that.trackId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(trackId, paused);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.dennisguse.opentracks.services;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
@@ -25,7 +26,7 @@ import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||
import de.dennisguse.opentracks.util.TrackNameUtils;
|
||||
|
||||
class TrackRecordingManager {
|
||||
class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = TrackRecordingManager.class.getSimpleName();
|
||||
|
||||
@@ -39,6 +40,9 @@ class TrackRecordingManager {
|
||||
private TrackStatisticsUpdater trackStatisticsUpdater;
|
||||
|
||||
private TrackPoint lastTrackPoint;
|
||||
private TrackPoint lastTrackPointUIWithSpeed;
|
||||
private TrackPoint lastTrackPointUIWithAltitude;
|
||||
|
||||
private TrackPoint lastStoredTrackPoint;
|
||||
private TrackPoint lastStoredTrackPointWithLocation;
|
||||
|
||||
@@ -47,8 +51,18 @@ class TrackRecordingManager {
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
}
|
||||
|
||||
Track.Id start(TrackPoint segmentStartTrackPoint, ZoneOffset zoneOffset) {
|
||||
public void start() {
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
Track.Id startNewTrack(TrackPointCreator trackPointCreator) {
|
||||
TrackPoint segmentStartTrackPoint = trackPointCreator.createSegmentStartManual();
|
||||
// Create new track
|
||||
ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime());
|
||||
Track track = new Track(zoneOffset);
|
||||
trackId = contentProviderUtils.insertTrack(track);
|
||||
track.setId(trackId);
|
||||
@@ -69,7 +83,7 @@ class TrackRecordingManager {
|
||||
}
|
||||
|
||||
//TODO Handle non-existing trackId? Start a new track or exception?
|
||||
void resume(@NonNull Track.Id resumeTrackId, @NonNull TrackPoint segmentStartTrackPoint) {
|
||||
void resumeExistingTrack(@NonNull Track.Id resumeTrackId, @NonNull TrackPointCreator trackPointCreator) {
|
||||
trackId = resumeTrackId;
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
if (track == null) {
|
||||
@@ -78,19 +92,15 @@ class TrackRecordingManager {
|
||||
}
|
||||
|
||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
|
||||
onNewTrackPoint(segmentStartTrackPoint);
|
||||
onNewTrackPoint(trackPointCreator.createSegmentStartManual());
|
||||
|
||||
lastTrackPoint = null;
|
||||
lastStoredTrackPoint = null;
|
||||
lastStoredTrackPointWithLocation = null;
|
||||
reset();
|
||||
}
|
||||
|
||||
void pause(TrackPointCreator trackPointCreator) {
|
||||
insertTrackPoint(trackPointCreator.createSegmentEnd());
|
||||
|
||||
lastTrackPoint = null;
|
||||
lastStoredTrackPoint = null;
|
||||
lastStoredTrackPointWithLocation = null;
|
||||
reset();
|
||||
}
|
||||
|
||||
void end(TrackPointCreator trackPointCreator) {
|
||||
@@ -100,17 +110,15 @@ class TrackRecordingManager {
|
||||
trackId = null;
|
||||
trackStatisticsUpdater = null;
|
||||
|
||||
lastTrackPoint = null;
|
||||
lastStoredTrackPoint = null;
|
||||
lastStoredTrackPointWithLocation = null;
|
||||
reset();
|
||||
}
|
||||
|
||||
Pair<Track, Pair<TrackPoint, SensorDataSet>> get(TrackPointCreator trackPointCreator) {
|
||||
Pair<Track, Pair<TrackPoint, SensorDataSet>> getDataForUI(TrackPointCreator trackPointCreator) {
|
||||
if (trackPointCreator == null) {
|
||||
return null;
|
||||
}
|
||||
TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater);
|
||||
Pair<TrackPoint, SensorDataSet> current = trackPointCreator.createCurrentTrackPoint(lastTrackPoint);
|
||||
Pair<TrackPoint, SensorDataSet> current = trackPointCreator.createCurrentTrackPoint(lastTrackPointUIWithSpeed, lastTrackPointUIWithAltitude, lastStoredTrackPointWithLocation);
|
||||
|
||||
tmpTrackStatisticsUpdater.addTrackPoint(current.first);
|
||||
|
||||
@@ -154,6 +162,12 @@ class TrackRecordingManager {
|
||||
* @return TrackPoint was stored?
|
||||
*/
|
||||
boolean onNewTrackPoint(@NonNull TrackPoint trackPoint) {
|
||||
if (trackPoint.hasSpeed()) {
|
||||
lastTrackPointUIWithSpeed = trackPoint;
|
||||
}
|
||||
if (trackPoint.hasAltitude()) {
|
||||
lastTrackPointUIWithAltitude = trackPoint;
|
||||
}
|
||||
//Storing trackPoint
|
||||
|
||||
// Always insert the first segment location
|
||||
@@ -242,7 +256,17 @@ class TrackRecordingManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(String key) {
|
||||
private void reset() {
|
||||
lastTrackPoint = null;
|
||||
lastTrackPointUIWithSpeed = null;
|
||||
lastTrackPointUIWithAltitude = null;
|
||||
|
||||
lastStoredTrackPoint = null;
|
||||
lastStoredTrackPointWithLocation = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.recording_distance_interval_key, key)) {
|
||||
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval();
|
||||
}
|
||||
|
||||
@@ -16,75 +16,55 @@
|
||||
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Objects;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TrackListActivity;
|
||||
import de.dennisguse.opentracks.TrackRecordingActivity;
|
||||
import de.dennisguse.opentracks.data.CustomContentProvider;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.exporter.ExportServiceResultReceiver;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.announcement.VoiceAnnouncementManager;
|
||||
import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
|
||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.ExportUtils;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
import de.dennisguse.opentracks.util.SystemUtils;
|
||||
|
||||
/**
|
||||
* A background service that registers a location listener and records track points.
|
||||
* Track points are saved to the {@link CustomContentProvider}.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class TrackRecordingService extends Service implements TrackPointCreator.Callback, ExportServiceResultReceiver.Receiver {
|
||||
public class TrackRecordingService extends Service implements TrackPointCreator.Callback {
|
||||
|
||||
private static final String TAG = TrackRecordingService.class.getSimpleName();
|
||||
|
||||
private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
||||
private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofMillis(100);
|
||||
|
||||
public static final RecordingStatus STATUS_DEFAULT = RecordingStatus.notRecording();
|
||||
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null);
|
||||
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
|
||||
|
||||
public class Binder extends android.os.Binder {
|
||||
|
||||
private Binder() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TrackRecordingService getService() {
|
||||
return TrackRecordingService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private final Binder binder = new Binder();
|
||||
|
||||
// The following variables are setFrequency in onCreate:
|
||||
private VoiceAnnouncementManager voiceAnnouncementManager;
|
||||
private TrackRecordingServiceNotificationManager notificationManager;
|
||||
|
||||
private TrackRecordingManager trackRecordingManager;
|
||||
|
||||
private final EGM2008CorrectionManager egm2008CorrectionManager = new EGM2008CorrectionManager();
|
||||
|
||||
private Handler handler;
|
||||
private final Runnable updateRecordingData = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -100,38 +80,24 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
};
|
||||
|
||||
@Deprecated
|
||||
//TODO Workaround as service is not stopped on API23; thus sharedpreferences are not reset between tests.
|
||||
@VisibleForTesting
|
||||
final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||
boolean metricUnits = PreferencesUtils.isMetricUnits();
|
||||
notificationManager.setMetricUnits(metricUnits);
|
||||
}
|
||||
if (PreferencesUtils.isKey(R.string.voice_announcement_frequency_key, key)) {
|
||||
voiceAnnouncementManager.setFrequency(PreferencesUtils.getVoiceAnnouncementFrequency());
|
||||
}
|
||||
if (PreferencesUtils.isKey(new int[]{R.string.voice_announcement_distance_key, R.string.stats_units_key}, key)) {
|
||||
voiceAnnouncementManager.setFrequency(PreferencesUtils.getVoiceAnnouncementDistance());
|
||||
}
|
||||
|
||||
trackPointCreator.onSharedPreferenceChanged(key);
|
||||
trackRecordingManager.onSharedPreferenceChanged(key);
|
||||
}
|
||||
};
|
||||
|
||||
// The following variables are set when recording:
|
||||
private WakeLock wakeLock;
|
||||
|
||||
private TrackPointCreator trackPointCreator; //TODO Move to TrackRecordingManager?
|
||||
|
||||
// The following variables are set in onCreate:
|
||||
private RecordingStatus recordingStatus;
|
||||
private MutableLiveData<RecordingStatus> recordingStatusObservable;
|
||||
private MutableLiveData<GpsStatusValue> gpsStatusObservable;
|
||||
private MutableLiveData<RecordingData> recordingDataObservable;
|
||||
|
||||
// The following variables are set when recording:
|
||||
private WakeLock wakeLock;
|
||||
private Handler handler;
|
||||
|
||||
private TrackPointCreator trackPointCreator;
|
||||
private TrackRecordingManager trackRecordingManager;
|
||||
|
||||
private VoiceAnnouncementManager voiceAnnouncementManager;
|
||||
private TrackRecordingServiceNotificationManager notificationManager;
|
||||
|
||||
private EGM2008CorrectionManager egm2008CorrectionManager;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
@@ -143,14 +109,13 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
gpsStatusObservable = new MutableLiveData<>(STATUS_GPS_DEFAULT);
|
||||
recordingDataObservable = new MutableLiveData<>(NOT_RECORDING);
|
||||
|
||||
egm2008CorrectionManager = new EGM2008CorrectionManager();
|
||||
trackRecordingManager = new TrackRecordingManager(this);
|
||||
trackRecordingManager.start();
|
||||
trackPointCreator = new TrackPointCreator(this);
|
||||
|
||||
voiceAnnouncementManager = new VoiceAnnouncementManager(this);
|
||||
|
||||
notificationManager = new TrackRecordingServiceNotificationManager(this);
|
||||
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,18 +123,19 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
handler.removeCallbacksAndMessages(null); //Some tests do not finish the recording completely
|
||||
handler = null;
|
||||
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
|
||||
trackPointCreator.stop();
|
||||
trackPointCreator = null;
|
||||
trackRecordingManager.stop();
|
||||
trackRecordingManager = null;
|
||||
|
||||
// Reverse order from onCreate
|
||||
showNotification(false); //TODO Why?
|
||||
notificationManager.stop();
|
||||
notificationManager = null;
|
||||
|
||||
egm2008CorrectionManager = null;
|
||||
try {
|
||||
voiceAnnouncementManager.shutdown();
|
||||
voiceAnnouncementManager.stop();
|
||||
} finally {
|
||||
voiceAnnouncementManager = null;
|
||||
}
|
||||
@@ -195,27 +161,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
return binder;
|
||||
}
|
||||
|
||||
public boolean isRecording() {
|
||||
return recordingStatus.isRecording();
|
||||
}
|
||||
|
||||
public boolean isPaused() {
|
||||
return recordingStatus.isPaused();
|
||||
}
|
||||
|
||||
public Marker.Id insertMarker(String name, String category, String description, String photoUrl) {
|
||||
if (!isRecording() || isPaused()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trackRecordingManager.insertMarker(name, category, description, photoUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new track.
|
||||
*
|
||||
* @return the track id
|
||||
*/
|
||||
public Track.Id startNewTrack() {
|
||||
if (isRecording()) {
|
||||
Log.w(TAG, "Ignore startNewTrack. Already recording.");
|
||||
@@ -223,26 +168,17 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
|
||||
// Set recording status
|
||||
TrackPoint segmentStartManual = trackPointCreator.createSegmentStartManual();
|
||||
ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartManual.getTime());
|
||||
Track.Id trackId = trackRecordingManager.start(segmentStartManual, zoneOffset);
|
||||
Track.Id trackId = trackRecordingManager.startNewTrack(trackPointCreator);
|
||||
updateRecordingStatus(RecordingStatus.record(trackId));
|
||||
|
||||
startRecording();
|
||||
return trackId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the track identified by trackId.
|
||||
* It results in a pause/continue.
|
||||
*
|
||||
* @param trackId the id of the track to be resumed.
|
||||
*/
|
||||
public void resumeTrack(Track.Id trackId) {
|
||||
trackPointCreator.resetSensorData();
|
||||
trackRecordingManager.resume(trackId, trackPointCreator.createSegmentStartManual());
|
||||
trackPointCreator.reset();
|
||||
trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator);
|
||||
|
||||
// Set recording status
|
||||
updateRecordingStatus(RecordingStatus.record(trackId));
|
||||
|
||||
startRecording();
|
||||
@@ -258,25 +194,22 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
resumeTrack(recordingStatus.getTrackId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code for starting a new track or resuming a track.
|
||||
*/
|
||||
private void startRecording() {
|
||||
// Update instance variables
|
||||
handler.postDelayed(updateRecordingData, RECORDING_DATA_UPDATE_INTERVAL.toMillis());
|
||||
|
||||
startGps();
|
||||
startSensors();
|
||||
|
||||
voiceAnnouncementManager.restore(trackRecordingManager.getTrackStatistics());
|
||||
voiceAnnouncementManager.start(trackRecordingManager.getTrackStatistics());
|
||||
}
|
||||
|
||||
public void tryStartGps() {
|
||||
public void tryStartSensors() {
|
||||
if (isRecording()) return;
|
||||
|
||||
startGps();
|
||||
startSensors();
|
||||
}
|
||||
|
||||
private void startGps() {
|
||||
private void startSensors() {
|
||||
wakeLock = SystemUtils.acquireWakeLock(this, wakeLock);
|
||||
trackPointCreator.start(this);
|
||||
showNotification(true);
|
||||
@@ -301,7 +234,9 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
|
||||
endRecording(true);
|
||||
|
||||
ExportUtils.postWorkoutExport(this, trackId, new ExportServiceResultReceiver(new Handler(), this));
|
||||
ExportUtils.postWorkoutExport(this, trackId);
|
||||
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
@@ -321,11 +256,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
notificationManager.updateContent(getString(R.string.generic_paused));
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code for ending a track or pausing a track.
|
||||
*
|
||||
* @param trackStopped true if track is stopped, false if track is paused
|
||||
*/
|
||||
private void endRecording(boolean trackStopped) {
|
||||
stopUpdateRecordingData();
|
||||
if (!trackStopped) {
|
||||
@@ -334,33 +264,28 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
recordingDataObservable.postValue(NOT_RECORDING);
|
||||
}
|
||||
|
||||
// Shutdown periodic tasks
|
||||
voiceAnnouncementManager.shutdown();
|
||||
voiceAnnouncementManager.stop();
|
||||
|
||||
// Update instance variables
|
||||
trackPointCreator.stop();
|
||||
|
||||
stopGps(trackStopped);
|
||||
stopSensors();
|
||||
}
|
||||
|
||||
public void stopGpsAndShutdown() {
|
||||
stopGps(true);
|
||||
public void stopSensorsAndShutdown() {
|
||||
if (isRecording()) {
|
||||
return;
|
||||
}
|
||||
stopSensors();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops gps.
|
||||
*
|
||||
* @param shutdown true to shutdown self
|
||||
*/
|
||||
void stopGps(boolean shutdown) {
|
||||
void stopSensors() {
|
||||
if (!isRecording()) return;
|
||||
|
||||
trackPointCreator.stop();
|
||||
showNotification(false);
|
||||
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
|
||||
if (shutdown) {
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -387,36 +312,10 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
|
||||
private void showNotification(boolean isGpsStarted) {
|
||||
if (isRecording()) {
|
||||
Intent intent = IntentUtils.newIntent(this, TrackRecordingActivity.class);
|
||||
|
||||
int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
|
||||
}
|
||||
|
||||
PendingIntent pendingIntent = TaskStackBuilder.create(this)
|
||||
.addNextIntentWithParentStack(intent)
|
||||
.getPendingIntent(0, pendingIntentFlags);
|
||||
|
||||
notificationManager.updatePendingIntent(pendingIntent);
|
||||
notificationManager.updateContent(getString(R.string.gps_starting));
|
||||
startForeground(TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.getNotification());
|
||||
startForeground(TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.setRecording(this));
|
||||
}
|
||||
if (!isRecording() && isGpsStarted) {
|
||||
Intent intent = IntentUtils.newIntent(this, TrackListActivity.class);
|
||||
|
||||
int pendingIntentFlags = 0;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
pendingIntentFlags = PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
}
|
||||
PendingIntent pendingIntent = TaskStackBuilder.create(this)
|
||||
.addParentStack(TrackListActivity.class)
|
||||
.addNextIntent(intent)
|
||||
.getPendingIntent(0, pendingIntentFlags);
|
||||
|
||||
notificationManager.updatePendingIntent(pendingIntent);
|
||||
notificationManager.updateContent(getString(R.string.gps_starting));
|
||||
startForeground(TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.getNotification());
|
||||
startForeground(TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.setGPSonlyStarted(this));
|
||||
}
|
||||
if (!isRecording() && !isGpsStarted) {
|
||||
stopForeground(true);
|
||||
@@ -424,6 +323,14 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
}
|
||||
|
||||
public Marker.Id insertMarker(String name, String category, String description, String photoUrl) {
|
||||
if (!isRecording() || isPaused()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trackRecordingManager.insertMarker(name, category, description, photoUrl);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public TrackPointCreator getTrackPointCreator() {
|
||||
@@ -460,7 +367,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<Track, Pair<TrackPoint, SensorDataSet>> data = trackRecordingManager.get(trackPointCreator);
|
||||
Pair<Track, Pair<TrackPoint, SensorDataSet>> data = trackRecordingManager.getDataForUI(trackPointCreator);
|
||||
if (data == null) {
|
||||
Log.w(TAG, "Requesting data if not recording is taking place, should not be done.");
|
||||
return;
|
||||
@@ -488,160 +395,13 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
recordingStatusObservable.postValue(recordingStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveResult(final int resultCode, final Bundle resultData) {
|
||||
Log.w(TAG, "onReceiveResult: " + resultCode);
|
||||
if (resultCode != ExportServiceResultReceiver.RESULT_CODE_SUCCESS) {
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
intent.putExtra(SettingsActivity.EXTRAS_CHECK_EXPORT_DIRECTORY, true);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
@Deprecated //TODO Should be @VisibleForTesting
|
||||
public boolean isRecording() {
|
||||
return recordingStatus.isRecording();
|
||||
}
|
||||
|
||||
|
||||
public class Binder extends android.os.Binder {
|
||||
|
||||
private Binder() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TrackRecordingService getService() {
|
||||
return TrackRecordingService.this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RecordingStatus {
|
||||
private final Track.Id trackId;
|
||||
private final boolean paused;
|
||||
|
||||
@VisibleForTesting
|
||||
RecordingStatus(Track.Id trackId, boolean paused) {
|
||||
this.trackId = trackId;
|
||||
this.paused = paused;
|
||||
}
|
||||
|
||||
public Track.Id getTrackId() {
|
||||
return trackId;
|
||||
}
|
||||
|
||||
public boolean isRecording() {
|
||||
return trackId != null;
|
||||
}
|
||||
|
||||
public boolean isPaused() {
|
||||
return paused;
|
||||
}
|
||||
|
||||
public boolean isRecordingAndNotPaused() {
|
||||
return isRecording() && !isPaused();
|
||||
}
|
||||
|
||||
private static RecordingStatus notRecording() {
|
||||
return new RecordingStatus(null, false);
|
||||
}
|
||||
|
||||
private static RecordingStatus record(@NonNull Track.Id trackId) {
|
||||
return new RecordingStatus(trackId, false);
|
||||
}
|
||||
|
||||
private RecordingStatus pause() {
|
||||
return new RecordingStatus(getTrackId(), true);
|
||||
}
|
||||
|
||||
public RecordingStatus stop() {
|
||||
return STATUS_DEFAULT;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecordingStatus{" +
|
||||
"trackId=" + trackId +
|
||||
", paused=" + paused +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RecordingStatus that = (RecordingStatus) o;
|
||||
return paused == that.paused && Objects.equals(trackId, that.trackId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(trackId, paused);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RecordingData {
|
||||
|
||||
private final Track track;
|
||||
|
||||
private final TrackPoint latestTrackPoint;
|
||||
|
||||
private final SensorDataSet sensorDataSet;
|
||||
|
||||
/**
|
||||
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
|
||||
*/
|
||||
public RecordingData(Track track, TrackPoint lastTrackPoint, SensorDataSet sensorDataSet) {
|
||||
this.track = track;
|
||||
this.latestTrackPoint = lastTrackPoint;
|
||||
this.sensorDataSet = sensorDataSet;
|
||||
}
|
||||
|
||||
public Track getTrack() {
|
||||
return track;
|
||||
}
|
||||
|
||||
public String getTrackCategory() {
|
||||
if (track == null) {
|
||||
return "";
|
||||
}
|
||||
return track.getCategory();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
if (track == null) {
|
||||
return new TrackStatistics();
|
||||
}
|
||||
|
||||
return track.getTrackStatistics();
|
||||
}
|
||||
|
||||
public TrackPoint getLatestTrackPoint() {
|
||||
return latestTrackPoint;
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorDataSet() {
|
||||
return sensorDataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RecordingData that = (RecordingData) o;
|
||||
return Objects.equals(track, that.track) && Objects.equals(latestTrackPoint, that.latestTrackPoint) && Objects.equals(sensorDataSet, that.sensorDataSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(track, latestTrackPoint, sensorDataSet);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecordingData{" +
|
||||
"track=" + track +
|
||||
", latestTrackPoint=" + latestTrackPoint +
|
||||
", sensorDataSet=" + sensorDataSet +
|
||||
'}';
|
||||
}
|
||||
@VisibleForTesting
|
||||
public boolean isPaused() {
|
||||
return recordingStatus.isPaused();
|
||||
}
|
||||
}
|
||||
+60
-6
@@ -5,21 +5,28 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TrackListActivity;
|
||||
import de.dennisguse.opentracks.TrackRecordingActivity;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Manages the content of the notification shown by {@link TrackRecordingService}.
|
||||
*/
|
||||
class TrackRecordingServiceNotificationManager {
|
||||
class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
static final int NOTIFICATION_ID = 123;
|
||||
|
||||
@@ -34,6 +41,7 @@ class TrackRecordingServiceNotificationManager {
|
||||
private Boolean metricUnits = null;
|
||||
|
||||
TrackRecordingServiceNotificationManager(Context context) {
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, context.getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
|
||||
@@ -54,6 +62,10 @@ class TrackRecordingServiceNotificationManager {
|
||||
.setSmallIcon(R.drawable.ic_logo_color_24dp);
|
||||
}
|
||||
|
||||
void stop() {
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TrackRecordingServiceNotificationManager(NotificationManager notificationManager, NotificationCompat.Builder notificationBuilder) {
|
||||
this.notificationManager = notificationManager;
|
||||
@@ -84,19 +96,50 @@ class TrackRecordingServiceNotificationManager {
|
||||
notificationBuilder.setOnlyAlertOnce(true);
|
||||
}
|
||||
|
||||
void updatePendingIntent(PendingIntent pendingIntent) {
|
||||
Notification setRecording(Context context) {
|
||||
Intent intent = IntentUtils.newIntent(context, TrackRecordingActivity.class);
|
||||
|
||||
int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
|
||||
}
|
||||
|
||||
PendingIntent pendingIntent = TaskStackBuilder.create(context)
|
||||
.addNextIntentWithParentStack(intent)
|
||||
.getPendingIntent(0, pendingIntentFlags);
|
||||
|
||||
updateContent(context.getString(R.string.gps_starting));
|
||||
|
||||
notificationBuilder.setContentIntent(pendingIntent);
|
||||
updateNotification();
|
||||
|
||||
return getNotification();
|
||||
}
|
||||
|
||||
Notification setGPSonlyStarted(Context context) {
|
||||
Intent intent = IntentUtils.newIntent(context, TrackListActivity.class);
|
||||
|
||||
int pendingIntentFlags = 0;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
pendingIntentFlags = PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
}
|
||||
PendingIntent pendingIntent = TaskStackBuilder.create(context)
|
||||
.addParentStack(TrackListActivity.class)
|
||||
.addNextIntent(intent)
|
||||
.getPendingIntent(0, pendingIntentFlags);
|
||||
|
||||
updateContent(context.getString(R.string.gps_starting));
|
||||
|
||||
notificationBuilder.setContentIntent(pendingIntent);
|
||||
updateNotification();
|
||||
|
||||
return getNotification();
|
||||
}
|
||||
|
||||
void cancelNotification() {
|
||||
notificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
Notification getNotification() {
|
||||
return notificationBuilder.build();
|
||||
}
|
||||
|
||||
void setMetricUnits(boolean metricUnits) {
|
||||
this.metricUnits = metricUnits;
|
||||
}
|
||||
@@ -104,4 +147,15 @@ class TrackRecordingServiceNotificationManager {
|
||||
private void updateNotification() {
|
||||
notificationManager.notify(NOTIFICATION_ID, getNotification());
|
||||
}
|
||||
|
||||
private Notification getNotification() {
|
||||
return notificationBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||
setMetricUnits(PreferencesUtils.isMetricUnits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,11 +165,10 @@ public class VoiceAnnouncement {
|
||||
|
||||
boolean isMetricUnits = PreferencesUtils.isMetricUnits();
|
||||
boolean isReportSpeed = PreferencesUtils.isReportSpeed(track.getCategory());
|
||||
Distance minGPSDistance = PreferencesUtils.getRecordingDistanceInterval();
|
||||
|
||||
//TODO Do not load all trackpoints for every announcement
|
||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits), minGPSDistance);
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
||||
|
||||
@@ -179,7 +178,7 @@ public class VoiceAnnouncement {
|
||||
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null, "not used");
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
public void stop() {
|
||||
if (tts != null) {
|
||||
tts.shutdown();
|
||||
tts = null;
|
||||
|
||||
+25
-6
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package de.dennisguse.opentracks.services.announcement;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -23,9 +24,11 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
/**
|
||||
@@ -33,7 +36,7 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class VoiceAnnouncementManager {
|
||||
public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = VoiceAnnouncementManager.class.getSimpleName();
|
||||
|
||||
@@ -55,12 +58,16 @@ public class VoiceAnnouncementManager {
|
||||
|
||||
public VoiceAnnouncementManager(@NonNull TrackRecordingService trackRecordingService) {
|
||||
this.trackRecordingService = trackRecordingService;
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void restore(@Nullable TrackStatistics trackStatistics) {
|
||||
public void start(@Nullable TrackStatistics trackStatistics) {
|
||||
voiceAnnouncement = new VoiceAnnouncement(trackRecordingService);
|
||||
voiceAnnouncement.start();
|
||||
update(trackStatistics);
|
||||
}
|
||||
|
||||
void update(@Nullable TrackStatistics trackStatistics) {
|
||||
this.trackStatistics = trackStatistics;
|
||||
updateNextDuration();
|
||||
updateNextTaskDistance();
|
||||
@@ -88,21 +95,22 @@ public class VoiceAnnouncementManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
public void stop() {
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
|
||||
if (voiceAnnouncement != null) {
|
||||
voiceAnnouncement.shutdown();
|
||||
voiceAnnouncement.stop();
|
||||
voiceAnnouncement = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrequency(Duration frequency) {
|
||||
this.totalTimeFrequency = frequency;
|
||||
restore(this.trackStatistics);
|
||||
update(this.trackStatistics);
|
||||
}
|
||||
|
||||
public void setFrequency(Distance frequency) {
|
||||
this.distanceFrequency = frequency;
|
||||
restore(this.trackStatistics);
|
||||
update(this.trackStatistics);
|
||||
}
|
||||
|
||||
public void updateNextTaskDistance() {
|
||||
@@ -141,4 +149,15 @@ public class VoiceAnnouncementManager {
|
||||
public Distance getNextTotalDistance() {
|
||||
return nextTotalDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(R.string.voice_announcement_frequency_key, key)) {
|
||||
setFrequency(PreferencesUtils.getVoiceAnnouncementFrequency());
|
||||
}
|
||||
|
||||
if (PreferencesUtils.isKey(new int[]{R.string.voice_announcement_distance_key, R.string.stats_units_key}, key)) {
|
||||
setFrequency(PreferencesUtils.getVoiceAnnouncementDistance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.dennisguse.opentracks.services.handlers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
@@ -17,25 +18,27 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.PermissionUtils;
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener {
|
||||
public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private final String TAG = GPSHandler.class.getSimpleName();
|
||||
|
||||
private LocationManager locationManager;
|
||||
private final TrackPointCreator trackPointCreator;
|
||||
private Context context;
|
||||
private LocationManager locationManager;
|
||||
private GpsStatus gpsStatus;
|
||||
private Duration gpsInterval;
|
||||
private Distance thresholdHorizontalAccuracy;
|
||||
private TrackPoint lastTrackPoint;
|
||||
|
||||
public GPSHandler(TrackPointCreator trackPointCreator) {
|
||||
this.trackPointCreator = trackPointCreator;
|
||||
}
|
||||
|
||||
public void onStart(@NonNull Context context) {
|
||||
onSharedPreferenceChanged(null);
|
||||
this.context = context;
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||
gpsStatus = new GpsStatus(context, this);
|
||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
registerLocationListener();
|
||||
@@ -49,19 +52,23 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
|
||||
@SuppressWarnings({"MissingPermission"})
|
||||
//TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates.
|
||||
public void onStop() {
|
||||
lastTrackPoint = null;
|
||||
if (locationManager != null) {
|
||||
locationManager.removeUpdates(this);
|
||||
if (locationManager != null && context != null) {
|
||||
if (PermissionUtils.hasGPSPermission(context)) {
|
||||
locationManager.removeUpdates(this);
|
||||
}
|
||||
locationManager = null;
|
||||
context = null;
|
||||
}
|
||||
|
||||
if (gpsStatus != null) {
|
||||
gpsStatus.stop();
|
||||
gpsStatus = null;
|
||||
}
|
||||
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(String key) {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
boolean registerListener = false;
|
||||
|
||||
if (PreferencesUtils.isKey(R.string.min_recording_interval_key, key)) {
|
||||
@@ -120,7 +127,6 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
|
||||
return;
|
||||
}
|
||||
|
||||
lastTrackPoint = trackPoint;
|
||||
trackPointCreator.onNewTrackPoint(trackPoint);
|
||||
}
|
||||
|
||||
@@ -143,31 +149,23 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
|
||||
}
|
||||
|
||||
private void registerLocationListener() {
|
||||
if (locationManager == null) {
|
||||
Log.e(TAG, "locationManager is null.");
|
||||
if (locationManager == null || context == null) {
|
||||
Log.e(TAG, "Not started.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval.toMillis(), 0, this);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
|
||||
if (PermissionUtils.hasGPSPermission(context)) {
|
||||
try {
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval.toMillis(), 0, this);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrackPoint getLastTrackPoint() {
|
||||
return lastTrackPoint;
|
||||
}
|
||||
|
||||
Distance getThresholdHorizontalAccuracy() {
|
||||
return thresholdHorizontalAccuracy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link GpsStatus} to inform that GPS status has changed from prevStatus to currentStatus.
|
||||
*
|
||||
* @param prevStatus previous {@link GpsStatusValue}.
|
||||
* @param currentStatus current {@link GpsStatusValue}.
|
||||
*/
|
||||
@Override
|
||||
public void onGpsStatusChanged(GpsStatusValue prevStatus, GpsStatusValue currentStatus) {
|
||||
trackPointCreator.sendGpsStatus(currentStatus);
|
||||
|
||||
@@ -56,7 +56,7 @@ class GpsStatus {
|
||||
|
||||
public void stop() {
|
||||
stopped = true;
|
||||
sendStatus(gpsStatus, GpsStatusValue.GPS_NONE);
|
||||
sendStatus(gpsStatus, GpsStatusValue.GPS_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
|
||||
remoteSensorManager.start();
|
||||
altitudeSumManager.start(context);
|
||||
|
||||
}
|
||||
|
||||
private boolean isStarted() {
|
||||
@@ -70,7 +71,7 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
gpsHandler.onStop();
|
||||
}
|
||||
|
||||
public void resetSensorData() {
|
||||
public void reset() {
|
||||
if (remoteSensorManager == null || altitudeSumManager == null) {
|
||||
Log.d(TAG, "No recording running and no reset necessary.");
|
||||
return;
|
||||
@@ -106,10 +107,6 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(String key) {
|
||||
gpsHandler.onSharedPreferenceChanged(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Got a new TrackPoint from Bluetooth only; contains no GPS location.
|
||||
*/
|
||||
@@ -123,7 +120,7 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
|
||||
boolean stored = service.newTrackPoint(trackPoint, gpsHandler.getThresholdHorizontalAccuracy());
|
||||
if (stored) {
|
||||
resetSensorData();
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,34 +131,32 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
public TrackPoint createSegmentEnd() {
|
||||
TrackPoint segmentEnd = TrackPoint.createSegmentEndWithTime(createNow());
|
||||
fill(segmentEnd);
|
||||
resetSensorData();
|
||||
reset();
|
||||
return segmentEnd;
|
||||
}
|
||||
|
||||
public Pair<TrackPoint, SensorDataSet> createCurrentTrackPoint(@Nullable TrackPoint lastValidTrackPoint) {
|
||||
public Pair<TrackPoint, SensorDataSet> createCurrentTrackPoint(@Nullable TrackPoint lastTrackPointUISpeed, @Nullable TrackPoint lastTrackPointUIAltitude, @Nullable TrackPoint lastStoredTrackPointWithLocation) {
|
||||
TrackPoint currentTrackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, createNow());
|
||||
TrackPoint lastTrackPoint = gpsHandler.getLastTrackPoint();
|
||||
|
||||
if (lastTrackPoint != null && lastTrackPoint.hasLocation()) {
|
||||
currentTrackPoint.setSpeed(lastTrackPoint.getSpeed());
|
||||
currentTrackPoint.setAltitude(lastTrackPoint.getAltitude());
|
||||
if (lastTrackPoint.hasBearing()) {
|
||||
currentTrackPoint.setBearing(lastTrackPoint.getBearing());
|
||||
}
|
||||
if (lastTrackPointUISpeed != null) {
|
||||
currentTrackPoint.setSpeed(lastTrackPointUISpeed.getSpeed());
|
||||
}
|
||||
if (lastValidTrackPoint != null && lastValidTrackPoint.hasLocation()) {
|
||||
if (lastTrackPointUIAltitude != null) {
|
||||
currentTrackPoint.setAltitude(lastTrackPointUIAltitude.getAltitude());
|
||||
}
|
||||
|
||||
if (lastStoredTrackPointWithLocation != null && lastStoredTrackPointWithLocation.hasLocation()) {
|
||||
//We are taking the coordinates from the last stored TrackPoint, so the distance is monotonously increasing.
|
||||
currentTrackPoint.setLongitude(lastValidTrackPoint.getLongitude());
|
||||
currentTrackPoint.setLatitude(lastValidTrackPoint.getLatitude());
|
||||
currentTrackPoint.setLongitude(lastStoredTrackPointWithLocation.getLongitude());
|
||||
currentTrackPoint.setLatitude(lastStoredTrackPointWithLocation.getLatitude());
|
||||
}
|
||||
|
||||
SensorDataSet sensorDataSet = fill(currentTrackPoint);
|
||||
|
||||
return new Pair<>(currentTrackPoint, sensorDataSet);
|
||||
}
|
||||
|
||||
//TODO Limit visibility
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public Instant createNow() {
|
||||
Instant createNow() {
|
||||
return Instant.now(clock);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package de.dennisguse.opentracks.settings;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.UriPermission;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
@@ -10,7 +8,6 @@ import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
@@ -76,7 +73,7 @@ public class ImportExportSettingsFragment extends PreferenceFragmentCompat {
|
||||
return getString(R.string.not_set);
|
||||
}
|
||||
|
||||
return directoryUri.toString() + (directory.canWrite() ? "" : getString(R.string.export_dir_not_writable));
|
||||
return directoryUri + (directory.canWrite() ? "" : getString(R.string.export_dir_not_writable));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
|
||||
@@ -14,7 +15,7 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
private static final String TAG = MainSettingsFragment.class.getSimpleName();
|
||||
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
private final TrackRecordingServiceConnection.Callback bindServiceCallback =
|
||||
service -> service.getRecordingStatusObservable()
|
||||
@@ -56,6 +57,11 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.settings_api_key)).setOnPreferenceClickListener(preference -> {
|
||||
((SettingsActivity) getActivity()).openScreen(getString(R.string.settings_api_key));
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.settings_open_tracks_key)).setOnPreferenceClickListener(preference -> {
|
||||
((SettingsActivity) getActivity()).openScreen(getString(R.string.settings_open_tracks_key));
|
||||
return true;
|
||||
@@ -98,7 +104,7 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
|
||||
super.onDisplayPreferenceDialog(preference);
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
this.recordingStatus = status;
|
||||
if (isAdded()) {
|
||||
updatePrefsDependOnRecording();
|
||||
|
||||
@@ -182,6 +182,10 @@ public class PreferencesUtils {
|
||||
return getBoolean(R.string.publicapi_enabled_key, resources.getBoolean(R.bool.publicapi_enabled_default));
|
||||
}
|
||||
|
||||
public static boolean isPublicAPIDashboardEnabled() {
|
||||
return getBoolean(R.string.publicapi_dashboard_enabled_key, resources.getBoolean(R.bool.publicapi_dashboard_enabled_default));
|
||||
}
|
||||
|
||||
public static boolean isMetricUnits() {
|
||||
final String STATS_UNIT = resources.getString(R.string.stats_units_default);
|
||||
return STATS_UNIT.equals(getString(R.string.stats_units_key, STATS_UNIT));
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.dennisguse.opentracks.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
|
||||
public class PublicAPISettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.settings_public_api);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
((SettingsActivity) getActivity()).getSupportActionBar().setTitle(R.string.settings_api_title);
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,8 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity
|
||||
fragment = new AnnouncementsSettingsFragment();
|
||||
} else if (key.equals(getString(R.string.settings_import_export_key))) {
|
||||
fragment = new ImportExportSettingsFragment();
|
||||
} else if (key.equals(getString(R.string.settings_api_key))) {
|
||||
fragment = new PublicAPISettingsFragment();
|
||||
} else if (key.equals(getString(R.string.settings_open_tracks_key))) {
|
||||
fragment = new OpenTracksSettingsFragment();
|
||||
}
|
||||
|
||||
@@ -9,14 +9,12 @@ import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.ShareContentProvider;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
@@ -47,6 +45,7 @@ public class ShareUtils {
|
||||
trackDescription = track == null ? "" : new DescriptionGenerator(context).generateTrackDescription(track, false);
|
||||
}
|
||||
|
||||
String mime = "";
|
||||
ArrayList<Uri> uris = new ArrayList<>();
|
||||
for (Track.Id trackId : trackIds) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
@@ -56,14 +55,14 @@ public class ShareUtils {
|
||||
}
|
||||
|
||||
String trackName = FileUtils.sanitizeFileName(track.getName());
|
||||
Pair<Uri, String> uriTrackFile = ShareContentProvider.createURI(trackId, trackName, PreferencesUtils.getExportTrackFileFormat());
|
||||
Pair<Uri, String> uriSharePicture = ShareContentProvider.createURI(trackId, trackName, TrackFileFormat.SHARE_PICTURE_PNG);
|
||||
Pair<Uri, String> uriAndMime = ShareContentProvider.createURI(trackId, trackName, PreferencesUtils.getExportTrackFileFormat());
|
||||
|
||||
uris.addAll(Arrays.asList(uriSharePicture.first, uriTrackFile.first));
|
||||
uris.add(uriAndMime.first);
|
||||
mime = uriAndMime.second;
|
||||
}
|
||||
|
||||
return new Intent(Intent.ACTION_SEND_MULTIPLE)
|
||||
.setType("image/*")
|
||||
.setType(mime)
|
||||
.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.share_track_subject))
|
||||
|
||||
@@ -17,16 +17,13 @@ public class IntervalStatistics {
|
||||
private TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
private final List<Interval> intervalList;
|
||||
private final Distance distanceInterval;
|
||||
private final Distance minGPSDistance;
|
||||
private Interval interval, lastInterval;
|
||||
|
||||
/**
|
||||
* @param distanceInterval distance of every interval.
|
||||
* @param minGPSDistance the setting value for GPS distance.
|
||||
*/
|
||||
public IntervalStatistics(Distance distanceInterval, Distance minGPSDistance) {
|
||||
public IntervalStatistics(Distance distanceInterval) {
|
||||
this.distanceInterval = distanceInterval;
|
||||
this.minGPSDistance = minGPSDistance;
|
||||
|
||||
interval = new Interval();
|
||||
lastInterval = new Interval();
|
||||
|
||||
@@ -22,7 +22,6 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
/**
|
||||
* This model is used to load intervals for a track.
|
||||
@@ -35,7 +34,6 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
private MutableLiveData<List<IntervalStatistics.Interval>> intervalsLiveData;
|
||||
private IntervalStatistics intervalStatistics;
|
||||
private Distance distanceInterval;
|
||||
private final Distance minGPSDistance;
|
||||
private final ContentResolver contentResolver;
|
||||
private ContentObserver trackPointsTableObserver;
|
||||
private TrackPoint.Id lastTrackPointId;
|
||||
@@ -46,7 +44,6 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
public IntervalStatisticsModel(@NonNull Application application) {
|
||||
super(application);
|
||||
minGPSDistance = PreferencesUtils.getRecordingDistanceInterval();
|
||||
contentResolver = getApplication().getContentResolver();
|
||||
handlerThread = new HandlerThread(TAG);
|
||||
handlerThread.start();
|
||||
@@ -75,7 +72,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
intervalsLiveData = new MutableLiveData<>();
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval, minGPSDistance);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
@@ -114,7 +111,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
lastTrackPointId = null;
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval, minGPSDistance);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
import de.dennisguse.opentracks.databinding.MarkerListBinding;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.share.ShareUtils;
|
||||
@@ -59,7 +60,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
|
||||
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||
|
||||
private Track track;
|
||||
private MarkerResourceCursorAdapter resourceCursorAdapter;
|
||||
@@ -284,7 +285,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ package de.dennisguse.opentracks.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
@@ -25,12 +27,13 @@ import de.dennisguse.opentracks.io.file.exporter.ExportService;
|
||||
import de.dennisguse.opentracks.io.file.exporter.ExportServiceResultReceiver;
|
||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||
|
||||
public class ExportUtils {
|
||||
|
||||
private static final String TAG = ExportUtils.class.getSimpleName();
|
||||
|
||||
public static void postWorkoutExport(Context context, Track.Id trackId, ExportServiceResultReceiver resultReceiver) {
|
||||
public static void postWorkoutExport(Context context, Track.Id trackId) {
|
||||
if (PreferencesUtils.shouldInstantExportAfterWorkout()) {
|
||||
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat();
|
||||
DocumentFile directory = IntentUtils.toDocumentFile(context, PreferencesUtils.getDefaultExportDirectoryUri());
|
||||
@@ -40,6 +43,16 @@ public class ExportUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
ExportServiceResultReceiver resultReceiver = new ExportServiceResultReceiver(new Handler(), new ExportServiceResultReceiver.Receiver() {
|
||||
@Override
|
||||
public void onExportError(Track.Id trackId) {
|
||||
Intent intent = new Intent(context, SettingsActivity.class);
|
||||
intent.putExtra(SettingsActivity.EXTRAS_CHECK_EXPORT_DIRECTORY, true);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
ExportService.enqueue(context, resultReceiver, trackId, trackFileFormat, directory.getUri());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public class FileUtils {
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
int codePoint = name.codePointAt(i);
|
||||
char character = name.charAt(i);
|
||||
if (Character.isLetterOrDigit(character) || codePoint > 127 || isSpecialFat32(character) || character == '.') {
|
||||
if (Character.isLetterOrDigit(character) || isSpecialFat32(character) || character == '.') {
|
||||
builder.appendCodePoint(codePoint);
|
||||
} else {
|
||||
builder.append("_");
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -23,6 +24,7 @@ import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
* The receiving {@link android.app.Activity} gets temporary access to the {@link TracksColumns} and the {@link TrackPointsColumns} (incl. update).
|
||||
*/
|
||||
public class IntentDashboardUtils {
|
||||
private static final String TAG = IntentDashboardUtils.class.getSimpleName();
|
||||
|
||||
private static final String ACTION_DASHBOARD = "Intent.OpenTracks-Dashboard";
|
||||
|
||||
@@ -58,6 +60,15 @@ public class IntentDashboardUtils {
|
||||
* @param trackIds the track ids
|
||||
*/
|
||||
public static void startDashboard(Context context, boolean isRecording, Track.Id... trackIds) {
|
||||
startDashboard(context, isRecording, null, null, trackIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send intent to show tracks on a map (needs an another app) as resource URIs.
|
||||
* By providing a targetPackage and targetClass an explicit intent can be sent,
|
||||
* thus bypassing the need for the user to select an app.
|
||||
*/
|
||||
public static void startDashboard(Context context, boolean isRecording, String targetPackage, String targetClass, Track.Id... trackIds) {
|
||||
if (trackIds.length == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -87,6 +98,13 @@ public class IntentDashboardUtils {
|
||||
clipData.addItem(new ClipData.Item(uris.get(MARKERS_URI_INDEX)));
|
||||
intent.setClipData(clipData);
|
||||
|
||||
if ((targetPackage != null) && (targetClass != null)) {
|
||||
Log.i(TAG, "Starting dashboard activity with explicit intent (package=" + targetPackage + ", class=" + targetClass + ")");
|
||||
intent.setClassName(targetPackage, targetClass);
|
||||
} else {
|
||||
Log.i(TAG, "Starting dashboard activity with generic intent (package=" + targetPackage + ", class=" + targetClass + ")");
|
||||
}
|
||||
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.dennisguse.opentracks.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class PermissionUtils {
|
||||
|
||||
private PermissionUtils() {
|
||||
}
|
||||
|
||||
public static boolean hasGPSPermission(Context context) {
|
||||
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,9 @@ public class TrackIconUtils {
|
||||
private static final String INLINE_SKATING = "INLINES_SKATING";
|
||||
private static final String SKATE_BOARDING = "SKATE_BOARDING";
|
||||
private static final String CLIMBING = "CLIMBING";
|
||||
private static final String SWIMMING = "SWIMMING";
|
||||
private static final String SWIMMING_OPEN = "SWIMMING_OPEN";
|
||||
private static final String WORKOUT = "WORKOUT";
|
||||
|
||||
private static final int ACTIVITY_UNKNOWN_LOGO = R.drawable.ic_logo_24dp;
|
||||
|
||||
@@ -71,6 +74,8 @@ public class TrackIconUtils {
|
||||
private static final int[] SKATE_BOARDING_LIST = new int[]{R.string.activity_type_skate_boarding};
|
||||
private static final int[] KAYAKING_LIST = new int[]{R.string.activity_type_kayaking};
|
||||
private static final int[] WALK_LIST = new int[]{R.string.activity_type_hiking, R.string.activity_type_off_trail_hiking, R.string.activity_type_speed_walking, R.string.activity_type_trail_hiking, R.string.activity_type_walking};
|
||||
private static final int[] SWIM_LIST = new int[]{R.string.activity_type_swimming, R.string.activity_type_swimming_open};
|
||||
private static final int[] WORKOUT_LIST = new int[]{R.string.activity_type_workout};
|
||||
|
||||
// List of icons whose sports associated use speed (in km/h or mi/h).
|
||||
private static final int[] SPEED_ICON = {
|
||||
@@ -110,6 +115,9 @@ public class TrackIconUtils {
|
||||
MAP.put(KAYAK, new Pair<>(R.string.activity_type_kayaking, R.drawable.ic_activity_kayaking_24dp));
|
||||
MAP.put(BOAT, new Pair<>(R.string.activity_type_boat, R.drawable.ic_activity_boat_24dp));
|
||||
MAP.put(SAILING, new Pair<>(R.string.activity_type_sailing, R.drawable.ic_activity_sailing_24dp));
|
||||
MAP.put(SWIMMING, new Pair<>(R.string.activity_type_swimming, R.drawable.ic_activity_swimming_24dp));
|
||||
MAP.put(SWIMMING_OPEN, new Pair<>(R.string.activity_type_swimming_open, R.drawable.ic_activity_swimming_open_24dp));
|
||||
MAP.put(WORKOUT, new Pair<>(R.string.activity_type_workout, R.drawable.ic_activity_workout_24dp));
|
||||
}
|
||||
|
||||
private TrackIconUtils() {
|
||||
@@ -208,6 +216,12 @@ public class TrackIconUtils {
|
||||
if (inList(resources, activityType, WALK_LIST)) {
|
||||
return WALK;
|
||||
}
|
||||
if (inList(resources, activityType, SWIM_LIST)) {
|
||||
return SWIMMING;
|
||||
}
|
||||
if (inList(resources, activityType, WORKOUT_LIST)) {
|
||||
return WORKOUT;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
||||
@@ -24,7 +24,7 @@ import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
public class StatisticDataBuilder {
|
||||
|
||||
public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull TrackRecordingService.RecordingData recordingData, @NonNull Layout layout, boolean metricUnits) {
|
||||
public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull Layout layout, boolean metricUnits) {
|
||||
List<StatisticData> statisticDataList = layout.getFields().stream()
|
||||
.filter(DataField::isVisible)
|
||||
.map(field -> build(context, recordingData, field.getKey(), field.isPrimary(), metricUnits))
|
||||
@@ -34,7 +34,7 @@ public class StatisticDataBuilder {
|
||||
return statisticDataList;
|
||||
}
|
||||
|
||||
private static StatisticData build(@NonNull Context context, @NonNull TrackRecordingService.RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, boolean metricUnits) {
|
||||
private static StatisticData build(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, boolean metricUnits) {
|
||||
final TrackPoint latestTrackPoint = recordingData.getLatestTrackPoint();
|
||||
final SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||
final TrackStatistics trackStatistics = recordingData.getTrackStatistics();
|
||||
@@ -153,7 +153,7 @@ public class StatisticDataBuilder {
|
||||
/**
|
||||
* Builds a list of StatisticData with sensors configured but not in statisticDataList.
|
||||
*/
|
||||
private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, TrackRecordingService.RecordingData recordingData, List<StatisticData> statisticDataList, boolean metricUnits) {
|
||||
private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, RecordingData recordingData, List<StatisticData> statisticDataList, boolean metricUnits) {
|
||||
List<StatisticData> sensorDataList = new ArrayList<>();
|
||||
SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||
if (sensorDataSet == null) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||
|
||||
public class StatisticsDataModel extends AndroidViewModel {
|
||||
@@ -26,7 +26,7 @@ public class StatisticsDataModel extends AndroidViewModel {
|
||||
return statsData;
|
||||
}
|
||||
|
||||
public void update(TrackRecordingService.RecordingData recordingData, Layout layout, boolean metricUnit) {
|
||||
public void update(RecordingData recordingData, Layout layout, boolean metricUnit) {
|
||||
new Thread(() -> {
|
||||
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(getApplication(), recordingData, layout, metricUnit);
|
||||
statsData.postValue(statisticDataList);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<vector android:height="24dp" android:viewportHeight="21.99934"
|
||||
android:viewportWidth="21.84952" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m18.3273,15.5167c-1.0171,-0.0182 -1.9033,0.7707 -2.9456,0.5005 -0.9523,-0.2718 -1.9505,-0.7655 -2.9493,-0.3389 -0.9384,0.4921 -2.0789,0.4938 -3.017,0C8.4158,15.2514 7.4165,15.7448 6.4634,16.0171 5.2611,16.312 4.2318,15.2563 3.0297,15.5586 2.2389,15.8067 1.0535,16.1129 1.0535,16.1129v1.7649c1.0227,0.0195 1.9128,-0.7764 2.9601,-0.4982 1.4913,0.5895 1.7842,0.6237 2.7778,0.3753 0.9554,-0.4404 2.0942,-0.6063 3.0559,-0.0798 0.9567,0.4291 1.9816,0.0931 2.8934,-0.2638 1.0381,-0.3395 1.9553,0.3821 2.956,0.4619 1.0872,0.1057 2.0198,-0.7841 3.1216,-0.4936 0.5567,-0.0151 1.9432,1.034 1.9777,0.1483v-1.4713c-0.8787,0.0509 -1.5921,-0.5889 -2.4688,-0.5401z" android:strokeWidth="0.20758"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m18.3273,12.592c-1.0171,-0.0182 -1.9033,0.7707 -2.9456,0.5005 -0.9523,-0.2718 -1.9505,-0.7655 -2.9493,-0.3389 -0.9384,0.4921 -2.0789,0.4938 -3.017,0C8.4158,12.3268 7.4165,12.8201 6.4634,13.0925 5.2611,13.3873 4.2318,12.3317 3.0297,12.634 2.2389,12.8821 1.0535,13.1883 1.0535,13.1883v1.7649c1.0227,0.0195 1.9128,-0.7764 2.9601,-0.4982 1.4913,0.5895 1.7842,0.6237 2.7778,0.3753 0.9554,-0.4404 2.0942,-0.6063 3.0559,-0.0798 0.9567,0.4291 1.9816,0.0931 2.8934,-0.2638 1.0381,-0.3395 1.9553,0.3821 2.956,0.4619 1.0872,0.1057 2.0198,-0.7841 3.1216,-0.4936 0.5567,-0.0151 1.9432,1.034 1.9777,0.1483v-1.4713c-0.8787,0.0509 -1.5921,-0.5889 -2.4688,-0.5401z" android:strokeWidth="0.20758"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m15.7716,8.3605c0.0551,1.1808 -1.4064,2.0133 -2.3942,1.3656 -1.0445,-0.5537 -1.0179,-2.2353 0.0433,-2.7559 1.0184,-0.592 2.3788,0.2078 2.3509,1.3903z" android:strokeWidth="1.16861"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="M4.3146,12.0144 L9.3211,8.9479 6.7861,6.2628 11.9085,3.597c0.9367,-0.3746 1.6015,0.5529 1.0969,1.1662L9.4152,6.6599 15.5048,12.5142c-1.3345,-0.3907 -1.5957,-1.0088 -2.6631,-0.6568 -2.8185,0.9295 -2.2197,0.0047 -4.2403,0.0209 -2.2837,0.0182 -1.899,1.154 -4.2869,0.1361z"
|
||||
android:strokeColor="#00000000" android:strokeLineCap="butt"
|
||||
android:strokeLineJoin="miter" android:strokeWidth="1.18448"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,29 @@
|
||||
<vector android:height="24dp" android:viewportHeight="21.99934"
|
||||
android:viewportWidth="21.84952" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m2.7434,17.5717c-0.1058,0.0005 -0.2131,0.0136 -0.3223,0.041 -0.5747,0.1803 -1.4355,0.4023 -1.4355,0.4023l0,1.2812c0.7432,0.0141 1.3912,-0.5635 2.1523,-0.3613 1.0837,0.4284 1.2955,0.454 2.0175,0.2734 0.6943,-0.3201 1.5217,-0.4413 2.2206,-0.0586 0.6952,0.3118 1.4408,0.068 2.1035,-0.1914 0.7544,-0.2467 1.4211,0.2779 2.1484,0.3359 0.621,-0.0088 1.3519,-0.3994 1.8183,-0.3965 0.5367,0.0225 1.0513,0.2342 1.498,0.3828 0.3578,0.0766 0.7179,0.021 0.9707,-0.0722 0.7173,-0.2646 1.5217,-0.4413 2.2206,-0.0586 0.6952,0.3118 1.4408,0.068 2.1035,-0.1914 0.2296,-0.0751 0.4506,-0.0778 0.6679,-0.0449l0,-1.3144c-0.2959,-0.041 -0.5941,-0.0279 -0.8926,0.0996 -0.682,0.3576 -1.5115,0.3588 -2.1933,0 -0.7264,-0.3102 -1.4519,0.0482 -2.1445,0.2461 -0.1166,0.0286 -0.231,0.0388 -0.3437,0.0371l0,-0.0078c-0.3046,0.0233 -0.6105,-0.1228 -0.8789,-0.1894 -1.0617,-0.5989 -2.2859,0.1489 -3.0566,0.1601 -0.5103,-0.1115 -1.4167,-0.5561 -2.1425,-0.2461 -0.682,0.3576 -1.5115,0.3588 -2.1933,0C6.3352,17.3885 5.6097,17.7469 4.9171,17.9448 4.1526,18.1323 3.4837,17.5685 2.7434,17.5717Z" android:strokeWidth="0.15085247"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m10.1545,15.4447c-0.234,-0.0118 -0.6643,0.0285 -0.8996,0.129 -0.682,0.3576 -1.5115,0.3588 -2.1933,0C6.3352,15.2636 5.6097,15.6219 4.9171,15.8198 4.0434,16.0341 3.2947,15.2662 2.4211,15.4859 1.8464,15.6662 0.9856,15.8901 0.9856,15.8901l0,1.2812c0.7432,0.0141 1.3912,-0.5635 2.1523,-0.3613 1.0837,0.4284 1.2955,0.454 2.0175,0.2734 0.6943,-0.3201 1.5217,-0.4413 2.2206,-0.0586 0.3325,0.1491 0.6768,0.1691 1.0175,0.123 1.1763,-0.3771 1.7845,-0.5109 3.1301,0.0567 0.6455,0.0518 1.3443,-0.4456 2.2232,-0.4238 0.2646,-0.0133 1.0921,0.2466 1.4785,0.3652l0.002,0c0.5607,0.0803 1.135,-0.1155 1.6582,-0.3203 0.7544,-0.2467 1.4211,0.2779 2.1484,0.3359 0.68,0.0661 1.2778,-0.4027 1.9413,-0.4004l0,-1.3125c-0.0096,0.0003 -0.0197,-0.0005 -0.0293,0 -0.7392,-0.0133 -1.3831,0.5596 -2.1406,0.3633 -0.692,-0.1975 -1.4167,-0.5561 -2.1425,-0.2461 -1.6554,0.7989 -2.1315,-0.1361 -3.123,-0.1094 -0.5666,-0.0102 -1.0781,0.3243 -1.6269,0.3926 -0.7683,0.02 -1.1248,-0.2423 -1.7586,-0.4044z" android:strokeWidth="0.15085247"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m11.6818,12.3808c0.04,0.8581 -1.022,1.4631 -1.7399,0.9924 -0.7591,-0.4024 -0.7397,-1.6244 0.0315,-2.0028 0.7401,-0.4302 1.7287,0.151 1.7084,1.0104z" android:strokeWidth="0.849248"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m3.3557,15.0361 l3.6383,-2.2285 -1.8422,-1.9512 3.7226,-1.9373c0.6807,-0.2722 1.1638,0.4018 0.7971,0.8475l-2.6091,1.3783 4.4254,4.2544c-0.9698,-0.2839 -1.1597,-0.7331 -1.9353,-0.4773 -2.0482,0.6755 -1.6131,0.0034 -3.0815,0.0152 -1.6596,0.0132 -1.38,0.8387 -3.1154,0.0989z"
|
||||
android:strokeColor="#00000000" android:strokeLineCap="butt"
|
||||
android:strokeLineJoin="miter" android:strokeWidth="0.860781"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m21.1085,13.3063c-0.2603,0.0722 -0.5049,-0.3633 -0.8865,-0.3338 -0.6829,0.0526 -0.6885,0.2737 -1.1704,0.3331 -0.5638,-0.0118 -0.7051,-0.3911 -1.3231,-0.3855 -0.7972,0.0501 -0.8166,0.3448 -1.5064,0.3278 -0.6352,-0.006 -0.5848,-0.4008 -1.1376,-0.3736 -0.4459,0 -0.4235,0.3631 -1.0302,0.3368 0.8044,-1.9921 7.3134,-2.4728 7.0541,0.0952z"
|
||||
android:strokeLineCap="square" android:strokeWidth="1.00154"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m15.9523,6.3417 l0.8048,0.0055c0.7916,0.9558 1.568,2.3417 2.2881,5.3258l-1.7913,0.3682c0.0085,-1.596 -0.3277,-3.5172 -1.3016,-5.6995z"
|
||||
android:strokeLineCap="square" android:strokeWidth="1.00154"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="M15.7145,5.7993 L16.4606,5.6944C17.8926,5.5299 18.9304,6.2178 19.8263,7.1623 18.3158,6.5191 17.7587,6.2722 16.1948,6.4667 14.8205,6.8297 13.8049,7.216 13.2511,7.9257 13.3966,7.3314 13.938,6.4827 15.7145,5.7993Z"
|
||||
android:strokeLineCap="square" android:strokeWidth="1.00154"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m16.1656,5.4723c-0.0897,0.0805 -0.1785,0.1681 -0.2653,0.2649l-0.0964,0.1131 0.3909,0.6164C17.1506,5.4034 17.6862,5.2561 19.0601,4.8594 18.0325,4.6521 17.033,4.6944 16.1656,5.4723Z"
|
||||
android:strokeLineCap="square" android:strokeWidth="0.961457"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="M16.3148,5.7308C16.2942,5.7174 16.274,5.7037 16.2529,5.6906L15.6743,5.3522c-1.5912,-0.4464 -2.3886,-0.0545 -2.7819,0.3521 0.7387,-0.2697 1.6457,-0.011 2.7958,0.4706 0.0942,0.0571 0.1807,0.1119 0.2642,0.1669z"
|
||||
android:strokeLineCap="square" android:strokeWidth="0.928756"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,109 @@
|
||||
<vector android:height="24dp" android:viewportHeight="5.820833"
|
||||
android:viewportWidth="5.820833" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="#cacaca"
|
||||
android:pathData="M14.77216,-15.55645l26.53766,0l0,30.62037l-26.53766,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.6652036"/>
|
||||
<path android:fillColor="#e74c3c"
|
||||
android:pathData="M15.79283,-14.53577l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#ed1515"
|
||||
android:pathData="M19.87555,-14.53577l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#f47750"
|
||||
android:pathData="M23.95827,-14.53577l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#fdbc4b"
|
||||
android:pathData="M28.04098,-14.53577l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#c9ce3b"
|
||||
android:pathData="M32.1237,-14.53577l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#da4453"
|
||||
android:pathData="M15.79283,-10.45305l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#c0392b"
|
||||
android:pathData="M19.87555,-10.45305l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#d35400"
|
||||
android:pathData="M23.95827,-10.45305l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#f67400"
|
||||
android:pathData="M28.04098,-10.45305l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#f39c1f"
|
||||
android:pathData="M32.1237,-10.45305l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#1cdc9a"
|
||||
android:pathData="M15.79283,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#2ecc71"
|
||||
android:pathData="M19.87555,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#1abc9c"
|
||||
android:pathData="M23.95827,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#3498db"
|
||||
android:pathData="M28.04098,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#3daee9"
|
||||
android:pathData="M32.1237,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#10d116"
|
||||
android:pathData="M15.79283,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#27ae60"
|
||||
android:pathData="M19.87555,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#16a085"
|
||||
android:pathData="M23.95827,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#2980b9"
|
||||
android:pathData="M28.04098,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#1d99f3"
|
||||
android:pathData="M32.1237,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#9b59b6"
|
||||
android:pathData="M36.20642,-4.32897l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#8e44ad"
|
||||
android:pathData="M36.20642,-0.24626l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#34495e"
|
||||
android:pathData="M15.79284,5.87782l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#31363b"
|
||||
android:pathData="M19.87556,5.87782l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#7f8c8d"
|
||||
android:pathData="M23.95828,5.87782l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#bdc3c7"
|
||||
android:pathData="M28.04099,5.87782l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#fcfcfc"
|
||||
android:pathData="M32.12371,5.87782l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#2c3e50"
|
||||
android:pathData="M15.79284,9.96054l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#232629"
|
||||
android:pathData="M19.87556,9.96054l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#4d4d4d"
|
||||
android:pathData="M23.95828,9.96054l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#95a5a6"
|
||||
android:pathData="M28.04099,9.96054l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#eff0f1"
|
||||
android:pathData="M32.12371,9.96054l4.08272,0l0,4.08272l-4.08272,0z"
|
||||
android:strokeLineCap="square" android:strokeLineJoin="round" android:strokeWidth="5.769168"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="m3.31298,1.34824c-0.21043,0 -0.38292,0.17553 -0.38292,0.39016 0,0.21463 0.17249,0.39016 0.38292,0.39016 0.21043,0 0.38241,-0.17553 0.38241,-0.39016 0,-0.21463 -0.17197,-0.39016 -0.38241,-0.39016zM4.82038,1.95337c-0.26598,0.00002 -0.4816,0.21564 -0.48162,0.48162 0.00026,0.06831 0.00751,0.16626 0.08027,0.24751L4.15732,2.88036 3.56876,2.36742 2.7156,2.27428 1.98645,2.73527 1.52652,3.32745c-0.09934,0.17498 0.04806,0.33066 0.20567,0.2558l0.4532,-0.5492 0.50281,-0.32282 -0.15245,1.08751 -0.68471,1.5689 0.39274,-0.00775c0.12705,-0.24007 0.68781,-1.43971 0.68781,-1.43971l0.54364,0.24908l0,1.17047l0.38241,0l0,-1.46348L3.37344,3.67161l0.17208,-0.89917 0.60461,0.55655 0.46235,-0.45891c0.08228,0.06314 0.14361,0.0464 0.2079,0.04654 0.26598,-0.00002 0.4816,-0.21564 0.48162,-0.48162 -0.00002,-0.26598 -0.21564,-0.4816 -0.48162,-0.48162zM4.82194,2.31149c0.07259,0.00025 0.13129,0.05918 0.13126,0.13177 0.00004,0.07259 -0.05867,0.13153 -0.13126,0.13177C4.74915,2.57507 4.69013,2.51605 4.69016,2.44326 4.69013,2.37047 4.74915,2.31145 4.82194,2.31149Z"
|
||||
android:strokeColor="#00000000" android:strokeWidth="0.19320007"/>
|
||||
<path android:fillColor="#ffffff"
|
||||
android:pathData="M1.01311,0.53415C0.7373,0.54114 0.64785,0.76401 0.64775,1.04575c0.001,0.04943 0.00681,0.09589 0.01705,0.14056H1.19966L1.3304,1.44004 1.67146,0.85558 1.90711,1.18011 2.18409,1.18269C2.1969,1.13774 2.20342,1.09225 2.20321,1.04575 2.20311,0.75953 2.12666,0.53477 1.84045,0.53467 1.54014,0.53762 1.52844,0.67901 1.43272,0.76205 1.34218,0.69058 1.26141,0.53056 1.02654,0.53415c-0.00447,0 -0.00906,-0.00011 -0.01344,0zM2.18409,1.18269c-0.01672,0.05872 -0.04437,0.1163 -0.07958,0.17312l0.48731,-0.00258V1.18631ZM2.10451,1.35581 L1.79652,1.35736 1.67405,1.16874 1.30094,1.73615 1.08287,1.35322H0.72734C0.849,1.5866 1.09816,1.78001 1.39034,2.05809 1.66903,1.81677 1.95772,1.59271 2.10451,1.35581ZM0.72734,1.35322C0.69966,1.30013 0.67827,1.24504 0.66481,1.18631H0.25915v0.16691z"
|
||||
android:strokeColor="#00000000" android:strokeLineCap="square" android:strokeWidth="0.264999"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M14,12l-2,2l-2,-2l2,-2L14,12zM12,6l2.12,2.12l2.5,-2.5L12,1L7.38,5.62l2.5,2.5L12,6zM6,12l2.12,-2.12l-2.5,-2.5L1,12l4.62,4.62l2.5,-2.5L6,12zM18,12l-2.12,2.12l2.5,2.5L23,12l-4.62,-4.62l-2.5,2.5L18,12zM12,18l-2.12,-2.12l-2.5,2.5L12,23l4.62,-4.62l-2.5,-2.5L12,18z"/>
|
||||
</vector>
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@@ -17,22 +19,29 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/track_detail_activity_tablayout"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/track_detail_activity_tablayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/track_recording_coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/StatsScrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/stats_recycler_view"
|
||||
@@ -14,4 +14,4 @@
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@@ -11,15 +13,23 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/track_recording_coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/controller_fragment"
|
||||
android:name="de.dennisguse.opentracks.ControllerFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:ignore="SpUsage">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/splashscreen_background"
|
||||
android:padding="40dp"
|
||||
android:src="@drawable/ic_logo_color_24dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="top"
|
||||
android:layout_margin="20dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:scaleType="fitStart"
|
||||
android:src="@drawable/ic_logo_color_24dp"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical|end"
|
||||
android:text="@string/app_name"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
app:autoSizeTextType="uniform" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="bottom">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share_picture_category"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="CATEGORY" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share_picture_total_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="00:10:10" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share_picture_total_distance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="135km" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share_picture_gain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="214m" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -110,15 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">جارٍ التصدير إلى %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="zero">0 ملفات</item>
|
||||
<item quantity="one">1 ملف</item>
|
||||
<item quantity="two">2 ملفان</item>
|
||||
<item quantity="few">%1$d ملفات</item>
|
||||
<item quantity="many">%1$d ملفًا</item>
|
||||
<item quantity="other">%1$d من الملفات</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">إضافة</string>
|
||||
<string name="generic_delete_selected_confirm_title">حذف ما تم تحديده؟</string>
|
||||
|
||||
@@ -91,10 +91,6 @@
|
||||
<string name="description_total_distance">Total distance: %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Total time: %1$s</string>
|
||||
<string name="export_progress_message">Exporting to %1$s…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 file</item>
|
||||
<item quantity="other">%1$d files</item>
|
||||
</plurals>
|
||||
<string name="generic_add">Add</string>
|
||||
<string name="generic_delete_selected_confirm_title">Delete selected?</string>
|
||||
<string name="generic_description">Description</string>
|
||||
|
||||
@@ -91,10 +91,6 @@
|
||||
<string name="description_total_distance">Distancia total: %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Tiempo total: %1$s</string>
|
||||
<string name="export_progress_message">Exportando a %1$s…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 archivo</item>
|
||||
<item quantity="other">%1$d archivos</item>
|
||||
</plurals>
|
||||
<string name="generic_add">Agregar</string>
|
||||
<string name="generic_delete_selected_confirm_title">¿Eliminar elementos seleccionados?</string>
|
||||
<string name="generic_description">Descripción</string>
|
||||
@@ -104,7 +100,7 @@
|
||||
<string name="generic_paused">En pausa</string>
|
||||
<string name="generic_recording">Grabando…</string>
|
||||
<string name="generic_save">Guardar</string>
|
||||
<string name="generic_tracks">Rutas</string>
|
||||
<string name="generic_tracks">Recorridos</string>
|
||||
<string name="gps_starting">Iniciando GPS</string>
|
||||
<string name="gps_wait_for_better_signal">Esperando una mejor señal de GPS</string>
|
||||
<string name="gps_wait_for_signal">Esperando señal de GPS</string>
|
||||
@@ -145,7 +141,7 @@
|
||||
<string name="menu_show_on_map">Mostrar en el mapa</string>
|
||||
<string name="menu_start_gps">Iniciar GPS</string>
|
||||
<string name="menu_stop_gps">Detener GPS</string>
|
||||
<string name="menu_resume_track">Reanudar ruta</string>
|
||||
<string name="menu_resume_track">Reanudar recorrido</string>
|
||||
<string name="recording_service">Servicio de grabación</string>
|
||||
<string name="sensor_state_battery">Nivel de la batería</string>
|
||||
<string name="sensor_state_cadence">Cadencia</string>
|
||||
@@ -173,9 +169,9 @@
|
||||
<string name="settings_recording_track_name_number_option">Número</string>
|
||||
<string name="settings_recording_track_name_title">Nombre de recorrido predeterminado</string>
|
||||
<string name="settings_reset">Restablecer</string>
|
||||
<string name="settings_reset_confirm_message">Todos los parámetros de configuración se restablecerán a los valores predeterminados.</string>
|
||||
<string name="settings_reset_confirm_message">Todos las configuraciones se restablecerán a los valores predeterminados. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_reset_confirm_title">¿Restablecer ahora?</string>
|
||||
<string name="settings_reset_done">Se restablecieron los valores predeterminados de todas las opciones de configuración</string>
|
||||
<string name="settings_reset_done">Se restablecieron los valores predeterminados de todas las configuraciones</string>
|
||||
<string name="settings_sensor_bluetooth">Bluetooth</string>
|
||||
<string name="settings_stats_rate_title">Tasa preferida</string>
|
||||
<string name="settings_stats_units_imperial">Imperiales (millas, pies)</string>
|
||||
@@ -203,7 +199,7 @@
|
||||
<string name="track_name_format">Recorrido %1$d</string>
|
||||
<string name="track_markers">Marcadores de %1$s</string>
|
||||
<string name="track_delete_one_confirm_message">El recorrido y sus marcadores se eliminarán del dispositivo permanentemente.</string>
|
||||
<string name="track_delete_one_confirm_title">¿Eliminar ruta?</string>
|
||||
<string name="track_delete_one_confirm_title">¿Eliminar recorrido\?</string>
|
||||
<string name="track_delete_multiple_confirm_message">Los recorridos seleccionados y sus respectivos marcadores se eliminarán del dispositivo permanentemente.</string>
|
||||
<string name="track_delete_progress_message">Eliminando…</string>
|
||||
<string name="track_detail_stats_tab">Estadísticas</string>
|
||||
@@ -324,7 +320,7 @@
|
||||
<string name="about_url">Página web del proyecto: <a href="%1$s">%1$s</a></string>
|
||||
<string name="about_version_name">Nombre de la versión: %1$s</string>
|
||||
<string name="bluetooth_disabled">Por favor habilite Bluetooth.</string>
|
||||
<string name="settings_default_trackfileformat">Exportar/compartir formato de archivo</string>
|
||||
<string name="settings_default_trackfileformat">Formato para exportar/compartir</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">Mostrar estadísticas en pantalla de bloqueo</string>
|
||||
<string name="permission_gps_failed">OpenTracks necesita permiso para usar el GPS.</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">Mantener la pantalla encendida</string>
|
||||
@@ -382,9 +378,9 @@
|
||||
<string name="track_distance_notification">Distancia: %1$s</string>
|
||||
<string name="aggregated_stats_empty_message">Grabe su primer recorrido para ver estadísticas agregadas</string>
|
||||
<string name="settings_default_export_uri_title">Directorio de exportación de recorrido</string>
|
||||
<string name="help_track_map_content"> Utilice el icono de mapa pequeño.
|
||||
<string name="help_track_map_content"> Utilice el pequeño icono de mapa.
|
||||
\na) (actualizaciones en vivo) Instale <a href="https://github.com/OpenTracksApp/OSMDashboard"> OSMDashboard </a>. Proporciona mapas en línea o fuera de línea a través de <a href="https://www.openstreetmap.org"> OpenStreetMap </a>.
|
||||
\nEn realidad, OSMDashboard es una aplicación separada que solo puede acceder (temporalmente) a los datos de las pistas que se mostrarán.
|
||||
\nEn realidad, OSMDashboard es una aplicación separada que solo puede acceder (temporalmente) a los datos de los recorridos que se mostrarán.
|
||||
\nb) A través de una aplicación de mapas normal (p. ej., <a href="http://osmand.net/"> OsmAnd </a> y <a href="https://maps.me/"> MAPS.ME </a>). Estas aplicaciones deben admitir el formato de archivo KMZ (solo ubicaciones y marcas de tiempo). De hecho, una aplicación debe admitir <i> ACTION_VIEW </i> con MIME <i> application / vnd.google-earth.kmz</i>. </string>
|
||||
<string name="voice_speed_lap">Velocidad de vuelta de %1$s</string>
|
||||
<string name="voice_pace_lap">Tiempo de vuelta de %1$s</string>
|
||||
@@ -398,12 +394,12 @@
|
||||
\n* crear marcadores (incluidas imágenes)
|
||||
\n* funciona completamente sin conexión
|
||||
\n* mostrar pistas en un mapa (ver más abajo)</string>
|
||||
<string name="help_track_map_title">¿Cómo mostrar un camino en un mapa\?</string>
|
||||
<string name="help_track_map_title">¿Cómo mostrar un recorrido en un mapa\?</string>
|
||||
<string name="help_storage_pictures_title">¿Cómo almacena OpenTracks las imágenes que se tomaron como marcadores\?</string>
|
||||
<string name="help_storage_pictures_content">Estos se almacenan en el almacenamiento interno de la aplicación (es decir, solo se puede acceder a ellos dentro de OpenTracks).</string>
|
||||
<string name="help_track_export_title">¿Cómo puedo exportar / compartir pistas grabadas\?</string>
|
||||
<string name="help_track_export_content"> Las pistas se pueden exportar desde la configuración como KMZ, KML o GPX. KMZ / KML todos los datos; para GPX solo ubicaciones. Las pistas compartidas a través del <i> icono de compartir </i> se comparten como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">¿OpenTracks requiere / usa el servicio Google Play\?</string>
|
||||
<string name="help_track_export_title">¿Cómo puedo exportar/compartir recorridos grabados\?</string>
|
||||
<string name="help_track_export_content"> Los recorridos se pueden exportar desde la configuración como KMZ, KML o GPX. KMZ / KML todos los datos; para GPX solo ubicaciones. Los recorridos compartidos a través del <i> icono de compartir </i> se comparten como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">¿OpenTracks requiere/usa los servicios de Google Play\?</string>
|
||||
<string name="help_recording_title">¿Cómo registra OpenTracks los datos\?</string>
|
||||
<string name="help_recording_content">OpenTracks utiliza el sensor GPS del dispositivo para registrar la ubicación de forma continua. Si el dispositivo GPS informa datos inexactos (por ejemplo, ubicación, velocidad, elevación), OpenTracks no puede hacer nada al respecto.</string>
|
||||
<string name="help_data_storage_title">¿Cómo almacena OpenTracks los datos de los sensores\?</string>
|
||||
@@ -417,7 +413,7 @@
|
||||
<string name="description_default_speed_or_pace">Por tipo de actividad</string>
|
||||
<string name="export_with_photos">con fotos</string>
|
||||
<string name="export_without_photos">sin fotos</string>
|
||||
<string name="export_track_already_exists_msg">La pista %1$s ya existe en el directorio de destino.</string>
|
||||
<string name="export_track_already_exists_msg">El recorrido %1$s ya existe en el directorio de destino.</string>
|
||||
<string name="export_all_do_it_for_all">hacerlo para todos los conflictos</string>
|
||||
<string name="export_track_errors">Recorridos no exportados</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Recorridos sobreescritos</string>
|
||||
@@ -456,9 +452,9 @@
|
||||
<string name="settings_announcements_distance_frequency">Intervalo de distancia</string>
|
||||
<string name="settings_layout_reset">Restablecer pantalla personalizada</string>
|
||||
<string name="settings_announcements">Anuncios</string>
|
||||
<string name="settings_layout_reset_confirm_title">¿Restablecer todas las disposiciones\?</string>
|
||||
<string name="settings_layout_reset_done">Todas las disposiciones se han revertido a los valores por defecto</string>
|
||||
<string name="settings_all_reset">Restablecer todos los ajustes</string>
|
||||
<string name="settings_layout_reset_confirm_title">¿Restablecer todos los diseños\?</string>
|
||||
<string name="settings_layout_reset_done">Todos los diseños se han revertido a los valores predeterminados</string>
|
||||
<string name="settings_all_reset">Restablecer</string>
|
||||
<string name="stats_sensors_heart_rate">Ritmo cardíaco</string>
|
||||
<string name="stats_sensors_cadence">Cadencia</string>
|
||||
<string name="stats_sensors_power">Poder</string>
|
||||
@@ -468,13 +464,73 @@
|
||||
<string name="description_speed_source_gps">GPS</string>
|
||||
<string name="menu_voice_rate">Velocidad de la voz</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<string name="settings_layout_reset_confirm_message">Todos los ajustes de disposición se revertirán a los valores por defecto. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">Correr: Distancia, velocidad y cadencia</string>
|
||||
<string name="settings_layout_reset_confirm_message">Todos los ajustes de diseño se revertirán a los valores predeterminados. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">Distancia, velocidad y cadencia</string>
|
||||
<string name="stats_coordinates">Latitud/Longitud</string>
|
||||
<string name="location_coordinate">%1$s°</string>
|
||||
<string name="title_activity_settings_custom_layout">Personalizar distribución de grabación</string>
|
||||
<string name="title_activity_settings_custom_layout">Personalizar pantalla de grabación</string>
|
||||
<string name="generic_choose_an_option">Selecciona una opción</string>
|
||||
<string name="settings_sensor_cycling_distance_speed">Ciclismo: Distancia y velocidad</string>
|
||||
<string name="settings_sensor_cycling_cadence">Ciclismo: Cadencia</string>
|
||||
<string name="settings_sensor_cycling_distance_speed">Distancia y velocidad</string>
|
||||
<string name="settings_sensor_cycling_cadence">Cadencia</string>
|
||||
<string name="track_delete_not_recording">Este recorrido no puede ser eliminado porque se está grabando actualmente.</string>
|
||||
<string name="settings_defaults_title">Unidades y actividad predeterminadas</string>
|
||||
<string name="export_cannot_write_to_dir">No se puede escribir al directorio de exportación.</string>
|
||||
<string name="export_dir_not_writable">" (¡No se puede escribir!)"</string>
|
||||
<string name="value_float_mile_hour">%1$.1f mi/h</string>
|
||||
<string name="stats_clock">Reloj</string>
|
||||
<string name="generic_filter">Filtrar</string>
|
||||
<string name="menu_select_layout">Seleccionar diseño</string>
|
||||
<string name="settings_import_export_title">Importar/Exportar</string>
|
||||
<string name="settings_announcements_title">Avisos de voz</string>
|
||||
<string name="settings_announcements_summary">Tiempo, Distancia, Velocidad de la voz</string>
|
||||
<string name="settings_import_export_summary">Importar, Exportar, Autoexportar</string>
|
||||
<string name="settings_units_category">Unidades</string>
|
||||
<string name="settings_recording_idle_speed_title">Umbral de velocidad de ralentí</string>
|
||||
<string name="custom_layout_select_layout">Seleccionar diseño</string>
|
||||
<string name="stats_custom_layout_default_layout">Diseño predeterminado</string>
|
||||
<string name="settings_generic_sensor">Genérico</string>
|
||||
<string name="settings_cycling_sensor">Ciclismo</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks requiere permiso para usar Bluetooth.</string>
|
||||
<string name="generic_today">Hoy</string>
|
||||
<string name="generic_yesterday">Ayer</string>
|
||||
<string name="menu_filter">Filtrar</string>
|
||||
<string name="settings_ui_summary">Apariencia, Diseño de grabación, Tema</string>
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_gps_summary">Intervalo de tiempo, Intervalo de distancia, Distancia máxima, Precisión</string>
|
||||
<string name="settings_sensors_title">Sensores Bluetooth</string>
|
||||
<string name="settings_sensors_summary">Sensores de ciclismo, Circunferencia de la rueda, Sensores de carrera</string>
|
||||
<string name="settings_export_section">Exportar</string>
|
||||
<string name="activity_type_swimming">Natación</string>
|
||||
<string name="activity_type_swimming_open">Natación en aguas abiertas</string>
|
||||
<string name="activity_type_workout">Entrenamiento</string>
|
||||
<string name="generic_from">Desde</string>
|
||||
<string name="generic_to">A</string>
|
||||
<string name="settings_defaults_summary">Unidades preferidas, Actividad predeterminada, Nombre predeterminado del recorrido</string>
|
||||
<string name="settings_ui_title">Interfaz de usuario</string>
|
||||
<string name="settings_public_api_disabled_toast">La API pública de OpenTracks está deshabilitada: esta se puede activar en los ajustes.</string>
|
||||
<string name="settings_public_api_enabled_summary_off">Sólo OpenTracks puede iniciar y detener grabaciones.</string>
|
||||
<string name="generic_dismiss">Descartar</string>
|
||||
<string name="gps_recording_status">%1$s: %2$s</string>
|
||||
<string name="gps_recording_without_signal">OpenTracks está grabando sin datos GPS.</string>
|
||||
<string name="menu_add_custom_layout">Nuevo diseño</string>
|
||||
<string name="permission_bluetooth_failed_rejected">Es necesario conceder manualmente a OpenTracks el acceso a los Dispositivos Cercanos en la configuración del sistema.</string>
|
||||
<string name="settings_open_tracks_summary">Todo sobre el proyecto OpenTracks</string>
|
||||
<string name="settings_activity_defaults_category">Prederminados de la actividad</string>
|
||||
<string name="settings_reset_summary">Restablecer a valores predeterminados</string>
|
||||
<string name="custom_layout_list_title">Diseños</string>
|
||||
<string name="custom_layout_list_edit_name">Escriba el nombre del diseño a añadir</string>
|
||||
<string name="custom_layout_list_edit_already_exists">El nombre de este diseño ya existe</string>
|
||||
<string name="custom_layout_list_layout_removed">El diseño fue eliminado</string>
|
||||
<string name="settings_public_api_enabled_title">API pública</string>
|
||||
<string name="settings_public_api_enabled_summary_on">Otras aplicaciones instaladas pueden iniciar o detener grabaciones.</string>
|
||||
<string name="settings_import_section">Importar</string>
|
||||
<string name="aggregated_stats_filter_no_results">No hay actividades para el filtro especificado</string>
|
||||
<string name="value_float_mile_hour_recommended">%1$.1f mi/h (recomendado)</string>
|
||||
<string name="settings_open_tracks_title">Open Tracks</string>
|
||||
<string name="value_float_kilometer_hour">%1$.1f km/h</string>
|
||||
<string name="value_float_kilometer_hour_recommended">%1$.1f km/h (recomendado)</string>
|
||||
<string name="generic_undo">Deshacer</string>
|
||||
<string name="no_compatible_file_manager_installed">No hay un gestor de archivos compatible instalado</string>
|
||||
<string name="settings_running_sensor">Correr</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_enabled">Mostrar sólo los dispositivos Bluetooth que anuncian los servicios requeridos</string>
|
||||
</resources>
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">Експортира се в/ъв %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 файл</item>
|
||||
<item quantity="other">%1$d файла</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Прибавяне</string>
|
||||
<string name="generic_delete_selected_confirm_title">Да се изтрият ли избраните?</string>
|
||||
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">S\'està exportant a %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 fitxer</item>
|
||||
<item quantity="other">%1$d fitxers</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Afegeix</string>
|
||||
<string name="generic_delete_selected_confirm_title">Voleu esborrar els elements seleccionats?</string>
|
||||
|
||||
@@ -159,12 +159,6 @@ limitations under the License.
|
||||
<string name="export_without_photos">bez fotografií</string>
|
||||
<string name="export_progress_message">Exportování do složky %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 soubor</item>
|
||||
<item quantity="few">%1$d soubory</item>
|
||||
<item quantity="other">%1$d souborů</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Přidat</string>
|
||||
<string name="generic_delete_selected_confirm_title">Smazat vybrané?</string>
|
||||
@@ -587,4 +581,5 @@ limitations under the License.
|
||||
<string name="export_cannot_write_to_dir">Nelze zapisovat do adresáře pro export.</string>
|
||||
<string name="export_dir_not_writable">" (nelze zapisovat!)"</string>
|
||||
<string name="generic_today">Dnes</string>
|
||||
<string name="no_compatible_file_manager_installed">Není nainstalován kompatibilní správce souborů</string>
|
||||
</resources>
|
||||
@@ -164,11 +164,6 @@ Hvis GPS-enheden rapporterer unøjagtige data (f.eks. Placering, hastighed, høj
|
||||
<string name="export_without_photos">uden fotos</string>
|
||||
<string name="export_progress_message">Eksporterer til %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 fil</item>
|
||||
<item quantity="other">%1$d filer</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Tilføj</string>
|
||||
<string name="generic_delete_selected_confirm_title">Skal de valgte slettes?</string>
|
||||
@@ -581,4 +576,5 @@ Hvis GPS-enheden rapporterer unøjagtige data (f.eks. Placering, hastighed, høj
|
||||
<string name="custom_layout_list_edit_name">Skriv navnet på det layout, der skal tilføjes</string>
|
||||
<string name="settings_layout_reset_confirm_message">Alle layoutindstillinger vil blive tilbageført til standardværdierne. Dette vil ikke slette spor på enheden.</string>
|
||||
<string name="settings_all_reset">Nulstil</string>
|
||||
<string name="no_compatible_file_manager_installed">Ingen kompatibel filhåndtering installeret</string>
|
||||
</resources>
|
||||
@@ -165,11 +165,6 @@ Meldet das GPS-Gerät ungenaue Daten (z.B. Standort, Geschwindigkeit, Höhe), ka
|
||||
<string name="export_without_photos">ohne Fotos</string>
|
||||
<string name="export_progress_message">In %1$s exportieren…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->=
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 Datei</item>
|
||||
<item quantity="other">%1$d Dateien</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Hinzufügen</string>
|
||||
<string name="generic_delete_selected_confirm_title">Ausgewählte Elemente löschen?</string>
|
||||
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">Εξαγωγή στο %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 αρχείο</item>
|
||||
<item quantity="other">%1$d αρχεία</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Προσθήκη</string>
|
||||
<string name="generic_delete_selected_confirm_title">Διαγραφή επιλεγμένων;</string>
|
||||
|
||||
+238
-234
@@ -15,37 +15,35 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--><resources>
|
||||
<string name="about_preference_title">Acerca de OpenTracks</string>
|
||||
<string name="about_description"><i>OpenTracks</i> es una aplicación de seguimiento deportivo que respeta completamente su privacidad.</string>
|
||||
<string name="about_description"><i> OpenTracks </i> es una aplicación de seguimiento deportivo que respeta completamente su privacidad.</string>
|
||||
<string name="about_url">Página web del proyecto: <a href="%1$s">%1$s</a></string>
|
||||
<string name="about_version_name">Nombre de la versión: %1$s</string>
|
||||
<string name="about_version_code">Código de la versión: %1$d</string>
|
||||
<string name="about_history">OpenTracks es una bifurcación de <a href="https://code.google.com/archive/p/mytracks/"><i>MyTracks </i></a> de Google (descontinuado en 2016).</string>
|
||||
<string name="about_version_code">Código de versión: %1$d</string>
|
||||
<string name="about_history">OpenTracks es una bifurcación de <a href="https://code.google.com/archive/p/mytracks/"> <i> MyTracks de Google </i> </a> (descontinuado en 2016).</string>
|
||||
<string name="about_libraries">Bibliotecas</string>
|
||||
<!-- Help -->
|
||||
<string name="help_feature_title">OpenTracks tiene las siguientes características:</string>
|
||||
<string name="help_feature_content">* crear pistas de GPS
|
||||
\n* utilizar un sensor de frecuencia cardíaca (solo Bluetooth LE)
|
||||
\n* Anuncios de voz (por tiempo o distancia)
|
||||
\n* anuncios de voz (por tiempo o distancia)
|
||||
\n* crear marcadores (incluidas imágenes)
|
||||
\n* funciona completamente sin conexión
|
||||
\n* mostrar pistas en un mapa (ver más abajo)</string>
|
||||
<string name="help_track_map_title">¿Cómo mostrar una pista en un mapa?</string>
|
||||
<string name="help_track_map_content"> Usa el icono del mapa pequeño.
|
||||
\na) (actualizaciones en vivo) Instalar <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>. Proporciona mapas en línea o fuera de línea a través de <a href="https://www.openstreetmap.org">OpenStreetMap</a>.
|
||||
\n En realidad, OSMDashboard es una aplicación independiente que sólo puede acceder (temporalmente) a los datos de las pist(as) que se van a mostrar.
|
||||
\n b) A través de una aplicación de mapas normal (por ejemplo, <a href="http://osmand.net/">OsmAnd</a> y <a href="https://maps.me/">MAPS.ME</a>). Estas aplicaciones necesitan soportar el formato de archivo KMZ (sólo las ubicaciones y las marcas de tiempo). De hecho, una aplicación necesita soportar <i>ACTION_VIEW</i> con MIME <i>application/vnd.google-earth.kmz</i>. </string>
|
||||
<string name="help_storage_pictures_title">¿Cómo almacena OpenTracks las fotos que fueron tomadas como marcadores?</string>
|
||||
<string name="help_storage_pictures_content">Estos se almacenan en el almacenamiento interno de la aplicación (es decir, sólo accesible dentro de OpenTracks).</string>
|
||||
<string name="help_track_export_title">¿Cómo puedo exportar/compartir las pistas grabadas?</string>
|
||||
<string name="help_track_export_content"> Las pistas pueden ser exportadas desde los ajustes como KMZ, KML o GPX. KMZ/KML todos los datos; GPX sólo las ubicaciones. Las pistas compartidas a través del <i> icono de compartir </i> se comparten como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">¿Requiere OpenTracks usar el servicio de Google Play?</string>
|
||||
<string name="help_track_map_title">¿Cómo mostrar un recorrido en un mapa\?</string>
|
||||
<string name="help_track_map_content"> Utilice el pequeño icono de mapa.
|
||||
\na) (actualizaciones en vivo) Instale <a href="https://github.com/OpenTracksApp/OSMDashboard"> OSMDashboard </a>. Proporciona mapas en línea o fuera de línea a través de <a href="https://www.openstreetmap.org"> OpenStreetMap </a>.
|
||||
\nEn realidad, OSMDashboard es una aplicación separada que solo puede acceder (temporalmente) a los datos de los recorridos que se mostrarán.
|
||||
\nb) A través de una aplicación de mapas normal (p. ej., <a href="http://osmand.net/"> OsmAnd </a> y <a href="https://maps.me/"> MAPS.ME </a>). Estas aplicaciones deben admitir el formato de archivo KMZ (solo ubicaciones y marcas de tiempo). De hecho, una aplicación debe admitir <i> ACTION_VIEW </i> con MIME <i> application / vnd.google-earth.kmz</i>. </string>
|
||||
<string name="help_storage_pictures_title">¿Cómo almacena OpenTracks las imágenes que se tomaron como marcadores\?</string>
|
||||
<string name="help_storage_pictures_content">Estos se almacenan en el almacenamiento interno de la aplicación (es decir, solo se puede acceder a ellos dentro de OpenTracks).</string>
|
||||
<string name="help_track_export_title">¿Cómo puedo exportar/compartir recorridos grabados\?</string>
|
||||
<string name="help_track_export_content"> Los recorridos se pueden exportar desde la configuración como KMZ, KML o GPX. KMZ / KML todos los datos; para GPX solo ubicaciones. Los recorridos compartidos a través del <i> icono de compartir </i> se comparten como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">¿OpenTracks requiere/usa los servicios de Google Play\?</string>
|
||||
<string name="help_recording_title">¿Cómo registra OpenTracks los datos?</string>
|
||||
<string name="help_recording_content">
|
||||
OpenTracks utiliza el sensor GPS del dispositivo para registrar la ubicación de forma continua.
|
||||
Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocidad, elevación), OpenTracks no puede hacer nada al respecto.</string>
|
||||
<string name="help_recording_content">OpenTracks utiliza el sensor GPS del dispositivo para registrar la ubicación de forma continua. Si el dispositivo GPS informa datos inexactos (por ejemplo, ubicación, velocidad, elevación), OpenTracks no puede hacer nada al respecto.</string>
|
||||
<string name="help_data_storage_title">¿Cómo almacena OpenTracks los datos de los sensores?</string>
|
||||
<string name="help_data_storage_content"> Los datos de los sensores se almacenan por cada ubicación registrada. En términos de un sensor de frecuencia cardíaca, esto significa que sólo <i>uno</i> la medición de la frecuencia cardíaca se almacena por ubicación. Si está parado o en el interior, no se registrarán los datos del sensor (pero se mostrarán). </string>
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks no está grabando las localizaciones?</string>
|
||||
<string name="help_data_storage_content"> Los datos del sensor se almacenan por ubicación registrada. En términos de sensor de frecuencia cardíaca, esto significa que solo se almacena <i> una </i> medición de frecuencia cardíaca por ubicación. Si está parado o está adentro, no se registrarán los datos del sensor (pero se mostrarán). </string>
|
||||
<string name="help_gps_troubleshooting_title">¿OpenTracks no registra ubicaciones\?</string>
|
||||
<string name="help_gps_troubleshooting_content"> Lo que puedes hacer:
|
||||
\na) compruebe si el GPS está habilitado,
|
||||
\nb) mejorar la recepción del GPS (por ejemplo, salir al aire libre),
|
||||
@@ -53,106 +51,106 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
\nd) desactivar el ahorro de energía.
|
||||
\n
|
||||
\nSi todo no ayuda, informe un error. </string>
|
||||
<string name="help_support_title">¿Cómo puedo apoyar OpenTracks?</string>
|
||||
<string name="help_support_title">¿Cómo puedo ayudar a OpenTracks\?</string>
|
||||
<string name="help_support_content"> Usted puede:
|
||||
\n a) difundir la existencia de OpenTracks,
|
||||
\n b) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">proponer características</a>,
|
||||
\n c) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">reportar errores</a>,
|
||||
\n d) ayudar en el desarrollo del software,
|
||||
\n e) comprar en <a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">Google Play Store</a>,
|
||||
\n f) donar, y
|
||||
\n g) hacer lo que creas que ayuda a OpenTracks. </string>
|
||||
\na) haga correr la voz sobre OpenTracks,
|
||||
\nb) <a href="https://github.com/OpenTracksApp/OpenTracks/issues"> proponer funciones </a>,
|
||||
\nc) <a href="https://github.com/OpenTracksApp/OpenTracks/issues"> informar errores </a>,
|
||||
\nd) ayuda en el desarrollo de software,
|
||||
\ne) comprar en <a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore"> Google Play Store </a>,
|
||||
\nf) donar, y
|
||||
\ng) haga lo que crea que ayuda a OpenTracks. </string>
|
||||
<!-- Activity Type -->
|
||||
<string name="activity_type_airplane">avión</string>
|
||||
<string name="activity_type_atv">vehículos todoterreno</string>
|
||||
<string name="activity_type_atv">vehículos todo terreno</string>
|
||||
<string name="activity_type_biking">ciclismo</string>
|
||||
<string name="activity_type_blimp">dirigible</string>
|
||||
<string name="activity_type_boat">barco</string>
|
||||
<string name="activity_type_climbing">escalada</string>
|
||||
<string name="activity_type_commercial_airplane">avión comercial</string>
|
||||
<string name="activity_type_cross_country_skiing">esquí campo a través</string>
|
||||
<string name="activity_type_boat">embarcación</string>
|
||||
<string name="activity_type_climbing">escalar</string>
|
||||
<string name="activity_type_commercial_airplane">aviones comerciales</string>
|
||||
<string name="activity_type_cross_country_skiing">esquí de fondo</string>
|
||||
<string name="activity_type_cycling">ciclismo</string>
|
||||
<string name="activity_type_dirt_bike">moto de trial</string>
|
||||
<string name="activity_type_dirt_bike">moto enduro</string>
|
||||
<string name="activity_type_donkey_back_riding">paseo en burro</string>
|
||||
<string name="activity_type_driving">conducir</string>
|
||||
<string name="activity_type_driving_bus">ruta en autobús</string>
|
||||
<string name="activity_type_driving_car">ruta en automóvil</string>
|
||||
<string name="activity_type_ferry">balsa</string>
|
||||
<string name="activity_type_frisbee">Friso</string>
|
||||
<string name="activity_type_driving">conducción</string>
|
||||
<string name="activity_type_driving_bus">conducción de autobuses</string>
|
||||
<string name="activity_type_driving_car">conducción de automóviles</string>
|
||||
<string name="activity_type_ferry">transbordador</string>
|
||||
<string name="activity_type_frisbee">frisbee</string>
|
||||
<string name="activity_type_gliding">vuelo sin motor</string>
|
||||
<string name="activity_type_hang_gliding">vuelo en ala delta</string>
|
||||
<string name="activity_type_hang_gliding">aladeltismo</string>
|
||||
<string name="activity_type_helicopter">helicóptero</string>
|
||||
<string name="activity_type_hiking">senderismo</string>
|
||||
<string name="activity_type_horse_back_riding">paseo a caballo</string>
|
||||
<string name="activity_type_hot_air_balloon">globo aerostático</string>
|
||||
<string name="activity_type_ice_sailing">vela sobre hielo</string>
|
||||
<string name="activity_type_ice_sailing">carrera de bólidos en hielo</string>
|
||||
<string name="activity_type_inline_skating">patinaje en línea</string>
|
||||
<string name="activity_type_kayaking">kayak</string>
|
||||
<string name="activity_type_kite_surfing">kitesurf</string>
|
||||
<string name="activity_type_land_sailing">carrovelismo</string>
|
||||
<string name="activity_type_mixed_type">tipo mixto</string>
|
||||
<string name="activity_type_mixed_type">mixta</string>
|
||||
<string name="activity_type_motor_bike">motocicleta</string>
|
||||
<string name="activity_type_motor_boating">navegación a motor</string>
|
||||
<string name="activity_type_motor_boating">embarcaciones a motor</string>
|
||||
<string name="activity_type_mountain_biking">ciclismo de montaña</string>
|
||||
<string name="activity_type_off_trail_hiking">travesía campo a través</string>
|
||||
<string name="activity_type_other">otro</string>
|
||||
<string name="activity_type_paddling">boga</string>
|
||||
<string name="activity_type_off_trail_hiking">senderismo a campo traviesa</string>
|
||||
<string name="activity_type_other">otros</string>
|
||||
<string name="activity_type_paddling">remo</string>
|
||||
<string name="activity_type_para_gliding">parapente</string>
|
||||
<string name="activity_type_rc_airplane">avión teledirigido</string>
|
||||
<string name="activity_type_rc_boat">barco teledirigido</string>
|
||||
<string name="activity_type_rc_helicopter">helicóptero teledirigido</string>
|
||||
<string name="activity_type_rc_airplane">avión a radiocontrol</string>
|
||||
<string name="activity_type_rc_boat">embarcación a radiocontrol</string>
|
||||
<string name="activity_type_rc_helicopter">helicóptero a radiocontrol</string>
|
||||
<string name="activity_type_riding">equitación</string>
|
||||
<string name="activity_type_road_biking">ciclismo de carretera</string>
|
||||
<string name="activity_type_roller_skiing">esquí sobre asfalto (patinaje)</string>
|
||||
<string name="activity_type_road_biking">ciclismo en carretera</string>
|
||||
<string name="activity_type_roller_skiing">esquí sobre asfalto</string>
|
||||
<string name="activity_type_rowing">remo</string>
|
||||
<string name="activity_type_running">carrera</string>
|
||||
<string name="activity_type_sailing">vela</string>
|
||||
<string name="activity_type_running">correr</string>
|
||||
<string name="activity_type_sailing">regata</string>
|
||||
<string name="activity_type_seaplane">hidroavión</string>
|
||||
<string name="activity_type_skate_boarding">ruta en patinete</string>
|
||||
<string name="activity_type_skate_boarding">patineta</string>
|
||||
<string name="activity_type_skating">patinaje</string>
|
||||
<string name="activity_type_skiing">esquí</string>
|
||||
<string name="activity_type_sky_jumping">caída libre controlada</string>
|
||||
<string name="activity_type_sky_jumping">salto de esquí</string>
|
||||
<string name="activity_type_sled">trineo</string>
|
||||
<string name="activity_type_snow_boarding">snowboard</string>
|
||||
<string name="activity_type_snow_shoeing">ruta con raquetas de nieve</string>
|
||||
<string name="activity_type_speed_walking">marcha</string>
|
||||
<string name="activity_type_street_running">millas urbanas</string>
|
||||
<string name="activity_type_snow_shoeing">caminata con raquetas para nieve</string>
|
||||
<string name="activity_type_speed_walking">correcaminata</string>
|
||||
<string name="activity_type_street_running">maratón en carretera</string>
|
||||
<string name="activity_type_surfing">surf</string>
|
||||
<string name="activity_type_track_cycling">ciclismo en pista</string>
|
||||
<string name="activity_type_track_running">carrera a pie en pista</string>
|
||||
<string name="activity_type_trail_hiking">excursionismo</string>
|
||||
<string name="activity_type_trail_running">carrera de montaña</string>
|
||||
<string name="activity_type_track_running">pista de atletismo</string>
|
||||
<string name="activity_type_trail_hiking">senderismo de orientación</string>
|
||||
<string name="activity_type_trail_running">carrera de orientación</string>
|
||||
<string name="activity_type_train">tren</string>
|
||||
<string name="activity_type_ultimate_frisbee">Ultimate Frisbee</string>
|
||||
<string name="activity_type_ultimate_frisbee">ultimate (disco volador)</string>
|
||||
<string name="activity_type_unknown">desconocido</string>
|
||||
<string name="activity_type_wakeboarding">wakeboard</string>
|
||||
<string name="activity_type_walking">recorrido a pie</string>
|
||||
<string name="activity_type_walking">caminata</string>
|
||||
<string name="activity_type_water_skiing">esquí acuático</string>
|
||||
<string name="activity_type_wind_surfing">windsurf</string>
|
||||
<!-- Description -->
|
||||
<string name="description_activity_type">Tipo de actividad: %1$s</string>
|
||||
<string name="description_average_moving_pace_in_minute">Ritmo de movimiento medio: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_moving_speed">Velocidad de movimiento media: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_average_pace_in_minute">Ritmo medio: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_speed">Velocidad media: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_altitude_gain">Aumento de elevación: %1$d m (%2$d ft)</string>
|
||||
<string name="description_average_moving_pace_in_minute">Velocidad promedio de movimiento: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_moving_speed">Velocidad promedio de movimiento: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_average_pace_in_minute">Velocidad promedio: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_speed">Velocidad promedio: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_altitude_gain">Variación de altitud: %1$d m (%2$d pies)</string>
|
||||
<string name="description_altitude_imperial">Elevación (pies)</string>
|
||||
<string name="description_altitude_metric">Elevación (m)</string>
|
||||
<string name="description_fastest_pace_in_minute">Ritmo máximo: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_max_altitude">Elevación máxima: %1$d m (%2$d ft)</string>
|
||||
<string name="description_max_speed">Velocidad máxima: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_min_altitude">Elevación mínima: %1$d m (%2$d ft)</string>
|
||||
<string name="description_moving_time">Tiempo de movimiento: %1$s</string>
|
||||
<string name="description_pace_imperial">Ritmo (min/mi)</string>
|
||||
<string name="description_pace_metric">Ritmo (min/km)</string>
|
||||
<string name="description_recorded_time">Registro: %1$s</string>
|
||||
<string name="description_fastest_pace_in_minute">Velocidad más rápida: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_max_altitude">Elevación máx.: %1$d m (%2$d pies)</string>
|
||||
<string name="description_max_speed">Velocidad máx.: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_min_altitude">Elevación mín.: %1$d m (%2$d pies)</string>
|
||||
<string name="description_moving_time">Tiempo en movimiento: %1$s</string>
|
||||
<string name="description_pace_imperial">Velocidad (min/mi)</string>
|
||||
<string name="description_pace_metric">Velocidad (min/km)</string>
|
||||
<string name="description_recorded_time">Registrado: %1$s</string>
|
||||
<string name="description_speed_ms">Velocidad (m/s)</string>
|
||||
<string name="description_sensor_cadence">Cadencia (rpm)</string>
|
||||
<string name="description_sensor_heart_rate">Frecuencia cardíaca (bpm)</string>
|
||||
<string name="description_sensor_heart_rate">Frecuencia cardíaca (lpm)</string>
|
||||
<string name="description_sensor_power">Potencia (W)</string>
|
||||
<string name="description_default_speed_or_pace">Por la clase de actividad</string>
|
||||
<string name="description_default_speed_or_pace">Por tipo de actividad</string>
|
||||
<string name="description_speed_imperial">Velocidad (mi/h)</string>
|
||||
<string name="description_speed_metric">Velocidad (km / h)</string>
|
||||
<string name="description_speed_metric">Velocidad (km/h)</string>
|
||||
<string name="description_time">Tiempo</string>
|
||||
<string name="description_total_distance">Distancia total: %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Tiempo total: %1$s</string>
|
||||
@@ -161,13 +159,8 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="export_without_photos">sin fotos</string>
|
||||
<string name="export_progress_message">Exportando a %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 archivo</item>
|
||||
<item quantity="other">%1$d archivos</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Añadir</string>
|
||||
<string name="generic_add">Agregar</string>
|
||||
<string name="generic_delete_selected_confirm_title">¿Eliminar elementos seleccionados?</string>
|
||||
<string name="generic_description">Descripción</string>
|
||||
<string name="generic_description_line">Descripción: %1$s</string>
|
||||
@@ -176,7 +169,7 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="generic_paused">En pausa</string>
|
||||
<string name="generic_recording">Grabando…</string>
|
||||
<string name="generic_save">Guardar</string>
|
||||
<string name="generic_tracks">Rutas</string>
|
||||
<string name="generic_tracks">Recorridos</string>
|
||||
<!-- Gps -->
|
||||
<string name="gps_starting">Iniciando GPS</string>
|
||||
<string name="gps_wait_for_better_signal">Esperando una mejor señal de GPS</string>
|
||||
@@ -185,18 +178,18 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="image_arrow">Flecha</string>
|
||||
<string name="image_marker">Marcador</string>
|
||||
<string name="image_marker_count">Recuento de marcadores</string>
|
||||
<string name="image_pause">Pausar</string>
|
||||
<string name="image_pause">Pausa</string>
|
||||
<string name="image_photo_marker">Marcador de foto</string>
|
||||
<string name="image_record">Grabar</string>
|
||||
<string name="image_stop">Detener</string>
|
||||
<string name="image_track">Ruta</string>
|
||||
<string name="image_stop">Parar</string>
|
||||
<string name="image_track">Seguir</string>
|
||||
<!-- Import -->
|
||||
<string name="import_progress_message">Importando desde %1$s…</string>
|
||||
<!-- Marker -->
|
||||
<string name="marker_add_error">No se puede insertar el marcador. No se recibe señal de GPS. Inténtalo de nuevo.</string>
|
||||
<string name="marker_add_success">Se ha insertado un marcador</string>
|
||||
<string name="marker_add_canceled">Cancelado, no se ha añadido ningún marcador</string>
|
||||
<string name="marker_add_photo_canceled">Cancelado, no se ha añadido la foto al marcador</string>
|
||||
<string name="marker_add_error">No se puede insertar un marcador. No se recibe señal de GPS. Vuelve a intentarlo.</string>
|
||||
<string name="marker_add_success">Se insertó un marcador</string>
|
||||
<string name="marker_add_canceled">Cancelado, no se agregó ningún marcador</string>
|
||||
<string name="marker_add_photo_canceled">Cancelado, no se agregó la foto como marcador</string>
|
||||
<string name="marker_delete_one_confirm_message">El marcador se eliminará del dispositivo de forma permanente</string>
|
||||
<string name="marker_delete_one_confirm_title">¿Eliminar marcador?</string>
|
||||
<string name="marker_delete_multiple_confirm_message">Los marcadores seleccionados se eliminarán del dispositivo de forma permanente</string>
|
||||
@@ -204,12 +197,12 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="marker_title">%1$d de %2$d</string>
|
||||
<!-- Marker Detail -->
|
||||
<!-- Marker Edit -->
|
||||
<string name="marker_edit_marker_type">Tipo de marcador (p. ej., cascada…)</string>
|
||||
<string name="marker_edit_marker_type">Tipo de marcador (p. ej., cascada)</string>
|
||||
<string name="marker_edit_marker_type_hint">Tipo de marcador</string>
|
||||
<!-- Marker List -->
|
||||
<string name="marker_list_empty_message">No tienes ningún marcador</string>
|
||||
<!-- Menu -->
|
||||
<string name="menu_aggregated_statistics">Estadísticas globales</string>
|
||||
<string name="menu_aggregated_statistics">Estadíst. globales</string>
|
||||
<string name="menu_delete">Eliminar</string>
|
||||
<string name="menu_edit">Editar</string>
|
||||
<string name="menu_export_all">Exportar todo</string>
|
||||
@@ -221,80 +214,80 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="menu_markers">Marcadores</string>
|
||||
<string name="menu_search">Buscar</string>
|
||||
<string name="menu_select_all">Seleccionar todo</string>
|
||||
<string name="menu_settings">Ajustes</string>
|
||||
<string name="menu_settings">Configuración</string>
|
||||
<string name="menu_share">Compartir</string>
|
||||
<string name="menu_show_on_map">Mostrar en el mapa</string>
|
||||
<string name="menu_start_gps">Iniciar GPS</string>
|
||||
<string name="menu_stop_gps">Detener GPS</string>
|
||||
<string name="menu_resume_track">Reanudar ruta</string>
|
||||
<string name="menu_resume_track">Reanudar recorrido</string>
|
||||
<!-- OpenTracks -->
|
||||
<string name="recording_service">Servicio de grabación</string>
|
||||
<!-- Permission -->
|
||||
<string name="permission_gps_failed">OpenTracks requiere permiso para usar el GPS.</string>
|
||||
<string name="permission_gps_failed">OpenTracks necesita permiso para usar el GPS.</string>
|
||||
<!-- Search -->
|
||||
<!-- Sensor State -->
|
||||
<string name="sensor_state_battery">Nivel de batería</string>
|
||||
<string name="sensor_state_battery">Nivel de la batería</string>
|
||||
<string name="sensor_state_cadence">Cadencia</string>
|
||||
<string name="sensor_state_cadence_value">%1$d rym</string>
|
||||
<string name="sensor_state_cadence_value">%1$d rpm</string>
|
||||
<string name="sensor_state_heart_rate">Frecuencia cardíaca</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d ppm</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d lpm</string>
|
||||
<string name="sensor_state_power">Potencia</string>
|
||||
<string name="sensor_state_power_value">%1$d W</string>
|
||||
<string name="sensor_could_not_scan">No se pudieron buscar dispositivos Bluetooth (error %1$i).</string>
|
||||
<string name="bluetooth_disabled">Por favor, activa el Bluetooth.</string>
|
||||
<string name="settings_not_while_recording">No disponible mientras se graba una ruta</string>
|
||||
<string name="bluetooth_disabled">Por favor habilite Bluetooth.</string>
|
||||
<string name="settings_not_while_recording">No está disponible durante la grabación de un recorrido</string>
|
||||
<string name="settings_show">Mostrar</string>
|
||||
<!-- Settings Advanced -->
|
||||
<string name="settings_advanced">Avanzado</string>
|
||||
<string name="settings_advanced">Opciones avanzadas</string>
|
||||
<!-- Settings Chart -->
|
||||
<string name="settings_chart_by_distance">Por distancia</string>
|
||||
<string name="settings_chart_by_time">Por tiempo</string>
|
||||
<!-- Settings Recording -->
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">Mostrar las estadísticas en la pantalla de bloqueo</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_summary">Mientras graba, muestre las estadísticas sin desbloquear el dispositivo.</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">Mantén la pantalla encendida</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_summary">Mientras graba, mantenga la pantalla encendida.</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">Mostrar estadísticas en pantalla de bloqueo</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_summary">Mientras graba, mostrar estadísticas sin desbloquear el dispositivo.</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">Mantener la pantalla encendida</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_summary">Mientras graba, mantener la pantalla encendida.</string>
|
||||
<string name="settings_recording">Grabación</string>
|
||||
<string name="settings_recording_default_activity_title">Actividad predeterminada</string>
|
||||
<string name="settings_recording_location_frequency_summary">%1$s entre ubicaciones grabadas</string>
|
||||
<string name="settings_recording_max_recording_distance_summary">Esta opción permite crear un nuevo segmento si la distancia entre dos ubicaciones es superior a %1$s</string>
|
||||
<string name="settings_recording_default_activity_title">Tipo de actividad predeterminada</string>
|
||||
<string name="settings_recording_location_frequency_summary">%1$s entre las ubicaciones grabadas</string>
|
||||
<string name="settings_recording_max_recording_distance_summary">Se crea un nuevo tramo si la distancia entre dos ubicaciones es superior a %1$s</string>
|
||||
<string name="settings_recording_max_recording_distance_title">Distancia máxima</string>
|
||||
<string name="settings_recording_min_recording_distance_title">Intervalo de distancia</string>
|
||||
<string name="settings_recording_min_recording_interval_title">Intervalo de tiempo</string>
|
||||
<string name="settings_recording_min_required_accuracy_summary">Esta opción permite ignorar la ubicación si su precisión es inferior a %1$s</string>
|
||||
<string name="settings_recording_min_required_accuracy_title">Exactitud del GPS</string>
|
||||
<string name="settings_recording_min_required_accuracy_summary">La ubicación se ignora si su precisión es inferior a %1$s</string>
|
||||
<string name="settings_recording_min_required_accuracy_title">Precisión del GPS</string>
|
||||
<string name="settings_recording_track_name_date_iso_8601_option">Fecha (ISO 8601)</string>
|
||||
<string name="settings_recording_track_name_date_local_option">Fecha (local)</string>
|
||||
<string name="settings_recording_track_name_number_option">Número</string>
|
||||
<string name="settings_recording_track_name_title">Nombre de la ruta</string>
|
||||
<string name="settings_recording_track_name_title">Nombre de recorrido predeterminado</string>
|
||||
<!-- Settings Reset -->
|
||||
<string name="settings_reset">Restablecer</string>
|
||||
<string name="settings_reset_confirm_message">Todos los ajustes volverán a los valores predeterminados.</string>
|
||||
<string name="settings_reset_confirm_message">Todos las configuraciones se restablecerán a los valores predeterminados. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_reset_confirm_title">¿Restablecer ahora?</string>
|
||||
<string name="settings_reset_done">Se han restablecido los valores predeterminados de todas las opciones de configuración</string>
|
||||
<string name="settings_error_initial_values_restored">Lo siento, pero ha habido un error. Todos los ajustes se han vuelto a los valores predeterminados.</string>
|
||||
<string name="settings_reset_done">Se restablecieron los valores predeterminados de todas las configuraciones</string>
|
||||
<string name="settings_error_initial_values_restored">Lo sentimos, pero ha ocurrido un error. Todas las configuraciones se han revertido a los valores predeterminados.</string>
|
||||
<!-- Settings Sensor -->
|
||||
<string name="settings_sensor_bluetooth">Bluetooth</string>
|
||||
<string name="settings_sensor_connecting">Conectado a %1$s</string>
|
||||
<string name="settings_sensor_disconnected">Desconectado de %1$s</string>
|
||||
<!-- Settings Stats -->
|
||||
<string name="settings_stats_rate_title">Ritmo preferido</string>
|
||||
<string name="settings_stats_units_imperial">Imperial (millas, pies)</string>
|
||||
<string name="settings_stats_units_metric">Métrica (km, m)</string>
|
||||
<string name="settings_stats_rate_title">Tasa preferida</string>
|
||||
<string name="settings_stats_units_imperial">Imperiales (millas, pies)</string>
|
||||
<string name="settings_stats_units_metric">Métricas (km, m)</string>
|
||||
<string name="settings_stats_units_title">Unidades preferidas</string>
|
||||
<!-- Share Track -->
|
||||
<string name="share_track_share_file_body">Creo que esta ruta te podría interesar.
|
||||
<string name="share_track_share_file_body">Creo que este recorrido podría interesarte.
|
||||
\n
|
||||
\n%1$s</string>
|
||||
<string name="share_track_subject">Me gustaría compartir una ruta contigo</string>
|
||||
<string name="share_track_subject">Me gustaría compartir un recorrido contigo</string>
|
||||
<!-- Stats -->
|
||||
<string name="stats_average_moving_pace">Ritmo de movimiento medio</string>
|
||||
<string name="stats_average_moving_speed">Velocidad de movimiento media</string>
|
||||
<string name="stats_average_pace">Ritmo medio</string>
|
||||
<string name="stats_average_speed">Velocidad media</string>
|
||||
<string name="stats_average_moving_pace">Ritmo de movimiento promedio</string>
|
||||
<string name="stats_average_moving_speed">Velocidad de movimiento promedio</string>
|
||||
<string name="stats_average_pace">Ritmo promedio</string>
|
||||
<string name="stats_average_speed">Velocidad promedio</string>
|
||||
<string name="stats_altitude">Elevación</string>
|
||||
<string name="stats_fastest_pace">Ritmo máximo</string>
|
||||
<string name="stats_gain">Ganancia</string>
|
||||
<string name="stats_fastest_pace">Ritmo más rápido</string>
|
||||
<string name="stats_gain">Aumento</string>
|
||||
<string name="stats_latitude">Latitud</string>
|
||||
<string name="stats_longitude">Longitud</string>
|
||||
<string name="stats_max_speed">Velocidad máxima</string>
|
||||
@@ -304,30 +297,30 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="stats_distance">Distancia</string>
|
||||
<string name="stats_total_time">Tiempo total</string>
|
||||
<!-- Track -->
|
||||
<string name="track_name_format">Ruta %1$d</string>
|
||||
<string name="track_recording_notification_accuracy">Precisión de la localización: %1$s</string>
|
||||
<string name="track_name_format">Recorrido %1$d</string>
|
||||
<string name="track_recording_notification_accuracy">Precisión de ubicación: %1$s</string>
|
||||
<string name="track_markers">Marcadores de %1$s</string>
|
||||
<!-- Track Delete -->
|
||||
<string name="track_delete_one_confirm_message">La ruta y sus marcadores se eliminarán de forma permanente del dispositivo.</string>
|
||||
<string name="track_delete_one_confirm_title">¿Eliminar ruta?</string>
|
||||
<string name="track_delete_multiple_confirm_message">Las rutas seleccionadas y sus marcadores se eliminarán de forma permanente del dispositivo.</string>
|
||||
<string name="track_delete_one_confirm_message">El recorrido y sus marcadores se eliminarán del dispositivo permanentemente.</string>
|
||||
<string name="track_delete_one_confirm_title">¿Eliminar recorrido\?</string>
|
||||
<string name="track_delete_multiple_confirm_message">Los recorridos seleccionados y sus respectivos marcadores se eliminarán del dispositivo permanentemente.</string>
|
||||
<string name="track_delete_progress_message">Eliminando…</string>
|
||||
<!-- Track Detail -->
|
||||
<string name="track_detail_stats_tab">Estadísticas</string>
|
||||
<!-- Track Edit -->
|
||||
<string name="track_edit_activity_type">Tipo de actividad (p. ej., senderismo…)</string>
|
||||
<string name="track_edit_activity_type">Tipo de actividad (p. ej., senderismo)</string>
|
||||
<string name="track_edit_activity_type_hint">Tipo de actividad</string>
|
||||
<!-- Track List -->
|
||||
<string name="track_list_empty_message">Empieza a grabar aquí tu próxima aventura</string>
|
||||
<string name="track_list_empty_message">Comienza a grabar aquí tu próxima aventura</string>
|
||||
<!-- Track Widget -->
|
||||
<!-- Tracks -->
|
||||
<!-- Unit -->
|
||||
<string name="unit_feet">pies</string>
|
||||
<string name="unit_feet">pie</string>
|
||||
<string name="unit_kilometer">km</string>
|
||||
<string name="unit_kilometer_per_hour">km/h</string>
|
||||
<string name="unit_meter">m</string>
|
||||
<string name="unit_mile">millas</string>
|
||||
<string name="unit_mile_per_hour">mph</string>
|
||||
<string name="unit_mile_per_hour">millas/hora</string>
|
||||
<string name="unit_minute_per_kilometer">min/km</string>
|
||||
<string name="unit_minute_per_mile">min/milla</string>
|
||||
<!-- Value -->
|
||||
@@ -338,14 +331,14 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="value_integer_kilometer_hour">%1$d km/h</string>
|
||||
<string name="value_integer_meter">%1$d m</string>
|
||||
<string name="value_integer_meter_excellent_gps">%1$d m (señal de GPS excelente)</string>
|
||||
<string name="value_integer_meter_poor_gps">%1$d m (señal de GPS débil)</string>
|
||||
<string name="value_integer_meter_poor_gps">%1$d m (señal de GPS deficiente)</string>
|
||||
<string name="value_integer_meter_recommended">%1$d m (recomendado)</string>
|
||||
<string name="value_integer_mile">%1$d millas</string>
|
||||
<string name="value_integer_mile_hour">%1$d mi/h</string>
|
||||
<string name="value_integer_minute">%1$d min</string>
|
||||
<string name="value_integer_minute">%1$d mín</string>
|
||||
<string name="value_integer_second">%1$d s</string>
|
||||
<string name="value_none">Ninguna</string>
|
||||
<string name="value_off">No</string>
|
||||
<string name="value_none">Ninguno</string>
|
||||
<string name="value_off">Desactivado</string>
|
||||
<string name="value_smallest_recommended">Mínimo (recomendado)</string>
|
||||
<!-- Voice -->
|
||||
<plurals name="voiceHours">
|
||||
@@ -382,22 +375,22 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<!-- Waypoint Type -->
|
||||
<string name="waypoint_type_atm">cajero automático</string>
|
||||
<string name="waypoint_type_bank">banco</string>
|
||||
<string name="waypoint_type_bar">bar</string>
|
||||
<string name="waypoint_type_bar">barra</string>
|
||||
<string name="waypoint_type_barbecue">barbacoa</string>
|
||||
<string name="waypoint_type_building">edificio</string>
|
||||
<string name="waypoint_type_bus_stop">parada de autobús</string>
|
||||
<string name="waypoint_type_cafe">cafetería</string>
|
||||
<string name="waypoint_type_campfire">hoguera</string>
|
||||
<string name="waypoint_type_campground">camping</string>
|
||||
<string name="waypoint_type_campfire">hoguera de campamento</string>
|
||||
<string name="waypoint_type_campground">zona de camping</string>
|
||||
<string name="waypoint_type_church">iglesia</string>
|
||||
<string name="waypoint_type_coffee_house">cafetería</string>
|
||||
<string name="waypoint_type_convenience_store">tienda de barrio</string>
|
||||
<string name="waypoint_type_convenience_store">minimercado</string>
|
||||
<string name="waypoint_type_drinking_water">agua potable</string>
|
||||
<string name="waypoint_type_falling_rocks">desprendimiento de rocas</string>
|
||||
<string name="waypoint_type_ferry">barco</string>
|
||||
<string name="waypoint_type_fire_place">chimenea</string>
|
||||
<string name="waypoint_type_fire_station">parque de bomberos</string>
|
||||
<string name="waypoint_type_fishing">enclave pesquero</string>
|
||||
<string name="waypoint_type_ferry">transbordador</string>
|
||||
<string name="waypoint_type_fire_place">hogar</string>
|
||||
<string name="waypoint_type_fire_station">cuartel de bomberos</string>
|
||||
<string name="waypoint_type_fishing">pesca</string>
|
||||
<string name="waypoint_type_gas_station">gasolinera</string>
|
||||
<string name="waypoint_type_golf_course">campo de golf</string>
|
||||
<string name="waypoint_type_grocery_store">supermercado</string>
|
||||
@@ -408,108 +401,108 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="waypoint_type_house">casa</string>
|
||||
<string name="waypoint_type_information">información</string>
|
||||
<string name="waypoint_type_intersection">intersección</string>
|
||||
<string name="waypoint_type_mail_box">buzón de correos</string>
|
||||
<string name="waypoint_type_mail_box">buzón de correo</string>
|
||||
<string name="waypoint_type_market">mercado</string>
|
||||
<string name="waypoint_type_meeting_point">punto de encuentro</string>
|
||||
<string name="waypoint_type_opera">ópera</string>
|
||||
<string name="waypoint_type_parking">aparcamiento</string>
|
||||
<string name="waypoint_type_police_station">comisaría de policía</string>
|
||||
<string name="waypoint_type_post_office">oficina de correos</string>
|
||||
<string name="waypoint_type_pothole">socavón</string>
|
||||
<string name="waypoint_type_railway_crossing">paso a nivel</string>
|
||||
<string name="waypoint_type_parking">estacionamiento</string>
|
||||
<string name="waypoint_type_police_station">comisaría</string>
|
||||
<string name="waypoint_type_post_office">oficina postal</string>
|
||||
<string name="waypoint_type_pothole">bache</string>
|
||||
<string name="waypoint_type_railway_crossing">cruce ferroviario</string>
|
||||
<string name="waypoint_type_restaurant">restaurante</string>
|
||||
<string name="waypoint_type_shopping">comercio</string>
|
||||
<string name="waypoint_type_shopping">centro comercial</string>
|
||||
<string name="waypoint_type_sight">vista</string>
|
||||
<string name="waypoint_type_store">tienda</string>
|
||||
<string name="waypoint_type_swimming_pool">piscina</string>
|
||||
<string name="waypoint_type_telephone">teléfono</string>
|
||||
<string name="waypoint_type_theater">teatro</string>
|
||||
<string name="waypoint_type_toilet">aseo</string>
|
||||
<string name="waypoint_type_toilet">baño</string>
|
||||
<string name="waypoint_type_tourist_information">información turística</string>
|
||||
<string name="waypoint_type_tree">árbol</string>
|
||||
<string name="waypoint_type_tunnel">túnel</string>
|
||||
<string name="waypoint_type_waterfall">cascada</string>
|
||||
<string name="waypoint_type_water_fountain">fuente de agua</string>
|
||||
<string name="waypoint_type_waypoint">Punto de ruta</string>
|
||||
<string name="waypoint_type_waypoint">punto de referencia</string>
|
||||
<!-- Share image -->
|
||||
<string name="share_image_subject">Me gustaría compartir una imagen contigo</string>
|
||||
<string name="share_image_body">Creo que esta imagen te podría interesar.</string>
|
||||
<string name="share_image_body">Creo que esta imagen podría interesarte.</string>
|
||||
<string name="open_track_as_KML">Abrir como KML</string>
|
||||
<string name="open_track_as_GPX">Abrir como GPX</string>
|
||||
<string name="open_track_as_trackfileformat">Abrir como %1$s</string>
|
||||
<string name="activity_type_escooter">escúter</string>
|
||||
<string name="export_all_do_it_for_all">aplicar en todos los conflictos</string>
|
||||
<string name="export_track_errors">Pistas no exportadas</string>
|
||||
<string name="generic_skip">Ignorar</string>
|
||||
<string name="activity_type_escooter">moto</string>
|
||||
<string name="export_all_do_it_for_all">hacerlo para todos los conflictos</string>
|
||||
<string name="export_track_errors">Recorridos no exportados</string>
|
||||
<string name="generic_skip">Saltear</string>
|
||||
<string name="generic_separator_done_total">/</string>
|
||||
<string name="generic_show_errors">Ver Errores</string>
|
||||
<string name="generic_show_errors">Mostrar errores</string>
|
||||
<plurals name="generic_completed_with_errors">
|
||||
<item quantity="one">Terminado con un error</item>
|
||||
<item quantity="other">Terminado con %1$d errores</item>
|
||||
<item quantity="one">Completado con un error</item>
|
||||
<item quantity="other">Completado con %1$d errores</item>
|
||||
</plurals>
|
||||
<string name="generic_completed">Terminado</string>
|
||||
<string name="import_error_list_dialog_title">Ficheros no importados</string>
|
||||
<string name="import_file_imported">Fichero %1$s importado</string>
|
||||
<string name="generic_completed">Completado</string>
|
||||
<string name="import_error_list_dialog_title">Archivos no importados</string>
|
||||
<string name="import_file_imported">Archivo %1$s importado</string>
|
||||
<string name="import_error_info">%1$s: %2$s</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Pantalla completa durante la grabación.</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Mientras graba, presentar en pantalla completa.</string>
|
||||
<string name="settings_night_mode_option_system">Sistema</string>
|
||||
<string name="settings_night_mode_option_day">Claro</string>
|
||||
<string name="settings_night_mode_option_night">Oscuro</string>
|
||||
<string name="settings_night_mode_title">Elegir un tema</string>
|
||||
<string name="settings_night_mode_option_day">Día</string>
|
||||
<string name="settings_night_mode_option_night">Noche</string>
|
||||
<string name="settings_night_mode_title">Tema de interfaz de usuario</string>
|
||||
<string name="settings_sensor_wheel_circumference">Circunferencia de la rueda (mm)</string>
|
||||
<string name="stats_split_interval">Intervalo</string>
|
||||
<string name="stats_split_interval">Intervalo partido</string>
|
||||
<string name="track_detail_intervals_tab">Intervalos</string>
|
||||
<string name="aggregated_stats_empty_message">Graba tu primera pista para ver estadísticas agregadas</string>
|
||||
<string name="voice_pace_lap">Tiempo de la vuelta %1$s</string>
|
||||
<string name="hold_to_pause">Mantener en pausa</string>
|
||||
<string name="instant_export_enabled_title">Exportación automática tras grabación</string>
|
||||
<string name="settings_default_export_uri_title">Carpeta de pistas exportadas</string>
|
||||
<string name="export_track_already_exists_msg">La pista %1$s ya existe en la carpeta de destino.</string>
|
||||
<string name="generic_overwrite">Sobreescribe</string>
|
||||
<string name="generic_click_twice_cancel">Clic otra vez para cancelar</string>
|
||||
<string name="gps_disabled_msg">GPS desactivado</string>
|
||||
<string name="gps_fixed_and_ready">GPS fijado y listo</string>
|
||||
<string name="import_unsupported_format">Formato no soportado</string>
|
||||
<string name="import_parser_error">Error al analizar: %1$s</string>
|
||||
<string name="import_unable_to_import_file">No se ha podido importar el fichero: %1$s</string>
|
||||
<string name="aggregated_stats_empty_message">Grabe su primer recorrido para ver estadísticas agregadas</string>
|
||||
<string name="voice_pace_lap">Tiempo de vuelta de %1$s</string>
|
||||
<string name="hold_to_pause">Mantener para pausar</string>
|
||||
<string name="instant_export_enabled_title">Exportación instantánea post-entrenamiento</string>
|
||||
<string name="settings_default_export_uri_title">Directorio de exportación de recorrido</string>
|
||||
<string name="export_track_already_exists_msg">El recorrido %1$s ya existe en el directorio de destino.</string>
|
||||
<string name="generic_overwrite">Sobreescribir</string>
|
||||
<string name="generic_click_twice_cancel">Haga nuevamente clic en atrás para cancelar</string>
|
||||
<string name="gps_disabled_msg">GPS deshabilitado</string>
|
||||
<string name="gps_fixed_and_ready">GPS establecido y listo</string>
|
||||
<string name="import_unsupported_format">Formato de archivo no soportado</string>
|
||||
<string name="import_parser_error">Error de parseo: %1$s</string>
|
||||
<string name="import_unable_to_import_file">No se puede importar el archivo: %1$s</string>
|
||||
<string name="settings_default_trackfileformat">Formato para exportar/compartir</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_title">Pantalla completa</string>
|
||||
<string name="interval_list_empty_message">No hay intervalos todavía</string>
|
||||
<string name="voice_speed_lap">Velocidad de la vuelta %1$s</string>
|
||||
<string name="interval_list_empty_message">Aún no hay ningún intervalo</string>
|
||||
<string name="voice_speed_lap">Velocidad de vuelta de %1$s</string>
|
||||
<string name="hold_to_stop">Mantener para parar</string>
|
||||
<string name="instant_export_enabled_summary">Exportar pista después de terminar la grabación</string>
|
||||
<string name="instant_export_enabled_summary">Exportar el recorrido al almacenamiento una vez finalizada la grabación</string>
|
||||
<string name="stats_loss">Pérdida</string>
|
||||
<string name="settings_prevent_reimport_tracks_title">Impedir la reimportación de pistas</string>
|
||||
<string name="sensor_state_power_avg">Potencia media</string>
|
||||
<string name="sensor_state_heart_rate_max">Frecuencia cardíaca máxima</string>
|
||||
<string name="sensor_state_heart_rate_avg">Ritmo cardíaco medio</string>
|
||||
<string name="export_error_post_workout">La exportación de post-entrenamiento ha fallado, por favor compruebe el directorio de exportación.</string>
|
||||
<string name="export_progress_summary_new_msg">Nuevas pistas exportadas</string>
|
||||
<string name="settings_prevent_reimport_tracks_title">Evitar reimportar los recorridos</string>
|
||||
<string name="sensor_state_power_avg">Potencia promedio</string>
|
||||
<string name="sensor_state_heart_rate_max">Tasa cardíaca máxima</string>
|
||||
<string name="sensor_state_heart_rate_avg">Tasa cardíaca promedio</string>
|
||||
<string name="export_error_post_workout">La exportación posterior al entrenamiento falló, consulte el directorio de exportación.</string>
|
||||
<string name="export_progress_summary_new_msg">Nuevos recorridos exportados</string>
|
||||
<string name="import_thread_interrupted">Hilo interrumpido</string>
|
||||
<string name="import_progress_summary_errors_msg">Errores</string>
|
||||
<string name="import_progress_summary_ok_msg">Archivos importados</string>
|
||||
<string name="description_altitude_loss">Pérdida de altura: %1$d m (%2$d pies)</string>
|
||||
<string name="sensor_state_cadence_max">Cadencia máxima</string>
|
||||
<string name="sensor_state_cadence_avg">Cadencia media</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Pistas sobrescritas</string>
|
||||
<string name="export_progress_summary_skip_msg">Pistas omitidas</string>
|
||||
<string name="description_altitude_loss">Pérdida de elevación: %1$d m (%2$d pies)</string>
|
||||
<string name="sensor_state_cadence_max">Ritmo máximo</string>
|
||||
<string name="sensor_state_cadence_avg">Ritmo promedio</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Recorridos sobreescritos</string>
|
||||
<string name="export_progress_summary_skip_msg">Recorridos salteados</string>
|
||||
<string name="export_progress_summary_errors_msg">Errores</string>
|
||||
<string name="generic_open_track">Pista abierta</string>
|
||||
<string name="import_progress_summary_exists_msg">Ya existen</string>
|
||||
<string name="generic_open_track">Abrir recorrido</string>
|
||||
<string name="import_progress_summary_exists_msg">Ya existe</string>
|
||||
<string name="import_no_kml_file_found">No se ha encontrado ningún archivo doc.kml en KMZ</string>
|
||||
<string name="import_prevent_reimport">Ha establecido impedir la reimportación de la pista</string>
|
||||
<string name="import_prevent_reimport">Ha configurado evitar la reimportación del recorrido</string>
|
||||
<string name="track_distance_notification">Distancia: %1$s</string>
|
||||
<string name="track_speed_notification">Velocidad: %1$s</string>
|
||||
<string name="track_pace_notification">Ritmo: %1$s</string>
|
||||
<string name="about_third_party_data">Datos de terceros</string>
|
||||
<string name="delete_service">Servicio de borrado</string>
|
||||
<string name="delete_service">Borrar servicio</string>
|
||||
<string name="track_delete_progress">%1$d/%2$d</string>
|
||||
<string name="menu_voice_rate">Velocidad de voz</string>
|
||||
<string name="track_delete_not_recording">Esta pista no se puede borrar, ya que está grabada.</string>
|
||||
<string name="menu_voice_rate">Velocidad de la voz</string>
|
||||
<string name="track_delete_not_recording">Este recorrido no puede ser eliminado porque se está grabando actualmente.</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">Distancia, velocidad y cadencia</string>
|
||||
<string name="settings_sensor_cycling_distance_speed">Distancia y velocidad</string>
|
||||
<string name="settings_sensor_cycling_cadence">Cadencia</string>
|
||||
<string name="settings_announcements">Avisos</string>
|
||||
<string name="settings_announcements">Anuncios</string>
|
||||
<string name="settings_announcements_totaltime_frequency">Intervalo de tiempo</string>
|
||||
<string name="settings_announcements_distance_frequency">Intervalo de distancia</string>
|
||||
<string name="stats_sensors_heart_rate">Ritmo cardíaco</string>
|
||||
@@ -517,19 +510,19 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="stats_sensors_power">Poder</string>
|
||||
<string name="field_set_primary">Primario</string>
|
||||
<string name="description_speed_source_gps">GPS</string>
|
||||
<string name="settings_recording_customize_layout_title">Personalizar la pantalla de grabación</string>
|
||||
<string name="settings_recording_customize_layout_title">Personalice su pantalla de grabación</string>
|
||||
<string name="settings_recording_customize_layout_select_columns">Datos por columna</string>
|
||||
<string name="settings_layout_reset_confirm_message">Todas los ajustes de distribución se revertirán a los valores por defecto. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_layout_reset_confirm_title">¿Restablecer todas las disposiciones\?</string>
|
||||
<string name="settings_layout_reset_done">Todos los ajustes de disposición se han revertido a los valores por defecto</string>
|
||||
<string name="settings_all_reset">Reiniciar</string>
|
||||
<string name="settings_layout_reset_confirm_message">Todos los ajustes de diseño se revertirán a los valores predeterminados. Esto no eliminará ningún recorrido en el dispositivo.</string>
|
||||
<string name="settings_layout_reset_confirm_title">¿Restablecer todos los diseños\?</string>
|
||||
<string name="settings_layout_reset_done">Todos los diseños se han revertido a los valores predeterminados</string>
|
||||
<string name="settings_all_reset">Restablecer</string>
|
||||
<string name="location_coordinate">%1$s°</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<string name="field_remove_from_layout">Remover</string>
|
||||
<string name="generic_choose_an_option">Seleccione una opción</string>
|
||||
<string name="settings_layout_reset">Restabecer pantalla personalizada</string>
|
||||
<string name="generic_choose_an_option">Selecciona una opción</string>
|
||||
<string name="settings_layout_reset">Restablecer pantalla personalizada</string>
|
||||
<string name="stats_coordinates">Latitud/Longitud</string>
|
||||
<string name="title_activity_settings_custom_layout">Personalizar la pantalla de grabación</string>
|
||||
<string name="title_activity_settings_custom_layout">Personalizar pantalla de grabación</string>
|
||||
<string name="field_set_secondary">Secundario</string>
|
||||
<string name="value_float_kilometer_hour">%1$.1f km/h</string>
|
||||
<string name="value_float_mile_hour">%1$.1f mi/h</string>
|
||||
@@ -539,14 +532,14 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="value_float_kilometer_hour_recommended">%1$.1f km/h (recomendado)</string>
|
||||
<string name="settings_generic_sensor">Genérico</string>
|
||||
<string name="settings_cycling_sensor">Ciclismo</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks requiere un permiso para utilizar el Bluetooth.</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks requiere permiso para usar Bluetooth.</string>
|
||||
<string name="permission_bluetooth_failed_rejected">Es necesario conceder manualmente a OpenTracks el acceso a los Dispositivos Cercanos en la configuración del sistema.</string>
|
||||
<string name="settings_running_sensor">Corriendo</string>
|
||||
<string name="settings_running_sensor">Correr</string>
|
||||
<string name="settings_import_section">Importar</string>
|
||||
<string name="settings_export_section">Exportar</string>
|
||||
<string name="generic_today">Hoy</string>
|
||||
<string name="generic_yesterday">Ayer</string>
|
||||
<string name="menu_add_custom_layout">Nueva disposición</string>
|
||||
<string name="menu_add_custom_layout">Nuevo diseño</string>
|
||||
<string name="settings_sensors_summary">Sensores de ciclismo, Circunferencia de la rueda, Sensores de carrera</string>
|
||||
<string name="settings_sensors_title">Sensores Bluetooth</string>
|
||||
<string name="settings_gps_summary">Intervalo de tiempo, Intervalo de distancia, Distancia máxima, Precisión</string>
|
||||
@@ -555,29 +548,40 @@ Si el dispositivo GPS reporta datos inexactos (por ejemplo, ubicación, velocida
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_announcements_title">Avisos de voz</string>
|
||||
<string name="settings_units_category">Unidades</string>
|
||||
<string name="settings_import_export_title">Importación/exportación</string>
|
||||
<string name="stats_custom_layout_default_layout">Diseño por defecto</string>
|
||||
<string name="custom_layout_select_layout">Seleccione el diseño</string>
|
||||
<string name="custom_layout_list_edit_already_exists">El nombre del diseño ya existe</string>
|
||||
<string name="export_cannot_write_to_dir">No se puede escribir en el directorio de exportación.</string>
|
||||
<string name="settings_import_export_summary">Importar, exportar, autoexportar</string>
|
||||
<string name="settings_import_export_title">Importar/Exportar</string>
|
||||
<string name="stats_custom_layout_default_layout">Diseño predeterminado</string>
|
||||
<string name="custom_layout_select_layout">Seleccionar diseño</string>
|
||||
<string name="custom_layout_list_edit_already_exists">El nombre de este diseño ya existe</string>
|
||||
<string name="export_cannot_write_to_dir">No se puede escribir al directorio de exportación.</string>
|
||||
<string name="settings_import_export_summary">Importar, Exportar, Autoexportar</string>
|
||||
<string name="generic_from">Desde</string>
|
||||
<string name="generic_filter">Filtro</string>
|
||||
<string name="generic_filter">Filtrar</string>
|
||||
<string name="generic_to">A</string>
|
||||
<string name="menu_select_layout">Seleccionar diseño</string>
|
||||
<string name="menu_filter">Filtro</string>
|
||||
<string name="custom_layout_list_edit_name">Escriba el nombre del diseño para añadirlo</string>
|
||||
<string name="menu_filter">Filtrar</string>
|
||||
<string name="custom_layout_list_edit_name">Escriba el nombre del diseño a añadir</string>
|
||||
<string name="custom_layout_list_title">Diseños</string>
|
||||
<string name="export_dir_not_writable">" (¡no se puede escribir!)"</string>
|
||||
<string name="export_dir_not_writable">" (¡No se puede escribir!)"</string>
|
||||
<string name="aggregated_stats_filter_no_results">No hay actividades para el filtro especificado</string>
|
||||
<string name="custom_layout_list_layout_removed">El diseño fue eliminado</string>
|
||||
<string name="settings_reset_summary">Restablecer los valores por defecto</string>
|
||||
<string name="settings_activity_defaults_category">Actividad por defecto</string>
|
||||
<string name="settings_announcements_summary">Tiempo, distancia, velocidad de la voz</string>
|
||||
<string name="settings_reset_summary">Restablecer a valores predeterminados</string>
|
||||
<string name="settings_activity_defaults_category">Prederminados de la actividad</string>
|
||||
<string name="settings_announcements_summary">Tiempo, Distancia, Velocidad de la voz</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_enabled">Mostrar sólo los dispositivos Bluetooth que anuncian los servicios requeridos</string>
|
||||
<string name="settings_open_tracks_summary">Todo sobre el proyecto OpenTracks</string>
|
||||
<string name="settings_defaults_title">Unidades y actividad por defecto</string>
|
||||
<string name="settings_defaults_summary">Unidades preferidas, actividad por defecto, nombre por defecto de la pista</string>
|
||||
<string name="settings_open_tracks_title">Vías abiertas</string>
|
||||
<string name="settings_defaults_title">Unidades y actividad predeterminadas</string>
|
||||
<string name="settings_defaults_summary">Unidades preferidas, Actividad predeterminada, Nombre predeterminado del recorrido</string>
|
||||
<string name="settings_open_tracks_title">Open Tracks</string>
|
||||
<string name="generic_undo">Deshacer</string>
|
||||
<string name="no_compatible_file_manager_installed">No hay un gestor de archivos compatible instalado</string>
|
||||
<string name="settings_public_api_disabled_toast">La API pública de OpenTracks está deshabilitada: esta se puede activar en los ajustes.</string>
|
||||
<string name="activity_type_swimming">Natación</string>
|
||||
<string name="activity_type_swimming_open">Natación en aguas abiertas</string>
|
||||
<string name="activity_type_workout">Entrenamiento</string>
|
||||
<string name="settings_public_api_enabled_title">API pública</string>
|
||||
<string name="settings_public_api_enabled_summary_on">Otras aplicaciones instaladas pueden iniciar o detener grabaciones.</string>
|
||||
<string name="settings_public_api_enabled_summary_off">Sólo OpenTracks puede iniciar y detener grabaciones.</string>
|
||||
<string name="generic_dismiss">Descartar</string>
|
||||
<string name="gps_recording_status">%1$s: %2$s</string>
|
||||
<string name="gps_recording_without_signal">OpenTracks está grabando sin datos GPS.</string>
|
||||
</resources>
|
||||
+118
-124
@@ -14,95 +14,93 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--><resources>
|
||||
<string name="about_preference_title">Umbes OpenTracks</string>
|
||||
<string name="about_description"><i>OpenTracks</i> on spordi jälgimise rakendus, mis austab täielikult teie privaatsust.</string>
|
||||
<string name="about_preference_title">Teave OpenTracks\'i kohta</string>
|
||||
<string name="about_description"><i>OpenTracks</i> on spordi jälgimise rakendus, mis austab teie privaatsust.</string>
|
||||
<string name="about_url">Projekti veebileht: <a href="%1$s">%1$s</a></string>
|
||||
<string name="about_version_name">Versiooni nimi: %1$s</string>
|
||||
<string name="about_version_code">Versiooni kood: %1$d</string>
|
||||
<string name="about_history">OpenTracks on <a href="https://code.google.com/archive/p/mytracks/"> <i> Googlei MyTracks </i> </a> kahvel (lõpetatud 2016. aastal).</string>
|
||||
<string name="about_libraries">Raamatukogud</string>
|
||||
<string name="about_history">OpenTracks on <a href="https://code.google.com/archive/p/mytracks/"> <i>Google\'i MyTracks</i> </a> haru (seisatud 2016. aastal).</string>
|
||||
<string name="about_libraries">Teegid</string>
|
||||
<!-- Help -->
|
||||
<string name="help_feature_title">OpenTracks sellel on järgmised omadused:</string>
|
||||
<string name="help_feature_content">* loo GPS rajad
|
||||
\n* kasutage südame löögisageduse andurit ( ainult Bluetooth LE)
|
||||
<string name="help_feature_title">OpenTracks\'il on järgmised funktsioonid:</string>
|
||||
<string name="help_feature_content">* loo GPS radu
|
||||
\n* kasutage pulsi andurit (ainult Bluetooth LE)
|
||||
\n* häälteated (aja või vahemaa järgi)
|
||||
\n* loo markerid (sh. digikuvat)
|
||||
\n* töötab täiesti offline
|
||||
\n* näita lugusid kaardil (vt allpool)</string>
|
||||
<string name="help_track_map_title">Kuidas näidata pala kaardil?</string>
|
||||
\n* loo asukohapunkte (koos piltidega)
|
||||
\n* töötab ilma internetiühenduseta
|
||||
\n* näita radu kaardil (vt allapoole)</string>
|
||||
<string name="help_track_map_title">Kuidas näidata rada kaardil\?</string>
|
||||
<string name="help_track_map_content"> Kasutage väikest kaardisümbolit.
|
||||
\n a) (reaalajas uuendused) Installige <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>. See pakub online või offline-kaarte <a href="https://www.openstreetmap.org">OpenStreetMap</a> kaudu.
|
||||
\n Tegelikult on OSMDashboard eraldi rakendus, mis saab ainult (ajutiselt) juurdepääsu näidatavate rada(de) andmetele.
|
||||
\n b) Tavalise kaardirakenduse kaudu (nt <a href="http://osmand.net/">OsmAnd</a> ja <a href="https://maps.me/">MAPS.ME</a>). Need rakendused peavad toetama KMZ-failiformaati (ainult asukohad ja ajatemplid). Tegelikult peab rakendus toetama <i>ACTION_VIEW</i> koos MIME <i>application/vnd.google-earth.kmz</i>-ga. </string>
|
||||
<string name="help_storage_pictures_title">Kuidas OpenTracks salvestab markeritena tehtud pilte?</string>
|
||||
<string name="help_storage_pictures_content">Neid hoitakse rakenduse sisemises salvestusruumis (st pääseb juurde ainult OpenTracks is).</string>
|
||||
<string name="help_track_export_title">Kuidas saab salvestatud lugusid eksportida / jagada?</string>
|
||||
<string name="help_track_export_content"> Lugusid saab seadetest eksportida KMZ-, KML- või GPX-vormingus. KMZ / KML kõik andmed; Ainult GPX-i asukohad. Radasid, mis on jagatud <i> jagamise ikooni </i> kaudu, jagatakse KMZ-na. </string>
|
||||
<string name="help_data_google_play_services_title">Kas OpenTracks nõuab / kasutab Google Play teenust?</string>
|
||||
<string name="help_recording_title">Kuidas OpenTracks andmeid registreerib?</string>
|
||||
<string name="help_recording_content">
|
||||
OpenTracks kasutab seadme GPS-andurit asukoha pidevaks registreerimiseks.
|
||||
Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei saa OpenTracks sellega midagi teha.</string>
|
||||
\n a) (reaalajas uuendused) Installige <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>. See pakub online või offline kaarte <a href="https://www.openstreetmap.org">OpenStreetMap</a> kaudu.
|
||||
\n Tegelikult, OSMDashboard on eraldi rakendus, mis saab juurdepääsu (ajutiselt) ainult näidatavate rada(de) andmetele.
|
||||
\n b) Tavalise kaardirakenduse kaudu (nt <a href="http://osmand.net/">OsmAnd</a> ja <a href="https://maps.me/">MAPS.ME</a>). Need rakendused peavad toetama KMZ failivormingut (ainult asukohad ja ajatemplid). Tegelikult peab rakendus toetama <i>ACTION_VIEW</i>-d koos MIME <i>application/vnd.google-earth.kmz</i>-ga. </string>
|
||||
<string name="help_storage_pictures_title">Kuidas salvestab OpenTracks asukohapunktitena tehtud pilte\?</string>
|
||||
<string name="help_storage_pictures_content">Neid hoitakse rakenduse sisemises salvestusruumis (st ligipääsetav ainult Opentracks\'i siseselt).</string>
|
||||
<string name="help_track_export_title">Kuidas saab salvestatud radu eksportida/jagada\?</string>
|
||||
<string name="help_track_export_content"> Radu saab seadetest eksportida KMZ-, KML- või GPX-vormingus. KMZ/KML kõik andmed; GPX ainult asukohad. Radasid, mis on jagatud <i>jagamise ikooni</i> kaudu, jagatakse KMZ-na. </string>
|
||||
<string name="help_data_google_play_services_title">Kas OpenTracks nõuab/kasutab Google Play teenust\?</string>
|
||||
<string name="help_recording_title">Kuidas salvestab OpenTracks andmeid\?</string>
|
||||
<string name="help_recording_content">OpenTracks kasutab seadme GPS-andurit pidevalt asukoha salvestamiseks. Kui GPS-seade tagastab ebatäpseid andmeid (nt asukoht, kiirus, tõus), ei saa OpenTracks sellega midagi teha.</string>
|
||||
<string name="help_data_storage_title">Kuidas OpenTracks sensori andmeid salvestab?</string>
|
||||
<string name="help_data_storage_content"> Anduri andmed salvestatakse salvestatud asukoha kohta. Südame löögisageduse anduri puhul tähendab see, et asukoha kohta salvestatakse ainult <i>üks</i> südame löögisageduse mõõtmine. Kui seisate paigal või siseruumides, siis anduri andmeid ei registreerita (kuid need näidatakse). </string>
|
||||
<string name="help_data_storage_content"> Sensori andmed salvestatakse iga asukoha kohta. Pulsi anduri puhul tähendab see, et iga asukoha kohta salvestatakse ainult <i>üks</i> pulsi mõõtmine. Kui seisate paigal või siseruumides, siis anduri andmeid ei salvestata (kuid neid näidatakse). </string>
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks ei salvesta asukohti?</string>
|
||||
<string name="help_gps_troubleshooting_content"> Mida saate teha:
|
||||
\na) kontrollige, kas GPS on lubatud,
|
||||
\nb) parandada GPS vastuvõtt (NT minna õues),
|
||||
\nc) kontrollige <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid /">GPSTest</a> app ja
|
||||
\nd) keelata energiasäästu.
|
||||
\n a) kontrollige, kas GPS on sisse lülitatud,
|
||||
\n b) paranda GPS-i vastuvõttu (nt minge õue),
|
||||
\n c) testige <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a> rakendusega ja
|
||||
\n d) lülita energiasäästu režiim välja.
|
||||
\n
|
||||
\nKui kõik ei aita, palun teatage veast. </string>
|
||||
<string name="help_support_title">Kuidas OpenTracks it toetada?</string>
|
||||
<string name="help_support_content"> Saate:
|
||||
\n a) levitada OpenTracks\'i kohta sõna,
|
||||
\n Kui mitte midagi ei aita, palun teatage meid veast. </string>
|
||||
<string name="help_support_title">Kuidas ma saan OpenTracks\'i toetada\?</string>
|
||||
<string name="help_support_content"> Te saate:
|
||||
\n a) levitada sõna OpenTracks\'i kohta,
|
||||
\n b) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">ettepanekuid teha</a>,
|
||||
\n c) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">raportida vigadest</a>,
|
||||
\n c) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">teatada vigadest</a>,
|
||||
\n d) aidata tarkvara arendamisel,
|
||||
\n e) osta <a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">Google Play Store\'is</a>,
|
||||
\n e) osta rakendus <a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">Google Play poest</a>,
|
||||
\n f) annetada ja
|
||||
\n g) teha kõike, mis teie arvates aitab OpenTracks\'ile kaasa. </string>
|
||||
\n g) teha midagi, mis teie arvates aitaks OpenTracks\'i. </string>
|
||||
<!-- Activity Type -->
|
||||
<string name="activity_type_airplane">lennuk</string>
|
||||
<string name="activity_type_atv">ATV</string>
|
||||
<string name="activity_type_biking">rattasõit</string>
|
||||
<string name="activity_type_blimp">lennumudelism</string>
|
||||
<string name="activity_type_biking">jalgrattasõit</string>
|
||||
<string name="activity_type_blimp">õhulaev</string>
|
||||
<string name="activity_type_boat">paat</string>
|
||||
<string name="activity_type_climbing">mägironimine</string>
|
||||
<string name="activity_type_commercial_airplane">kaubalennuk</string>
|
||||
<string name="activity_type_cross_country_skiing">murdmaasuusatamine</string>
|
||||
<string name="activity_type_cycling">rattasõit</string>
|
||||
<string name="activity_type_cycling">jalgrattasõit</string>
|
||||
<string name="activity_type_dirt_bike">krossiratas</string>
|
||||
<string name="activity_type_donkey_back_riding">eesliga ratsutamine</string>
|
||||
<string name="activity_type_driving">autosõit</string>
|
||||
<string name="activity_type_driving_bus">bussisõit</string>
|
||||
<string name="activity_type_driving_car">autoga sõitmine</string>
|
||||
<string name="activity_type_ferry">praam</string>
|
||||
<string name="activity_type_frisbee">taldriku lennutamine</string>
|
||||
<string name="activity_type_frisbee">frisbi</string>
|
||||
<string name="activity_type_gliding">purilend</string>
|
||||
<string name="activity_type_hang_gliding">deltaplanerism</string>
|
||||
<string name="activity_type_hang_gliding">deltaplaan</string>
|
||||
<string name="activity_type_helicopter">helikopter</string>
|
||||
<string name="activity_type_hiking">matkamine</string>
|
||||
<string name="activity_type_horse_back_riding">hobusega ratsutamine</string>
|
||||
<string name="activity_type_hot_air_balloon">kuumaõhupall</string>
|
||||
<string name="activity_type_ice_sailing">jääpurjetamine</string>
|
||||
<string name="activity_type_inline_skating">rulluisutamine</string>
|
||||
<string name="activity_type_kayaking">süstasõit</string>
|
||||
<string name="activity_type_kayaking">kajakisõit</string>
|
||||
<string name="activity_type_kite_surfing">lohesurf</string>
|
||||
<string name="activity_type_land_sailing">maapurjetamine</string>
|
||||
<string name="activity_type_mixed_type">segatüüpi</string>
|
||||
<string name="activity_type_mixed_type">segatüüp</string>
|
||||
<string name="activity_type_motor_bike">mootorratas</string>
|
||||
<string name="activity_type_motor_boating">mootorpaadiga sõitmine</string>
|
||||
<string name="activity_type_mountain_biking">mägirattasõit</string>
|
||||
<string name="activity_type_off_trail_hiking">maastikul matkamine</string>
|
||||
<string name="activity_type_other">muu</string>
|
||||
<string name="activity_type_paddling">sõudmine</string>
|
||||
<string name="activity_type_para_gliding">liuglangevarjusõit</string>
|
||||
<string name="activity_type_rc_airplane">mudellennuk</string>
|
||||
<string name="activity_type_rc_boat">Paadimudel</string>
|
||||
<string name="activity_type_rc_helicopter">mudelhelikopter</string>
|
||||
<string name="activity_type_para_gliding">motovarjuga lendamine</string>
|
||||
<string name="activity_type_rc_airplane">kaugjuhitav lennuk</string>
|
||||
<string name="activity_type_rc_boat">kaugjuhitav paat</string>
|
||||
<string name="activity_type_rc_helicopter">kaugjuhitav helikopter</string>
|
||||
<string name="activity_type_riding">ratsutamine</string>
|
||||
<string name="activity_type_road_biking">jalgrattasõit maanteel</string>
|
||||
<string name="activity_type_road_biking">maanteerattasõit</string>
|
||||
<string name="activity_type_roller_skiing">rullsuusatamine</string>
|
||||
<string name="activity_type_rowing">sõudmine</string>
|
||||
<string name="activity_type_running">jooksmine</string>
|
||||
@@ -111,61 +109,56 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="activity_type_skate_boarding">rulasõit</string>
|
||||
<string name="activity_type_skating">uisutamine</string>
|
||||
<string name="activity_type_skiing">suusatamine</string>
|
||||
<string name="activity_type_sky_jumping">langevarjuhüpped</string>
|
||||
<string name="activity_type_sky_jumping">langevarjuhüppamine</string>
|
||||
<string name="activity_type_sled">kelk</string>
|
||||
<string name="activity_type_snow_boarding">lumelauasõit</string>
|
||||
<string name="activity_type_snow_shoeing">lumeräätsadega sõitmine</string>
|
||||
<string name="activity_type_snow_shoeing">lumeräätsadega matkamine</string>
|
||||
<string name="activity_type_speed_walking">kiirkõnd</string>
|
||||
<string name="activity_type_street_running">linnajooks</string>
|
||||
<string name="activity_type_street_running">linnas jooksmine</string>
|
||||
<string name="activity_type_surfing">surfamine</string>
|
||||
<string name="activity_type_track_cycling">trekisõit</string>
|
||||
<string name="activity_type_track_running">staadionijooks</string>
|
||||
<string name="activity_type_trail_hiking">matkarajal matkamine</string>
|
||||
<string name="activity_type_trail_running">maastikujooks</string>
|
||||
<string name="activity_type_train">rong</string>
|
||||
<string name="activity_type_ultimate_frisbee">ülim frisbee</string>
|
||||
<string name="activity_type_ultimate_frisbee">ülim frisbi</string>
|
||||
<string name="activity_type_unknown">tundmatu</string>
|
||||
<string name="activity_type_wakeboarding">veelauaga sõitmine</string>
|
||||
<string name="activity_type_walking">kõndimine</string>
|
||||
<string name="activity_type_walking">jalutamine</string>
|
||||
<string name="activity_type_water_skiing">veesuusatamine</string>
|
||||
<string name="activity_type_wind_surfing">purilauasõit</string>
|
||||
<!-- Description -->
|
||||
<string name="description_activity_type">Tegevuse tüüp: %1$s</string>
|
||||
<string name="description_average_moving_pace_in_minute">Keskmine liikumiskiirus: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_moving_pace_in_minute">Keskmine liikumis tempo: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_moving_speed">Keskmine liikumiskiirus: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_average_pace_in_minute">Keskmine kiirus: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_pace_in_minute">Keskmine tempo: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_average_speed">Keskmine kiirus: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_altitude_gain">Saavutatud kõrgus: %1$d m ( %2$d jalga)</string>
|
||||
<string name="description_altitude_imperial">Kõrgus (jalga)</string>
|
||||
<string name="description_altitude_metric">Kõrgus (m)</string>
|
||||
<string name="description_fastest_pace_in_minute">Kõrgeim tempo: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_max_altitude">Max kõrgus: %1$d m (%2$d jalga)</string>
|
||||
<string name="description_altitude_gain">Kõrguse kasv: %1$d m ( %2$d jalga)</string>
|
||||
<string name="description_altitude_imperial">Tõus (jalga)</string>
|
||||
<string name="description_altitude_metric">Tõus (m)</string>
|
||||
<string name="description_fastest_pace_in_minute">Kiireim tempo: %1$s min/km (%2$s min/mi)</string>
|
||||
<string name="description_max_altitude">Max tõus: %1$d m (%2$d jalga)</string>
|
||||
<string name="description_max_speed">Max kiirus: %1$.2f km/h (%2$.1f mi/h)</string>
|
||||
<string name="description_min_altitude">Min kõrgus: %1$d m ( %2$d jalga)</string>
|
||||
<string name="description_min_altitude">Min tõus: %1$d m ( %2$d jalga)</string>
|
||||
<string name="description_moving_time">Liikumisaeg: %1$s</string>
|
||||
<string name="description_pace_imperial">Tempo (min/mi)</string>
|
||||
<string name="description_pace_metric">Tempo (min/km)</string>
|
||||
<string name="description_recorded_time">Salvestatud: %1$s</string>
|
||||
<string name="description_speed_ms">Kiirus (m/s)</string>
|
||||
<string name="description_sensor_cadence">Rütm (p/min)</string>
|
||||
<string name="description_sensor_heart_rate">Pulsisagedus (l/min)</string>
|
||||
<string name="description_sensor_heart_rate">Pulsisagedus (lööki minutis)</string>
|
||||
<string name="description_sensor_power">Võimsus (W)</string>
|
||||
<string name="description_default_speed_or_pace">Tegevuse tüübi järgi</string>
|
||||
<string name="description_speed_imperial">Kiirus (mi/h)</string>
|
||||
<string name="description_speed_metric">Kiirus (km/h)</string>
|
||||
<string name="description_time">Aeg</string>
|
||||
<string name="description_total_distance">Kogupikkus: %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Koguaeg: %1$s</string>
|
||||
<string name="description_total_time">Aeg kokku: %1$s</string>
|
||||
<!-- Export -->
|
||||
<string name="export_with_photos">fotodega</string>
|
||||
<string name="export_with_photos">koos fotodega</string>
|
||||
<string name="export_without_photos">ilma fotodeta</string>
|
||||
<string name="export_progress_message">Eksportimine kataloogi %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 fail</item>
|
||||
<item quantity="other">%1$d faili</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Lisa</string>
|
||||
<string name="generic_delete_selected_confirm_title">Kas kustutada valitud?</string>
|
||||
@@ -183,42 +176,42 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="gps_wait_for_signal">Oodatakse GPS-signaali</string>
|
||||
<!-- Image -->
|
||||
<string name="image_arrow">Nool</string>
|
||||
<string name="image_marker">Mark</string>
|
||||
<string name="image_marker_count">Markerite arv</string>
|
||||
<string name="image_marker">Märgis</string>
|
||||
<string name="image_marker_count">Märgistuste arv</string>
|
||||
<string name="image_pause">Peata</string>
|
||||
<string name="image_photo_marker">Fotomarker</string>
|
||||
<string name="image_photo_marker">Fotomärgis</string>
|
||||
<string name="image_record">Salvesta</string>
|
||||
<string name="image_stop">Peata</string>
|
||||
<string name="image_track">Rada</string>
|
||||
<!-- Import -->
|
||||
<string name="import_progress_message">Importimine kataloogist %1$s…</string>
|
||||
<!-- Marker -->
|
||||
<string name="marker_add_error">Ei saa markerit lisada. GPS-signaal puudub. Proovige uuesti.</string>
|
||||
<string name="marker_add_success">Marker lisati</string>
|
||||
<string name="marker_add_canceled">Tühistatud, markerit ei lisatud</string>
|
||||
<string name="marker_add_photo_canceled">Tühistatud, fotomarkerit pole lisatud</string>
|
||||
<string name="marker_delete_one_confirm_message">Marker kustutatakse seadmest jäädavalt</string>
|
||||
<string name="marker_delete_one_confirm_title">Kas kustutada marker?</string>
|
||||
<string name="marker_delete_multiple_confirm_message">Valitud markerid kustutatakse seadmest jäädavalt</string>
|
||||
<string name="marker_name_format">Mark %1$d</string>
|
||||
<string name="marker_add_error">Ei saa märgist lisada. GPS-signaal puudub. Proovige uuesti.</string>
|
||||
<string name="marker_add_success">Märgis lisati</string>
|
||||
<string name="marker_add_canceled">Tühistatud, märgist ei lisatud</string>
|
||||
<string name="marker_add_photo_canceled">Tühistatud, fotomärgist ei lisatud</string>
|
||||
<string name="marker_delete_one_confirm_message">Märgis kustutatakse seadmest jäädavalt</string>
|
||||
<string name="marker_delete_one_confirm_title">Kas kustutada märgis\?</string>
|
||||
<string name="marker_delete_multiple_confirm_message">Valitud märgis kustutatakse seadmest jäädavalt</string>
|
||||
<string name="marker_name_format">Märgis %1$d</string>
|
||||
<string name="marker_title">%1$d/%2$d</string>
|
||||
<!-- Marker Detail -->
|
||||
<!-- Marker Edit -->
|
||||
<string name="marker_edit_marker_type">Markeri tüüp (nt juga)</string>
|
||||
<string name="marker_edit_marker_type_hint">Markeri tüüp</string>
|
||||
<string name="marker_edit_marker_type">Märgise tüüp (nt juga)</string>
|
||||
<string name="marker_edit_marker_type_hint">Märgise tüüp</string>
|
||||
<!-- Marker List -->
|
||||
<string name="marker_list_empty_message">Teil ei ole markereid</string>
|
||||
<string name="marker_list_empty_message">Teil ei ole märgiseid</string>
|
||||
<!-- Menu -->
|
||||
<string name="menu_aggregated_statistics">Agreg.statistika</string>
|
||||
<string name="menu_aggregated_statistics">Agregeeritud statistika</string>
|
||||
<string name="menu_delete">Kustuta</string>
|
||||
<string name="menu_edit">Muuda</string>
|
||||
<string name="menu_export_all">Ekspordi kõik</string>
|
||||
<string name="menu_help">Abi</string>
|
||||
<string name="menu_import_all">Impordi kõik</string>
|
||||
<string name="menu_insert_marker">Lisa marker</string>
|
||||
<string name="menu_insert_marker">Lisa märgis</string>
|
||||
<string name="menu_insert_photo">Foto lisamine</string>
|
||||
<string name="menu_insert_gallery_img">Sisestage galerii pilt</string>
|
||||
<string name="menu_markers">Markerid</string>
|
||||
<string name="menu_markers">Märgised</string>
|
||||
<string name="menu_search">Otsing</string>
|
||||
<string name="menu_select_all">Vali kõik</string>
|
||||
<string name="menu_settings">Seaded</string>
|
||||
@@ -226,7 +219,7 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="menu_show_on_map">Kuva kaardil</string>
|
||||
<string name="menu_start_gps">Käivita GPS</string>
|
||||
<string name="menu_stop_gps">Peata GPS</string>
|
||||
<string name="menu_resume_track">Jätka pala</string>
|
||||
<string name="menu_resume_track">Jätka rada</string>
|
||||
<!-- OpenTracks -->
|
||||
<string name="recording_service">Salvestamisteenus</string>
|
||||
<!-- Permission -->
|
||||
@@ -235,12 +228,12 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<!-- Sensor State -->
|
||||
<string name="sensor_state_battery">Aku tase</string>
|
||||
<string name="sensor_state_cadence">Rütm</string>
|
||||
<string name="sensor_state_cadence_value">%1$d p/min</string>
|
||||
<string name="sensor_state_cadence_value">%1$d p/min (pööret minutis)</string>
|
||||
<string name="sensor_state_heart_rate">Pulsisagedus</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d lööki minutis</string>
|
||||
<string name="sensor_state_power">Võimsus</string>
|
||||
<string name="sensor_state_power_value">%1$d W</string>
|
||||
<string name="sensor_could_not_scan">Bluetooth-seadmeid ei õnnestunud skannida (tõrge %1$i).</string>
|
||||
<string name="sensor_could_not_scan">Bluetooth seadmeid ei õnnestunud skannida (tõrge %1$i).</string>
|
||||
<string name="bluetooth_disabled">Lubage Bluetooth.</string>
|
||||
<string name="settings_not_while_recording">Raja salvestamise ajal ei ole kättesaadav</string>
|
||||
<string name="settings_show">Kuva</string>
|
||||
@@ -250,9 +243,9 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="settings_chart_by_distance">Vahemaa järgi</string>
|
||||
<string name="settings_chart_by_time">Aja järgi</string>
|
||||
<!-- Settings Recording -->
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">Kuva lukukraanil statistikat</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">Kuva lukustuskuval statistikat</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_summary">Salvestamise ajal näidake statistikat ilma seadet avamata.</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">Hoidke ekraani peal</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">Hoia ekraan sisse lülitatud</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_summary">Salvestamise ajal hoidke ekraani sisse lülitatud.</string>
|
||||
<string name="settings_recording">Salvestamine</string>
|
||||
<string name="settings_recording_default_activity_title">Tegevuse vaiketüüp</string>
|
||||
@@ -435,24 +428,24 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="share_image_subject">Tahaksin teiega pilti jagada</string>
|
||||
<string name="share_image_body">Ma arvan, et see pilt võiks teid huvitada.</string>
|
||||
<string name="open_track_as_trackfileformat">Ava kui %1$s</string>
|
||||
<string name="activity_type_escooter">eskuuter</string>
|
||||
<string name="open_track_as_GPX">Avatud kui GPX</string>
|
||||
<string name="open_track_as_KML">Avatud kui KML</string>
|
||||
<string name="description_altitude_loss">Kõrguse kadu: %1$d m (%2$d ft)</string>
|
||||
<string name="export_all_do_it_for_all">tehke seda kõigi konfliktide jaoks</string>
|
||||
<string name="activity_type_escooter">elektritõukeratas</string>
|
||||
<string name="open_track_as_GPX">Ava kui GPX</string>
|
||||
<string name="open_track_as_KML">Ava kui KML</string>
|
||||
<string name="description_altitude_loss">Kõrguse langus: %1$d m (%2$d jalga)</string>
|
||||
<string name="export_all_do_it_for_all">tehke seda iga konfilkti puhul</string>
|
||||
<string name="export_error_post_workout">Treeningujärgne eksport nurjus, palun kontrolli ekspordikataloogi.</string>
|
||||
<string name="import_thread_interrupted">Teema katkestatud</string>
|
||||
<string name="import_thread_interrupted">Lõim katkestatud</string>
|
||||
<string name="import_parser_error">Parseri viga: %1$s</string>
|
||||
<string name="import_unable_to_import_file">Faili importimine nurjus: %1$s</string>
|
||||
<plurals name="generic_completed_with_errors">
|
||||
<item quantity="one">Lõpetatud ühe veaga</item>
|
||||
<item quantity="other">Lõpetatud %1$d vigadega</item>
|
||||
<item quantity="other">Lõpetatud %1$d veaga</item>
|
||||
</plurals>
|
||||
<string name="gps_fixed_and_ready">GPS fikseeritud ja valmis</string>
|
||||
<string name="import_prevent_reimport">Olete määranud vältida re-import track</string>
|
||||
<string name="generic_overwrite">Ülekirjutamine</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Ülekirjutatud lood</string>
|
||||
<string name="export_track_errors">Palasid ei ekspordita</string>
|
||||
<string name="import_prevent_reimport">Olete määranud vältida raja re-importimist</string>
|
||||
<string name="generic_overwrite">Kirjuta üle</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Ülekirjutatud rajad</string>
|
||||
<string name="export_track_errors">Eksportimata rajad</string>
|
||||
<string name="export_track_already_exists_msg">Rada %1$s on sihtkataloogis juba olemas.</string>
|
||||
<string name="aggregated_stats_empty_message">Salvestage oma esimene pala, et näha koondatud statistikat</string>
|
||||
<string name="voice_pace_lap">Ringiaeg %1$s</string>
|
||||
@@ -464,7 +457,7 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Salvestamise ajal esitada täisekraanil.</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_title">Täisekraan</string>
|
||||
<string name="settings_default_trackfileformat">Failivormingu eksport/jagamine</string>
|
||||
<string name="sensor_state_power_avg">Avg Võimsus</string>
|
||||
<string name="sensor_state_power_avg">Keskmine Võimsus</string>
|
||||
<string name="sensor_state_heart_rate_max">Maksimaalne pulss</string>
|
||||
<string name="sensor_state_heart_rate_avg">Keskmine pulsisagedus</string>
|
||||
<string name="sensor_state_cadence_max">Max kadentsus</string>
|
||||
@@ -481,23 +474,23 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="settings_default_export_uri_title">Track ekspordi kataloog</string>
|
||||
<string name="instant_export_enabled_title">Vahetu treeningujärgne eksport</string>
|
||||
<string name="export_progress_summary_errors_msg">Viga</string>
|
||||
<string name="export_progress_summary_skip_msg">Palad vahele</string>
|
||||
<string name="export_progress_summary_new_msg">Uued palad eksporditud</string>
|
||||
<string name="export_progress_summary_skip_msg">Vahele jäetud rajad</string>
|
||||
<string name="export_progress_summary_new_msg">Uued rajad eksporditud</string>
|
||||
<string name="generic_open_track">Avatud rada</string>
|
||||
<string name="generic_completed">Lõpetanud</string>
|
||||
<string name="generic_click_twice_cancel">Tühistamiseks klõpsake uuesti</string>
|
||||
<string name="generic_completed">Lõpetatud</string>
|
||||
<string name="generic_click_twice_cancel">Tühistamiseks vajutage uuesti tagasi</string>
|
||||
<string name="gps_disabled_msg">GPS keelatud</string>
|
||||
<string name="import_unsupported_format">Toetamata failivorming</string>
|
||||
<string name="import_no_kml_file_found">Ei, doktor.KMZ-is leitud KML fail</string>
|
||||
<string name="import_no_kml_file_found">doc.kml faili ei leitud KMZ-st</string>
|
||||
<string name="import_error_info">%1$s: %2$s</string>
|
||||
<string name="import_error_list_dialog_title">Failid, mida ei impordita</string>
|
||||
<string name="import_error_list_dialog_title">Faile pole imporditud</string>
|
||||
<string name="import_file_imported">Fail %1$s imporditud</string>
|
||||
<string name="import_progress_summary_ok_msg">Imporditud failid</string>
|
||||
<string name="import_progress_summary_exists_msg">Juba olemas</string>
|
||||
<string name="generic_show_errors">Vigade Näitamine</string>
|
||||
<string name="generic_show_errors">Näita vigu</string>
|
||||
<string name="generic_separator_done_total">/</string>
|
||||
<string name="generic_skip">Jäta</string>
|
||||
<string name="import_progress_summary_errors_msg">Viga</string>
|
||||
<string name="generic_skip">Jäta vahele</string>
|
||||
<string name="import_progress_summary_errors_msg">Vead</string>
|
||||
<string name="track_distance_notification">Kaugus: %1$s</string>
|
||||
<string name="track_speed_notification">Kiirus: %1$s</string>
|
||||
<string name="track_pace_notification">Tempo: %1$s</string>
|
||||
@@ -517,28 +510,28 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="description_speed_source_gps">GPS</string>
|
||||
<string name="settings_cycling_sensor">Jalgrattasõit</string>
|
||||
<string name="settings_import_section">Import</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks nõuab luba kasutada Bluetooth.</string>
|
||||
<string name="permission_bluetooth_failed_rejected">Peate käsitsi andma Opentrackidele juurdepääsu lähedalasuvatele seadmetele süsteemi seadetes.</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks vajab Bluetooth-i kasutamiseks luba.</string>
|
||||
<string name="permission_bluetooth_failed_rejected">Peate Opentracks\'ile süsteemiseadetes andma käsitsi loa lähedalasuvatele seadmetele.</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<string name="location_coordinate">%1$s°</string>
|
||||
<string name="field_set_primary">Esmane</string>
|
||||
<string name="generic_choose_an_option">Valige suvand</string>
|
||||
<string name="settings_layout_reset_done">Kõik paigutusseaded on muudetud vaikeväärtusteks</string>
|
||||
<string name="settings_all_reset">Lähtestage</string>
|
||||
<string name="settings_defaults_title">Vaikeühikud ja tegevus</string>
|
||||
<string name="settings_defaults_summary">Eelistatud Üksused, Vaiketegevus, Raja Vaikenimi</string>
|
||||
<string name="settings_ui_title">kasutajaliides</string>
|
||||
<string name="settings_defaults_title">Vaikeühikud ja -tegevused</string>
|
||||
<string name="settings_defaults_summary">Eelistatud Ühikud, Vaiketegevused, Raja Vaikenimi</string>
|
||||
<string name="settings_ui_title">Kasutajaliides</string>
|
||||
<string name="settings_ui_summary">Välimus, Salvestamise Paigutus, Teema</string>
|
||||
<string name="settings_gps_summary">Ajavahemik, vahemaa intervall, maksimaalne kaugus, täpsus</string>
|
||||
<string name="settings_sensors_title">Bluetooth Andurid</string>
|
||||
<string name="settings_announcements_title">Häälteated</string>
|
||||
<string name="settings_announcements_summary">Aeg, Kaugus, Hääle Kiirus</string>
|
||||
<string name="settings_units_category">Üksus</string>
|
||||
<string name="settings_units_category">Ühikud</string>
|
||||
<string name="settings_import_export_summary">Import, Eksport, Automaatne Eksport</string>
|
||||
<string name="settings_import_export_title">Import/Eksport</string>
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_open_tracks_summary">Kõik OpenTracks Projekti Kohta</string>
|
||||
<string name="settings_open_tracks_title">Avatud Rajad</string>
|
||||
<string name="settings_open_tracks_title">OpenTracks</string>
|
||||
<string name="settings_reset_summary">Lähtestage Seaded vaikeväärtustele</string>
|
||||
<string name="settings_recording_customize_layout_title">Kohandage oma salvestuspaigutust</string>
|
||||
<string name="settings_recording_customize_layout_select_columns">Andmeväljad rea kohta</string>
|
||||
@@ -562,22 +555,23 @@ Kui GPS-seade teatab ebatäpsetest andmetest (nt asukoht, kiirus, kõrgus), ei s
|
||||
<string name="settings_running_sensor">Töötama</string>
|
||||
<string name="settings_generic_sensor">Geneeriline</string>
|
||||
<string name="custom_layout_list_layout_removed">Paigutus eemaldati</string>
|
||||
<string name="menu_add_custom_layout">Uus kujundus</string>
|
||||
<string name="generic_undo">Tagasi</string>
|
||||
<string name="menu_add_custom_layout">Uus paigutus</string>
|
||||
<string name="generic_undo">Võta tagasi</string>
|
||||
<string name="menu_select_layout">Valige paigutus</string>
|
||||
<string name="stats_custom_layout_default_layout">Vaikimisi paigutus</string>
|
||||
<string name="custom_layout_select_layout">Valige paigutus</string>
|
||||
<string name="custom_layout_list_edit_already_exists">Paigutuse nimi on juba olemas</string>
|
||||
<string name="custom_layout_list_edit_name">Sisestage paigutuse nimi, et lisada</string>
|
||||
<string name="custom_layout_list_title">Plaanid</string>
|
||||
<string name="generic_filter">Filtri</string>
|
||||
<string name="generic_filter">Filtreeri</string>
|
||||
<string name="generic_from">Alates</string>
|
||||
<string name="generic_to">Et</string>
|
||||
<string name="menu_filter">Filtri</string>
|
||||
<string name="generic_to">Kuni</string>
|
||||
<string name="menu_filter">Filtreeri</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_enabled">Näitab ainult neid Bluetooth-seadmeid, mis teatavad nõutavatest teenustest</string>
|
||||
<string name="aggregated_stats_filter_no_results">Määratud filtri jaoks ei ole tegevusi</string>
|
||||
<string name="generic_today">Täna</string>
|
||||
<string name="export_dir_not_writable">" (mitte kirjutatav!)"</string>
|
||||
<string name="export_dir_not_writable">" (pole kirjutatav!)"</string>
|
||||
<string name="export_cannot_write_to_dir">Ei saa kirjutada ekspordikataloogi.</string>
|
||||
<string name="generic_yesterday">Eile</string>
|
||||
<string name="no_compatible_file_manager_installed">Ühilduv failihaldur ei ole paigaldatud</string>
|
||||
</resources>
|
||||
@@ -162,11 +162,6 @@ GPS gailuak datu okerrak salatzen baditu (adibidez, kokapena, abiadura, kota), O
|
||||
<string name="export_without_photos">argazkirik gabe</string>
|
||||
<string name="export_progress_message">%1$s karpetara esportatzen…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 fitxategi</item>
|
||||
<item quantity="other">%1$d fitxategi</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Gehitu</string>
|
||||
<string name="generic_delete_selected_confirm_title">Hautatutakoak ezabatu nahi dituzu?</string>
|
||||
@@ -581,4 +576,5 @@ GPS gailuak datu okerrak salatzen baditu (adibidez, kokapena, abiadura, kota), O
|
||||
<string name="title_activity_settings_custom_layout">Pertsonalizatu Grabazioaren Diseinua</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<string name="generic_undo">Desegin</string>
|
||||
<string name="no_compatible_file_manager_installed">Fitxategi-kudeatzaile bateragarririk ez da instalatu</string>
|
||||
</resources>
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">در حال صادر کردن به %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d فایل</item>
|
||||
<item quantity="other">%1$d فایل</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">افزودن</string>
|
||||
<string name="generic_delete_selected_confirm_title">موارد انتخابی حذف شود؟</string>
|
||||
|
||||
@@ -165,11 +165,6 @@ limitations under the License.
|
||||
<string name="export_without_photos">ilman valokuvia</string>
|
||||
<string name="export_progress_message">Viedään kohteeseen %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 tiedosto</item>
|
||||
<item quantity="other">%1$d tiedostoa</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Lisää</string>
|
||||
<string name="generic_delete_selected_confirm_title">Poistetaanko valitut?</string>
|
||||
@@ -289,10 +284,10 @@ limitations under the License.
|
||||
<string name="settings_stats_units_metric">Metrijärjestelmä (km, m)</string>
|
||||
<string name="settings_stats_units_title">Halutut yksiköt</string>
|
||||
<!-- Share Track -->
|
||||
<string name="share_track_share_file_body">Luulen, että saatat olla kiinnostunut tästä kappaleesta.
|
||||
<string name="share_track_share_file_body">Luulen, että saatat olla kiinnostunut tästä reitistä.
|
||||
\n
|
||||
\n%1$s</string>
|
||||
<string name="share_track_subject">Haluaisin jakaa kappaleen kanssasi</string>
|
||||
<string name="share_track_subject">Haluaisin jakaa reitin kanssasi</string>
|
||||
<!-- Stats -->
|
||||
<string name="stats_average_moving_pace">Keskim. liikkumisvauhti</string>
|
||||
<string name="stats_average_moving_speed">Keskim. liikkumisnopeus</string>
|
||||
@@ -335,7 +330,7 @@ limitations under the License.
|
||||
<string name="unit_kilometer_per_hour">km/h</string>
|
||||
<string name="unit_meter">m</string>
|
||||
<string name="unit_mile">mailia</string>
|
||||
<string name="unit_mile_per_hour">km/h</string>
|
||||
<string name="unit_mile_per_hour">mailia/h</string>
|
||||
<string name="unit_minute_per_kilometer">min/km</string>
|
||||
<string name="unit_minute_per_mile">min/maili</string>
|
||||
<!-- Value -->
|
||||
@@ -452,18 +447,18 @@ limitations under the License.
|
||||
<string name="gps_fixed_and_ready">GPS kiinteä ja valmis</string>
|
||||
<string name="import_no_kml_file_found">Ei doc.KML tiedosto löytyy KMZ</string>
|
||||
<string name="settings_default_export_uri_title">Seuraa vientihakemistoa</string>
|
||||
<string name="instant_export_enabled_summary">Vie raita varastoon tallennuksen jälkeen on valmis</string>
|
||||
<string name="instant_export_enabled_summary">Vie reitti tiedostoon tallennuksen loputtua</string>
|
||||
<string name="voice_speed_lap">Kierrosnopeus %1$s</string>
|
||||
<string name="settings_sensor_wheel_circumference">Pyörän ympärysmitta (mm)</string>
|
||||
<string name="import_thread_interrupted">Lanka keskeytetty</string>
|
||||
<string name="import_unsupported_format">Tukematon tiedostomuoto</string>
|
||||
<string name="settings_prevent_reimport_tracks_title">Estä kappaleiden uudelleen tuonti</string>
|
||||
<string name="settings_prevent_reimport_tracks_title">Estä reittien uudelleen tuonti</string>
|
||||
<string name="import_parser_error">Jäsentimen virhe: %1$s</string>
|
||||
<string name="import_unable_to_import_file">Tiedostoa ei voi tuoda: %1$s</string>
|
||||
<string name="import_error_info">%1$s: %2$s</string>
|
||||
<string name="import_error_list_dialog_title">Tiedostoja ei tuotu</string>
|
||||
<string name="import_file_imported">Tiedosto %1$s tuotu</string>
|
||||
<string name="import_prevent_reimport">Olet asettanut Estä uudelleen tuonti raita</string>
|
||||
<string name="import_prevent_reimport">Olet estänyt reitin uudelleentuonnin</string>
|
||||
<string name="import_progress_summary_ok_msg">Tuodut tiedostot</string>
|
||||
<string name="import_progress_summary_exists_msg">Jo olemassa</string>
|
||||
<string name="import_progress_summary_errors_msg">Virhe</string>
|
||||
@@ -471,21 +466,21 @@ limitations under the License.
|
||||
<string name="settings_recording_fullscreen_on_while_recording_title">Kokoruutu</string>
|
||||
<string name="interval_list_empty_message">Ei ole mitään intervallia vielä</string>
|
||||
<string name="export_error_post_workout">Treenin jälkeinen vienti epäonnistui, tarkista vientihakemisto.</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Kappaleet ylikirjoitettu</string>
|
||||
<string name="export_progress_summary_overwrite_msg">Reitit ylikirjoitettu</string>
|
||||
<plurals name="generic_completed_with_errors">
|
||||
<item quantity="one">Valmista yhdellä virheellä</item>
|
||||
<item quantity="other">Valmista %1$d virheellä</item>
|
||||
</plurals>
|
||||
<string name="export_track_already_exists_msg">Kappale %1$s on jo olemassa kohdehakemistossa.</string>
|
||||
<string name="export_track_already_exists_msg">Reitti %1$s on jo olemassa kohdehakemistossa.</string>
|
||||
<string name="export_all_do_it_for_all">tee se kaikkien konfliktien vuoksi</string>
|
||||
<string name="export_track_errors">Kappaleita ei viety</string>
|
||||
<string name="export_track_errors">Reittejä ei viety</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">Tallennuksen aikana, läsnä koko näytön.</string>
|
||||
<string name="settings_night_mode_title">UI-teema</string>
|
||||
<string name="settings_night_mode_option_system">Järjestelmä</string>
|
||||
<string name="settings_night_mode_option_day">Päivä</string>
|
||||
<string name="settings_night_mode_option_night">Yö</string>
|
||||
<string name="export_progress_summary_new_msg">Uusia kappaleita viety</string>
|
||||
<string name="export_progress_summary_skip_msg">Kappaleet ohitettu</string>
|
||||
<string name="export_progress_summary_new_msg">Uusia reittejä viety</string>
|
||||
<string name="export_progress_summary_skip_msg">Reitit ohitettu</string>
|
||||
<string name="export_progress_summary_errors_msg">Virhe</string>
|
||||
<string name="generic_overwrite">Korvaa</string>
|
||||
<string name="generic_skip">Ohita</string>
|
||||
@@ -508,7 +503,7 @@ limitations under the License.
|
||||
<string name="delete_service">Poistopalvelu</string>
|
||||
<string name="track_delete_progress">%1$d/%2$d</string>
|
||||
<string name="menu_voice_rate">Äänen nopeus</string>
|
||||
<string name="track_delete_not_recording">Tätä raitaa ei voi poistaa, koska se on parhaillaan tallennettuna.</string>
|
||||
<string name="track_delete_not_recording">Tätä reittiä ei voi poistaa koska sitä tallennetaan parhaillaan.</string>
|
||||
<string name="settings_sensor_cycling_cadence">Pyöräily: tahtiaika</string>
|
||||
<string name="settings_sensor_cycling_distance_speed">Pyöräily: etäisyys ja nopeus</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">Juoksu: etäisyys, nopeus ja askeltiheys</string>
|
||||
@@ -520,4 +515,47 @@ limitations under the License.
|
||||
<string name="description_speed_source_gps">GPS</string>
|
||||
<string name="generic_choose_an_option">Valitse vaihtoehto</string>
|
||||
<string name="generic_undo">Kumoa</string>
|
||||
<string name="menu_select_layout">Valitse asettelu</string>
|
||||
<string name="settings_announcements_totaltime_frequency">Aikaväli</string>
|
||||
<string name="settings_public_api_enabled_summary_on">Muut sovellukset voivat aloittaa tai lopettaa tallennuksen.</string>
|
||||
<string name="field_set_primary">Ensisijainen</string>
|
||||
<string name="generic_today">Tänään</string>
|
||||
<string name="field_set_secondary">Toissijainen</string>
|
||||
<string name="field_remove_from_layout">Poista</string>
|
||||
<string name="menu_add_custom_layout">Uusi asettelu</string>
|
||||
<string name="settings_ui_summary">Ulkonäkö, asettelu, teema</string>
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_sensors_title">Bluetooth-anturit</string>
|
||||
<string name="settings_import_export_title">Tuonti/Vienti</string>
|
||||
<string name="custom_layout_list_edit_name">Nimeä luotava asettelu</string>
|
||||
<string name="custom_layout_list_edit_already_exists">Samanniminen asettelu on jo olemassa</string>
|
||||
<string name="custom_layout_list_layout_removed">Asettelu poistettu</string>
|
||||
<string name="custom_layout_select_layout">Valitse asettelu</string>
|
||||
<string name="stats_custom_layout_default_layout">Oletusasettelu</string>
|
||||
<string name="settings_layout_reset">Poista omat asettelut</string>
|
||||
<string name="settings_layout_reset_confirm_message">Kaikki asettelut palautetaan oletusasetuksiinsa. Yhtäkään tallennettua reittiä ei poisteta.</string>
|
||||
<string name="settings_layout_reset_confirm_title">Poistetaanko asettelut\?</string>
|
||||
<string name="settings_layout_reset_done">Kaikki asetteluasetukset palautettu oletuksiinsa</string>
|
||||
<string name="settings_all_reset">Tehdasasetukset</string>
|
||||
<string name="settings_cycling_sensor">Pyöräily</string>
|
||||
<string name="settings_generic_sensor">Yleinen</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks tarvitsee luvan käyttääkseen Bluetoothia.</string>
|
||||
<string name="location_coordinate">%1$s°</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<string name="generic_yesterday">Eilen</string>
|
||||
<string name="settings_open_tracks_summary">Kaikki OpenTracks-projektista</string>
|
||||
<string name="settings_ui_title">Käyttöliittymä</string>
|
||||
<string name="settings_import_export_summary">Tuo, vie, automaattinen vienti</string>
|
||||
<string name="settings_units_category">Yksiköt</string>
|
||||
<string name="settings_reset_summary">Palauta oletusasetukset</string>
|
||||
<string name="settings_recording_customize_layout_select_columns">Tietokenttiä rivillä</string>
|
||||
<string name="custom_layout_list_title">Asettelut</string>
|
||||
<string name="settings_running_sensor">Juoksu</string>
|
||||
<string name="settings_public_api_enabled_title">Julkinen rajapinta</string>
|
||||
<string name="settings_public_api_enabled_summary_off">Vain OpenTracks voi aloittaa tai lopettaa tallennuksen.</string>
|
||||
<string name="settings_public_api_disabled_toast">OpenTracksin julkinen rajapinta on pois käytöstä. Sen voi ottaa käyttöön asetuksista.</string>
|
||||
<string name="stats_coordinates">Leveys- ja pituusaste</string>
|
||||
<string name="stats_sensors_heart_rate">Sykenopeus</string>
|
||||
<string name="stats_sensors_power">Teho</string>
|
||||
<string name="no_compatible_file_manager_installed">Yhteensopiva tiedostojen hallinta puuttuu</string>
|
||||
</resources>
|
||||
@@ -91,10 +91,6 @@
|
||||
<string name="description_total_distance">Distance totale : %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Durée totale : %1$s</string>
|
||||
<string name="export_progress_message">Exportation vers le répertoire %1$s en cours…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d fichier</item>
|
||||
<item quantity="other">%1$d fichiers</item>
|
||||
</plurals>
|
||||
<string name="generic_add">Ajouter</string>
|
||||
<string name="generic_delete_selected_confirm_title">Supprimer les éléments sélectionnés?</string>
|
||||
<string name="generic_description">Description</string>
|
||||
|
||||
@@ -91,10 +91,6 @@
|
||||
<string name="description_total_distance">Distance totale : %1$.2f km (%2$.1f mi)</string>
|
||||
<string name="description_total_time">Durée totale : %1$s</string>
|
||||
<string name="export_progress_message">Exportation vers le répertoire %1$s en cours…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d fichier</item>
|
||||
<item quantity="other">%1$d fichiers</item>
|
||||
</plurals>
|
||||
<string name="generic_add">Ajouter</string>
|
||||
<string name="generic_delete_selected_confirm_title">Supprimer les éléments sélectionnés ?</string>
|
||||
<string name="generic_description">Description</string>
|
||||
|
||||
@@ -162,11 +162,6 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="export_without_photos">sans les photos</string>
|
||||
<string name="export_progress_message">Exportation vers le répertoire %1$s en cours…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d fichier</item>
|
||||
<item quantity="other">%1$d fichiers</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Ajouter</string>
|
||||
<string name="generic_delete_selected_confirm_title">Supprimer les éléments sélectionnés ?</string>
|
||||
@@ -581,4 +576,5 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
|
||||
<string name="generic_yesterday">Hier</string>
|
||||
<string name="export_cannot_write_to_dir">Impossible d\'écrire dans le répertoire d\'exportation.</string>
|
||||
<string name="export_dir_not_writable">" (non inscriptible !)"</string>
|
||||
<string name="no_compatible_file_manager_installed">Aucun gestionnaire de fichiers compatible n\'est installé</string>
|
||||
</resources>
|
||||
@@ -170,11 +170,6 @@ Se te detés ou estás en interiores, non se gardarán datos do sensor (mais ser
|
||||
<string name="export_without_photos">sen fotos</string>
|
||||
<string name="export_progress_message">Exportando a %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 ficheiro</item>
|
||||
<item quantity="other">%1$d ficheiros</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Engadir</string>
|
||||
<string name="generic_delete_selected_confirm_title">Eliminar a selección?</string>
|
||||
@@ -586,4 +581,5 @@ Se te detés ou estás en interiores, non se gardarán datos do sensor (mais ser
|
||||
<string name="generic_yesterday">Onte</string>
|
||||
<string name="export_cannot_write_to_dir">Non se pode escribir no directorio de exportación.</string>
|
||||
<string name="export_dir_not_writable">" (non escribible!)"</string>
|
||||
<string name="no_compatible_file_manager_installed">Non compatible xestor de ficheiros instalados</string>
|
||||
</resources>
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">%1$s पर निर्यात किया जा रहा है…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d फ़ाइलें</item>
|
||||
<item quantity="other">%1$d फ़ाइलें</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">जोड़ें</string>
|
||||
<string name="generic_delete_selected_confirm_title">चयनित हटाएं?</string>
|
||||
|
||||
@@ -110,12 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">Izvoz u direktorij %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">%1$d datoteka</item>
|
||||
<item quantity="few">%1$d datoteke</item>
|
||||
<item quantity="other">%1$d datoteka</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Dodaj</string>
|
||||
<string name="generic_delete_selected_confirm_title">Želite li izbrisati odabrano?</string>
|
||||
|
||||
@@ -110,11 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">Exportálás ide: %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 fájl</item>
|
||||
<item quantity="other">%1$d fájl</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Hozzáadás</string>
|
||||
<string name="generic_delete_selected_confirm_title">Törli a kiválasztott(ak)at?</string>
|
||||
|
||||
@@ -91,9 +91,6 @@
|
||||
<string name="description_total_distance">Jarak total: %1$.2f km (%2$.1f mil)</string>
|
||||
<string name="description_total_time">Waktu total: %1$s</string>
|
||||
<string name="export_progress_message">Mengekspor ke %1$s…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="other">%1$d file</item>
|
||||
</plurals>
|
||||
<string name="generic_add">Tambahkan</string>
|
||||
<string name="generic_delete_selected_confirm_title">Hapus yang dipilih?</string>
|
||||
<string name="generic_description">Deskripsi</string>
|
||||
|
||||
@@ -150,11 +150,6 @@ Infatti, un\'applicazione deve supportare <i>ACTION_VIEW</i> con MIME <i>applica
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">Esportando su %1$s…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="one">1 file</item>
|
||||
<item quantity="other">%1$d file</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">Aggiungi</string>
|
||||
<string name="generic_delete_selected_confirm_title">Eliminare selezionati\?</string>
|
||||
@@ -584,4 +579,5 @@ Infatti, un\'applicazione deve supportare <i>ACTION_VIEW</i> con MIME <i>applica
|
||||
<string name="generic_yesterday">Ieri</string>
|
||||
<string name="export_cannot_write_to_dir">Impossibile scrivere nella directory di esportazione.</string>
|
||||
<string name="export_dir_not_writable">" (non scrivibile!)"</string>
|
||||
<string name="no_compatible_file_manager_installed">Nessun file manager compatibile installato</string>
|
||||
</resources>
|
||||
@@ -91,12 +91,6 @@
|
||||
<string name="description_total_distance">מרחק כולל: %1$.2f ק\"מ (%2$.1f מייל)</string>
|
||||
<string name="description_total_time">זמן כולל: %1$s</string>
|
||||
<string name="export_progress_message">מייצא אל %1$s…</string>
|
||||
<plurals name="files">
|
||||
<item quantity="one">קובץ אחד</item>
|
||||
<item quantity="two">שני קבצים</item>
|
||||
<item quantity="many">%1$d קבצים</item>
|
||||
<item quantity="other">%1$d קבצים</item>
|
||||
</plurals>
|
||||
<string name="generic_add">הוסף</string>
|
||||
<string name="generic_delete_selected_confirm_title">למחוק את הפריטים שנבחרו?</string>
|
||||
<string name="generic_description">תיאור</string>
|
||||
|
||||
@@ -110,10 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">%1$sにエクスポート中…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="other">%1$d個のファイル</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">追加</string>
|
||||
<string name="generic_delete_selected_confirm_title">選択したアイテムを削除しますか?</string>
|
||||
|
||||
@@ -110,10 +110,6 @@ limitations under the License.
|
||||
<!-- Export -->
|
||||
<string name="export_progress_message">%1$s(으)로 내보내기 중…</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Files -->
|
||||
<plurals name="files">
|
||||
<item quantity="other">파일 %1$d개</item>
|
||||
</plurals>
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">추가하기</string>
|
||||
<string name="generic_delete_selected_confirm_title">선택한 항목을 삭제하시겠습니까?</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user