forked from upstream-mirrors/OpenTracks
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0605dbb0ab | |||
| bf03de6be7 | |||
| d65ce361f7 | |||
| 3f600f6be7 | |||
| 9aab3c216c | |||
| 7935185812 | |||
| 4c1b1be96c | |||
| 5762830655 | |||
| 6d61206782 | |||
| b9dedef292 | |||
| f3caecd049 | |||
| e16780277f | |||
| 13484685a3 | |||
| 7b745d9837 | |||
| 52742064f6 | |||
| 2edf5582aa | |||
| 808eb92bf2 |
+5
-4
@@ -59,8 +59,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 5151
|
||||
versionName "v4.3.0"
|
||||
versionCode 5168
|
||||
versionName "v4.3.1"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
@@ -122,7 +122,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.2'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
@@ -131,13 +131,14 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.8.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||
implementation 'androidx.mediarouter:mediarouter:1.3.1'
|
||||
|
||||
androidTestImplementation 'androidx.test:core:1.5.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test:rules:1.5.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.5.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
androidTestImplementation 'org.mockito:mockito-android:4.11.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:5.2.0'
|
||||
|
||||
androidTestUtil 'androidx.test:orchestrator:1.4.2'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
v4.3.1: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Setting to skip voice announcements on device speaker
|
||||
|
||||
Bugfix:
|
||||
- GPS disabled warning was falsely shown
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
||||
Vendored
+8
-6
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
+4
-4
@@ -166,7 +166,7 @@ public class ExportImportTest {
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:02:18Z");
|
||||
BluetoothRemoteSensorManager mockRemoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class);
|
||||
trackPointCreator.setRemoteSensorManager(mockRemoteSensorManager);
|
||||
trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager);
|
||||
service.endCurrentTrack();
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:03:20Z");
|
||||
@@ -179,7 +179,7 @@ public class ExportImportTest {
|
||||
sendLocation(trackPointCreator, "2020-02-02T02:03:23Z", 3, 16.001, 10, 27, 15, 10, 0);
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:03:24Z");
|
||||
trackPointCreator.setRemoteSensorManager(mockRemoteSensorManager);
|
||||
trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager);
|
||||
service.endCurrentTrack();
|
||||
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
@@ -521,12 +521,12 @@ public class ExportImportTest {
|
||||
sensorDataSet.fillTrackPoint(trackPoint);
|
||||
return sensorDataSet;
|
||||
});
|
||||
trackPointCreator.setRemoteSensorManager(remoteSensorManager);
|
||||
trackPointCreator.getSensorManager().setBluetoothSensorManager(remoteSensorManager);
|
||||
trackPointCreator.onChange(new SensorDataSet());
|
||||
}
|
||||
|
||||
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
|
||||
AltitudeSumManager altitudeSumManager = trackPointCreator.getAltitudeSumManager();
|
||||
AltitudeSumManager altitudeSumManager = trackPointCreator.getSensorManager().getAltitudeSumManager();
|
||||
altitudeSumManager.setAltitudeGain_m(altitudeGain);
|
||||
altitudeSumManager.setAltitudeLoss_m(altitudeGain);
|
||||
}
|
||||
|
||||
+20
-17
@@ -45,6 +45,8 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
/**
|
||||
* Tests insert location.
|
||||
* Note: on API23, the TrackRecordingService may not be stopped properly before the next test.
|
||||
* So, if something fails, subsequent tests may be affected.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackRecordingServiceTestRecording {
|
||||
@@ -112,7 +114,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
String startTime = "2020-02-02T02:02:02Z";
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, startTime, 0, 0, 0, 0, null, null)
|
||||
@@ -149,7 +151,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String pauseTime = "2020-02-02T02:02:03Z";
|
||||
@@ -195,7 +197,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
String starTime = "2020-02-02T02:02:02Z";
|
||||
trackPointCreator.setClock(starTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
String pauseTime = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(pauseTime);
|
||||
@@ -227,7 +229,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
String stopTime = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(stopTime);
|
||||
@@ -237,7 +239,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
String resumeTime = "2020-02-02T02:02:04Z";
|
||||
trackPointCreator.setClock(resumeTime);
|
||||
service.resumeTrack(trackId);
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// then
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
@@ -258,12 +260,13 @@ public class TrackRecordingServiceTestRecording {
|
||||
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getRemoteSensorManager();
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getSensorManager().getBluetoothSensorManager();
|
||||
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
|
||||
remoteSensorManager.onChanged(new SensorDataHeartRate("", "", HeartRate.of(5))); //Should be ignored
|
||||
|
||||
String sensor3 = "2020-02-02T02:02:13Z";
|
||||
@@ -297,7 +300,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
|
||||
// when
|
||||
@@ -371,7 +374,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -436,7 +439,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -500,7 +503,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -564,7 +567,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -652,7 +655,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -702,7 +705,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -748,7 +751,7 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
@@ -812,8 +815,8 @@ public class TrackRecordingServiceTestRecording {
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.setAltitudeSumManager(altitudeSumManager);
|
||||
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getRemoteSensorManager();
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getSensorManager().getBluetoothSensorManager();
|
||||
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
|
||||
-14
@@ -1,17 +1,12 @@
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
|
||||
import androidx.test.rule.ServiceTestRule;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
@@ -24,15 +19,6 @@ public class TrackRecordingServiceTestUtils {
|
||||
public static void resetService(ServiceTestRule mServiceRule, Context context) throws TimeoutException {
|
||||
// Let's use default values.
|
||||
PreferencesUtils.clear();
|
||||
|
||||
// Reset service (if some previous test failed)
|
||||
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
||||
.getService();
|
||||
|
||||
BluetoothRemoteSensorManager remoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class);
|
||||
service.getTrackPointCreator().setRemoteSensorManager(remoteSensorManager);
|
||||
service.getTrackPointCreator().setClock(Clock.systemUTC());
|
||||
service.endCurrentTrack();
|
||||
}
|
||||
|
||||
static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) {
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GPSHandlerTest {
|
||||
public class GPSManagerTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@@ -34,7 +34,7 @@ public class GPSHandlerTest {
|
||||
private TrackPointCreator trackPointCreator;
|
||||
|
||||
@InjectMocks
|
||||
private GPSHandler locationHandler;
|
||||
private GPSManager locationHandler;
|
||||
|
||||
@BeforeClass
|
||||
public static void preSetUp() {
|
||||
@@ -50,7 +50,7 @@ public class GPSHandlerTest {
|
||||
Mockito.when(trackPointCreator.createNow())
|
||||
.thenReturn(Instant.now());
|
||||
|
||||
locationHandler.onStart(context, new Handler());
|
||||
locationHandler.start(context, new Handler());
|
||||
}
|
||||
|
||||
/**
|
||||
+1
-1
@@ -25,7 +25,7 @@ public class TrackPointCreatorTest {
|
||||
private TrackPointCreator.Callback server;
|
||||
|
||||
@Mock
|
||||
private GPSHandler locationHandler;
|
||||
private GPSManager locationHandler;
|
||||
|
||||
private TrackPointCreator subject;
|
||||
|
||||
|
||||
@@ -381,13 +381,18 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
}
|
||||
|
||||
private void onGpsStatusChanged(GpsStatusValue gpsStatusValue) {
|
||||
if (gpsStatusValue.isGpsStarted() && snackbar != null && snackbar.isShown()) {
|
||||
snackbar.dismiss();
|
||||
boolean snackbarShowing = snackbar != null && snackbar.isShown();
|
||||
if (gpsStatusValue.isGpsStarted()) {
|
||||
if (snackbarShowing) {
|
||||
snackbar.dismiss();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (gpsStatusValue != GpsStatusValue.GPS_DISABLED) {
|
||||
|
||||
if (snackbarShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
snackbar = Snackbar
|
||||
.make(viewBinding.trackRecordingCoordinatorLayout,
|
||||
getString(R.string.gps_recording_status, getString(gpsStatusValue.message), getString(R.string.gps_recording_without_signal)),
|
||||
|
||||
@@ -162,7 +162,7 @@ public class StatisticsRecordingFragment extends Fragment {
|
||||
|
||||
viewBinding.statsLayout.addView(viewHolder.getView(), param);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException("Could not add " + dataField.getKey(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -40,9 +40,9 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorData;
|
||||
* Manages connection to a Bluetooth LE sensor and subscribes for onChange-notifications.
|
||||
* Also parses the transferred data into {@link SensorDataObserver}.
|
||||
*/
|
||||
public abstract class BluetoothConnectionManager<DataType> {
|
||||
public abstract class AbstractBluetoothConnectionManager<DataType> {
|
||||
|
||||
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
|
||||
private static final String TAG = AbstractBluetoothConnectionManager.class.getSimpleName();
|
||||
|
||||
private final SensorDataObserver observer;
|
||||
|
||||
@@ -136,12 +136,12 @@ public abstract class BluetoothConnectionManager<DataType> {
|
||||
}
|
||||
};
|
||||
|
||||
BluetoothConnectionManager(ServiceMeasurementUUID serviceUUUID, SensorDataObserver observer) {
|
||||
AbstractBluetoothConnectionManager(ServiceMeasurementUUID serviceUUUID, SensorDataObserver observer) {
|
||||
this.serviceMeasurementUUIDs = List.of(serviceUUUID);
|
||||
this.observer = observer;
|
||||
}
|
||||
|
||||
BluetoothConnectionManager(List<ServiceMeasurementUUID> serviceUUUID, SensorDataObserver observer) {
|
||||
AbstractBluetoothConnectionManager(List<ServiceMeasurementUUID> serviceUUUID, SensorDataObserver observer) {
|
||||
this.serviceMeasurementUUIDs = serviceUUUID;
|
||||
this.observer = observer;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
/**
|
||||
* Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer).
|
||||
*/
|
||||
public class AltitudeSumManager implements SensorEventListener {
|
||||
public class AltitudeSumManager implements SensorConnector, SensorEventListener {
|
||||
|
||||
private static final String TAG = AltitudeSumManager.class.getSimpleName();
|
||||
|
||||
|
||||
+3
-3
@@ -8,11 +8,11 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
|
||||
|
||||
public class BluetoothRemoteSensorManagerCyclingCadence extends BluetoothConnectionManager<Cadence> {
|
||||
public class BluetoothConnectionManagerCyclingCadence extends AbstractBluetoothConnectionManager<Cadence> {
|
||||
|
||||
private static final String TAG = BluetoothRemoteSensorManagerCyclingCadence.class.getSimpleName();
|
||||
private static final String TAG = BluetoothConnectionManagerCyclingCadence.class.getSimpleName();
|
||||
|
||||
BluetoothRemoteSensorManagerCyclingCadence(SensorDataObserver observer) {
|
||||
BluetoothConnectionManagerCyclingCadence(SensorDataObserver observer) {
|
||||
super(BluetoothUtils.CYCLING_CADENCE, observer);
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed;
|
||||
|
||||
public class BluetoothRemoteSensorManagerCyclingDistanceSpeed extends BluetoothConnectionManager<SensorDataCyclingDistanceSpeed.Data> {
|
||||
public class BluetoothConnectionManagerCyclingDistanceSpeed extends AbstractBluetoothConnectionManager<SensorDataCyclingDistanceSpeed.Data> {
|
||||
|
||||
BluetoothRemoteSensorManagerCyclingDistanceSpeed(SensorDataObserver observer) {
|
||||
BluetoothConnectionManagerCyclingDistanceSpeed(SensorDataObserver observer) {
|
||||
super(BluetoothUtils.CYCLING_SPEED_CADENCE, observer);
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ import androidx.annotation.NonNull;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
|
||||
|
||||
public class BluetoothRemoteSensorManagerCyclingPower extends BluetoothConnectionManager<Power> {
|
||||
public class BluetoothConnectionManagerCyclingPower extends AbstractBluetoothConnectionManager<Power> {
|
||||
|
||||
BluetoothRemoteSensorManagerCyclingPower(@NonNull SensorDataObserver observer) {
|
||||
BluetoothConnectionManagerCyclingPower(@NonNull SensorDataObserver observer) {
|
||||
super(BluetoothUtils.CYCLING_POWER, observer);
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ import androidx.annotation.NonNull;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate;
|
||||
|
||||
public class BluetoothRemoteSensorManagerHeartRate extends BluetoothConnectionManager<HeartRate> {
|
||||
public class BluetoothConnectionManagerHeartRate extends AbstractBluetoothConnectionManager<HeartRate> {
|
||||
|
||||
BluetoothRemoteSensorManagerHeartRate(@NonNull SensorDataObserver observer) {
|
||||
BluetoothConnectionManagerHeartRate(@NonNull SensorDataObserver observer) {
|
||||
super(BluetoothUtils.HEARTRATE, observer);
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,9 +6,9 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
|
||||
|
||||
public class BluetoothRemoteSensorManagerRunningSpeedAndCadence extends BluetoothConnectionManager<SensorDataRunning.Data> {
|
||||
public class BluetoothConnectionRunningSpeedAndCadence extends AbstractBluetoothConnectionManager<SensorDataRunning.Data> {
|
||||
|
||||
BluetoothRemoteSensorManagerRunningSpeedAndCadence(@NonNull SensorDataObserver observer) {
|
||||
BluetoothConnectionRunningSpeedAndCadence(@NonNull SensorDataObserver observer) {
|
||||
super(BluetoothUtils.RUNNING_SPEED_CADENCE, observer);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ import de.dennisguse.opentracks.util.PermissionRequester;
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.SensorDataObserver {
|
||||
public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBluetoothConnectionManager.SensorDataObserver {
|
||||
|
||||
private static final String TAG = BluetoothRemoteSensorManager.class.getSimpleName();
|
||||
|
||||
@@ -65,15 +65,15 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
|
||||
|
||||
private Distance preferenceWheelCircumference;
|
||||
|
||||
private final BluetoothRemoteSensorManagerHeartRate heartRate = new BluetoothRemoteSensorManagerHeartRate(this);
|
||||
private final BluetoothRemoteSensorManagerCyclingCadence cyclingCadence = new BluetoothRemoteSensorManagerCyclingCadence(this);
|
||||
private final BluetoothRemoteSensorManagerCyclingDistanceSpeed cyclingSpeed = new BluetoothRemoteSensorManagerCyclingDistanceSpeed(this);
|
||||
private final BluetoothRemoteSensorManagerCyclingPower cyclingPower = new BluetoothRemoteSensorManagerCyclingPower(this);
|
||||
private final BluetoothRemoteSensorManagerRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothRemoteSensorManagerRunningSpeedAndCadence(this);
|
||||
private final BluetoothConnectionManagerHeartRate heartRate = new BluetoothConnectionManagerHeartRate(this);
|
||||
private final BluetoothConnectionManagerCyclingCadence cyclingCadence = new BluetoothConnectionManagerCyclingCadence(this);
|
||||
private final BluetoothConnectionManagerCyclingDistanceSpeed cyclingSpeed = new BluetoothConnectionManagerCyclingDistanceSpeed(this);
|
||||
private final BluetoothConnectionManagerCyclingPower cyclingPower = new BluetoothConnectionManagerCyclingPower(this);
|
||||
private final BluetoothConnectionRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothConnectionRunningSpeedAndCadence(this);
|
||||
|
||||
private final SensorDataSet sensorDataSet = new SensorDataSet();
|
||||
|
||||
private final SensorDataSetChangeObserver observer;
|
||||
private final SensorManager.SensorDataSetChangeObserver observer;
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
@@ -114,21 +114,23 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
|
||||
}
|
||||
};
|
||||
|
||||
public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @NonNull SensorDataSetChangeObserver observer) {
|
||||
public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @NonNull SensorManager.SensorDataSetChangeObserver observer) {
|
||||
this.context = context;
|
||||
this.handler = handler;
|
||||
this.observer = observer;
|
||||
bluetoothAdapter = BluetoothUtils.getAdapter(context);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@Override
|
||||
public void start(Context context, Handler handler) {
|
||||
started = true;
|
||||
|
||||
//Registering triggers connection startup
|
||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
@Override
|
||||
public synchronized void stop(Context context) {
|
||||
heartRate.disconnect();
|
||||
cyclingCadence.disconnect();
|
||||
cyclingSpeed.disconnect();
|
||||
@@ -145,7 +147,7 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
|
||||
return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
|
||||
}
|
||||
|
||||
private synchronized void connect(BluetoothConnectionManager<?> connectionManager, String address) {
|
||||
private synchronized void connect(AbstractBluetoothConnectionManager<?> connectionManager, String address) {
|
||||
if (!isEnabled()) {
|
||||
Log.w(TAG, "Bluetooth not enabled.");
|
||||
return;
|
||||
@@ -230,8 +232,4 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
|
||||
public Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public interface SensorDataSetChangeObserver {
|
||||
void onChange(SensorDataSet sensorDataSet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.dennisguse.opentracks.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
public interface SensorConnector {
|
||||
|
||||
void start(Context context, Handler handler);
|
||||
|
||||
void stop(Context context);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package de.dennisguse.opentracks.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
|
||||
public class SensorManager {
|
||||
|
||||
private static final String TAG = SensorManager.class.getSimpleName();
|
||||
|
||||
private BluetoothRemoteSensorManager bluetoothSensorManager;
|
||||
|
||||
private AltitudeSumManager altitudeSumManager;
|
||||
|
||||
public SensorManager(Context context, Handler handler, SensorDataSetChangeObserver observer) {
|
||||
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, observer);
|
||||
altitudeSumManager = new AltitudeSumManager();
|
||||
}
|
||||
|
||||
public void start(Context context, Handler handler) {
|
||||
bluetoothSensorManager.start(context, handler);
|
||||
altitudeSumManager.start(context, handler);
|
||||
}
|
||||
|
||||
public void stop(Context context) {
|
||||
if (bluetoothSensorManager != null) {
|
||||
bluetoothSensorManager.stop(context);
|
||||
bluetoothSensorManager = null;
|
||||
}
|
||||
|
||||
if (altitudeSumManager != null) {
|
||||
altitudeSumManager.stop(context);
|
||||
altitudeSumManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
public SensorDataSet fill(TrackPoint trackPoint) {
|
||||
altitudeSumManager.fill(trackPoint);
|
||||
return bluetoothSensorManager.fill(trackPoint);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (bluetoothSensorManager == null || altitudeSumManager == null) {
|
||||
Log.d(TAG, "No recording running and no reset necessary.");
|
||||
return;
|
||||
}
|
||||
bluetoothSensorManager.reset();
|
||||
altitudeSumManager.reset();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public BluetoothRemoteSensorManager getBluetoothSensorManager() {
|
||||
return bluetoothSensorManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public void setBluetoothSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
|
||||
this.bluetoothSensorManager = remoteSensorManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public AltitudeSumManager getAltitudeSumManager() {
|
||||
return altitudeSumManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public void setAltitudeSumManager(AltitudeSumManager altitudeSumManager) {
|
||||
this.altitudeSumManager = altitudeSumManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public interface SensorDataSetChangeObserver {
|
||||
void onChange(SensorDataSet sensorDataSet);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -32,16 +31,6 @@ public abstract class SensorData<T> {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getSensorAddress() {
|
||||
return sensorAddress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSensorName() {
|
||||
return sensorName;
|
||||
}
|
||||
|
||||
public String getSensorNameOrAddress() {
|
||||
return sensorName != null ? sensorName : sensorAddress;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
egm2008CorrectionManager = new EGM2008CorrectionManager();
|
||||
trackRecordingManager = new TrackRecordingManager(this);
|
||||
trackRecordingManager.start();
|
||||
trackPointCreator = new TrackPointCreator(this);
|
||||
trackPointCreator = new TrackPointCreator(this, this, handler);
|
||||
|
||||
voiceAnnouncementManager = new VoiceAnnouncementManager(this);
|
||||
notificationManager = new TrackRecordingServiceNotificationManager(this);
|
||||
@@ -177,7 +177,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
|
||||
public void resumeTrack(Track.Id trackId) {
|
||||
trackPointCreator.reset();
|
||||
if (!trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator)) {
|
||||
Log.w(TAG, "Cannot resume a non-existing track.");
|
||||
return;
|
||||
@@ -328,7 +327,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
TrackPoint trackPoint = data.second.first;
|
||||
egm2008CorrectionManager.correctAltitude(this, trackPoint);
|
||||
|
||||
localVoiceAnnouncementManager.update(data.first);
|
||||
localVoiceAnnouncementManager.update(this, data.first);
|
||||
|
||||
recordingDataObservable.postValue(new RecordingData(data.first, trackPoint, data.second.second));
|
||||
}
|
||||
|
||||
+11
-1
@@ -15,12 +15,14 @@
|
||||
*/
|
||||
package de.dennisguse.opentracks.services.announcement;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.mediarouter.media.MediaRouter;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -73,12 +75,20 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
updateNextTaskDistance();
|
||||
}
|
||||
|
||||
public void update(@NonNull Track track) {
|
||||
public void update(@NonNull Context context, @NonNull Track track) {
|
||||
if (voiceAnnouncement == null) {
|
||||
Log.e(TAG, "Cannot update when in status shutdown.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PreferencesUtils.shouldVoiceAnnouncementOnDeviceSpeaker()
|
||||
&& MediaRouter.getInstance(context)
|
||||
.getSelectedRoute()
|
||||
.isDeviceSpeaker()) {
|
||||
Log.i(TAG, "No voice announcement on device speaker.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean announce = false;
|
||||
this.trackStatistics = track.getTrackStatistics();
|
||||
if (trackStatistics.getTotalDistance().greaterThan(nextTotalDistance)) {
|
||||
|
||||
+6
-5
@@ -20,14 +20,15 @@ import java.time.Instant;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.SensorConnector;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.PermissionRequester;
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
public class GPSManager implements SensorConnector, LocationListenerCompat, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private final String TAG = GPSHandler.class.getSimpleName();
|
||||
private final String TAG = GPSManager.class.getSimpleName();
|
||||
|
||||
public static final String LOCATION_PROVIDER = LocationManager.GPS_PROVIDER;
|
||||
|
||||
@@ -40,11 +41,11 @@ public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusLi
|
||||
private Duration gpsInterval;
|
||||
private Distance thresholdHorizontalAccuracy;
|
||||
|
||||
public GPSHandler(TrackPointCreator trackPointCreator) {
|
||||
public GPSManager(TrackPointCreator trackPointCreator) {
|
||||
this.trackPointCreator = trackPointCreator;
|
||||
}
|
||||
|
||||
public void onStart(@NonNull Context context, @NonNull Handler handler) {
|
||||
public void start(@NonNull Context context, @NonNull Handler handler) {
|
||||
this.context = context;
|
||||
this.handler = handler;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusLi
|
||||
|
||||
@SuppressWarnings({"MissingPermission"})
|
||||
//TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates.
|
||||
public void onStop() {
|
||||
public void stop(Context context) {
|
||||
if (locationManager != null && context != null) {
|
||||
if (PermissionRequester.GPS.hasPermission(context)) {
|
||||
LocationManagerCompat.removeUpdates(locationManager, this);
|
||||
@@ -16,14 +16,13 @@ import java.time.ZoneId;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.AltitudeSumManager;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
|
||||
import de.dennisguse.opentracks.sensors.SensorManager;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
|
||||
/**
|
||||
* Creates TrackPoints while recording by fusing data from different sensors (e.g., GNSS, barometer, BLE sensors).
|
||||
*/
|
||||
public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDataSetChangeObserver {
|
||||
public class TrackPointCreator implements SensorManager.SensorDataSetChangeObserver {
|
||||
|
||||
private static final String TAG = TrackPointCreator.class.getSimpleName();
|
||||
|
||||
@@ -34,45 +33,34 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
@NonNull
|
||||
private Clock clock = new MonotonicClock();
|
||||
|
||||
private final GPSHandler gpsHandler;
|
||||
private BluetoothRemoteSensorManager remoteSensorManager;
|
||||
private AltitudeSumManager altitudeSumManager;
|
||||
private final GPSManager gpsManager;
|
||||
private SensorManager sensorManager;
|
||||
|
||||
public TrackPointCreator(Callback service) {
|
||||
public TrackPointCreator(Callback service, Context context, Handler handler) {
|
||||
this.service = service;
|
||||
this.gpsHandler = new GPSHandler(this);
|
||||
this.gpsManager = new GPSManager(this);
|
||||
this.sensorManager = new SensorManager(context, handler, this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TrackPointCreator(GPSHandler gpsHandler, Callback service) {
|
||||
TrackPointCreator(GPSManager gpsManager, Callback service) {
|
||||
this.service = service;
|
||||
this.gpsHandler = gpsHandler;
|
||||
this.gpsManager = gpsManager;
|
||||
}
|
||||
|
||||
public synchronized void start(@NonNull Context context, @NonNull Handler handler) {
|
||||
this.context = context;
|
||||
|
||||
gpsHandler.onStart(context, handler);
|
||||
|
||||
remoteSensorManager = new BluetoothRemoteSensorManager(context, handler, this);
|
||||
altitudeSumManager = new AltitudeSumManager();
|
||||
|
||||
remoteSensorManager.start();
|
||||
altitudeSumManager.start(context, handler);
|
||||
|
||||
gpsManager.start(context, handler);
|
||||
sensorManager.start(context, handler);
|
||||
}
|
||||
|
||||
private boolean isStarted() {
|
||||
return context != null;
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
if (remoteSensorManager == null || altitudeSumManager == null) {
|
||||
Log.d(TAG, "No recording running and no reset necessary.");
|
||||
return;
|
||||
}
|
||||
remoteSensorManager.reset();
|
||||
altitudeSumManager.reset();
|
||||
private synchronized void reset() {
|
||||
sensorManager.reset();
|
||||
}
|
||||
|
||||
private SensorDataSet addSensorData(TrackPoint trackPoint) {
|
||||
@@ -80,31 +68,12 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
Log.w(TAG, "Not started, should not be called.");
|
||||
return null;
|
||||
}
|
||||
SensorDataSet sensorDataSet = null;
|
||||
BluetoothRemoteSensorManager localRemoteSensorManager = remoteSensorManager;
|
||||
if (localRemoteSensorManager != null) {
|
||||
sensorDataSet = localRemoteSensorManager.fill(trackPoint);
|
||||
}
|
||||
AltitudeSumManager localAltitudeSumManager = altitudeSumManager;
|
||||
if (localAltitudeSumManager != null) {
|
||||
localAltitudeSumManager.fill(trackPoint);
|
||||
}
|
||||
|
||||
return sensorDataSet;
|
||||
return sensorManager.fill(trackPoint);
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
gpsHandler.onStop();
|
||||
|
||||
if (remoteSensorManager != null) {
|
||||
remoteSensorManager.stop();
|
||||
remoteSensorManager = null;
|
||||
}
|
||||
|
||||
if (altitudeSumManager != null) {
|
||||
altitudeSumManager.stop(context);
|
||||
altitudeSumManager = null;
|
||||
}
|
||||
gpsManager.stop(context);
|
||||
|
||||
this.context = null;
|
||||
}
|
||||
@@ -125,7 +94,7 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
public void onNewTrackPoint(@NonNull TrackPoint trackPoint) {
|
||||
addSensorData(trackPoint);
|
||||
|
||||
boolean stored = service.newTrackPoint(trackPoint, gpsHandler.getThresholdHorizontalAccuracy());
|
||||
boolean stored = service.newTrackPoint(trackPoint, gpsManager.getThresholdHorizontalAccuracy());
|
||||
if (stored) {
|
||||
reset();
|
||||
}
|
||||
@@ -169,26 +138,8 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public AltitudeSumManager getAltitudeSumManager() {
|
||||
return altitudeSumManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public void setAltitudeSumManager(AltitudeSumManager altitudeSumManager) {
|
||||
this.altitudeSumManager = altitudeSumManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public BluetoothRemoteSensorManager getRemoteSensorManager() {
|
||||
return remoteSensorManager;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
|
||||
this.remoteSensorManager = remoteSensorManager;
|
||||
public SensorManager getSensorManager() {
|
||||
return sensorManager;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -202,8 +153,8 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public GPSHandler getGpsHandler() {
|
||||
return gpsHandler;
|
||||
public GPSManager getGpsHandler() {
|
||||
return gpsManager;
|
||||
}
|
||||
|
||||
void sendGpsStatus(GpsStatusValue gpsStatusValue) {
|
||||
|
||||
@@ -302,6 +302,11 @@ public class PreferencesUtils {
|
||||
return getBoolean(R.string.stats_fullscreen_while_recording_key, DEFAULT);
|
||||
}
|
||||
|
||||
public static boolean shouldVoiceAnnouncementOnDeviceSpeaker() {
|
||||
final boolean DEFAULT = resources.getBoolean(R.bool.voice_on_device_speaker_default);
|
||||
return getBoolean(R.string.voice_on_device_speaker_key, DEFAULT);
|
||||
}
|
||||
|
||||
public static Duration getVoiceAnnouncementFrequency() {
|
||||
final int DEFAULT = Integer.parseInt(resources.getString(R.string.voice_announcement_frequency_default));
|
||||
int value = getInt(R.string.voice_announcement_frequency_key, DEFAULT);
|
||||
|
||||
@@ -87,4 +87,14 @@ public class DataField implements Parcelable {
|
||||
public int hashCode() {
|
||||
return Objects.hash(key, isVisible, isPrimary, isWide);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataField{" +
|
||||
"key='" + key + '\'' +
|
||||
", isVisible=" + isVisible +
|
||||
", isPrimary=" + isPrimary +
|
||||
", isWide=" + isWide +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,15 @@ package de.dennisguse.opentracks.viewmodels;
|
||||
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||
import de.dennisguse.opentracks.data.models.HeartRateZones;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.databinding.StatsGenericItemBinding;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
@@ -256,84 +253,4 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_coordinates);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorHeartRate extends GenericStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
//TODO Loads preference every time
|
||||
HeartRateZones zones = PreferencesUtils.getHeartRateZones();
|
||||
int textColor;
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getHeartRate() != null) {
|
||||
valueAndUnit = StringUtils.getHeartRateParts(getContext(), sensorDataSet.getHeartRate().first);
|
||||
sensorName = sensorDataSet.getHeartRate().second;
|
||||
textColor = zones.getTextColorForZone(getContext(), sensorDataSet.getHeartRate().first);
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getHeartRateParts(getContext(), null);
|
||||
textColor = zones.getTextColorForZone(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_heart_rate);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setVisibility(View.VISIBLE);
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
|
||||
getBinding().statsValue.setTextColor(textColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorCadence extends GenericStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getCadence() != null) {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), sensorDataSet.getCadence().first);
|
||||
sensorName = sensorDataSet.getCadence().second;
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_cadence);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setVisibility(View.VISIBLE);
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorPower extends GenericStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingPower() != null) {
|
||||
valueAndUnit = StringUtils.getPowerParts(getContext(), sensorDataSet.getCyclingPower().getValue());
|
||||
sensorName = sensorDataSet.getCyclingPower().getSensorNameOrAddress();
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_power);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setVisibility(View.VISIBLE);
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ public class Mapping {
|
||||
m.put(context.getString(R.string.stats_custom_layout_loss_key), GenericStatisticsViewHolder.Loss::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_coordinates_key), GenericStatisticsViewHolder.Coordinates::new);
|
||||
|
||||
m.put(context.getString(R.string.stats_custom_layout_heart_rate_key), GenericStatisticsViewHolder.SensorHeartRate::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_cadence_key), GenericStatisticsViewHolder.SensorCadence::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_power_key), GenericStatisticsViewHolder.SensorPower::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_heart_rate_key), SensorStatisticsViewHolder.SensorHeartRate::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_cadence_key), SensorStatisticsViewHolder.SensorCadence::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_power_key), SensorStatisticsViewHolder.SensorPower::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_clock_key), ClockViewHolder::new);
|
||||
|
||||
return m;
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package de.dennisguse.opentracks.viewmodels;
|
||||
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.HeartRateZones;
|
||||
import de.dennisguse.opentracks.databinding.StatsSensorItemBinding;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
public abstract class SensorStatisticsViewHolder extends StatisticViewHolder<StatsSensorItemBinding> {
|
||||
|
||||
@Override
|
||||
protected StatsSensorItemBinding createViewBinding(LayoutInflater inflater) {
|
||||
return StatsSensorItemBinding.inflate(inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureUI(DataField dataField) {
|
||||
getBinding().statsValue.setTextAppearance(getContext(), dataField.isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryValue : R.style.TextAppearance_OpenTracks_SecondaryValue);
|
||||
getBinding().statsDescriptionMain.setTextAppearance(getContext(), dataField.isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryHeader : R.style.TextAppearance_OpenTracks_SecondaryHeader);
|
||||
}
|
||||
|
||||
public static class SensorHeartRate extends SensorStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getHeartRate() != null) {
|
||||
valueAndUnit = StringUtils.getHeartRateParts(getContext(), sensorDataSet.getHeartRate().first);
|
||||
sensorName = sensorDataSet.getHeartRate().second;
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getHeartRateParts(getContext(), null);
|
||||
}
|
||||
|
||||
//TODO Loads preference every time
|
||||
HeartRateZones zones = PreferencesUtils.getHeartRateZones();
|
||||
int textColor;
|
||||
if (sensorDataSet != null && sensorDataSet.getHeartRate() != null) {
|
||||
textColor = zones.getTextColorForZone(getContext(), sensorDataSet.getHeartRate().first);
|
||||
} else {
|
||||
textColor = zones.getTextColorForZone(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_heart_rate);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
|
||||
getBinding().statsValue.setTextColor(textColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorCadence extends SensorStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getCadence() != null) {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), sensorDataSet.getCadence().first);
|
||||
sensorName = sensorDataSet.getCadence().second;
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_cadence);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorPower extends SensorStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.getSensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingPower() != null) {
|
||||
valueAndUnit = StringUtils.getPowerParts(getContext(), sensorDataSet.getCyclingPower().getValue());
|
||||
sensorName = sensorDataSet.getCyclingPower().getSensorNameOrAddress();
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getCadenceParts(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_power);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_value"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintEnd_toStartOf="@id/stats_unit"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="90" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_unit"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryUnit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@id/stats_value"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/stats_value"
|
||||
tools:text="@string/sensor_unit_beats_per_minute" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_description_main"
|
||||
style="@style/TextAppearance.OpenTracks.PrimaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_value"
|
||||
tools:text="@string/sensor_state_heart_rate" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_description_secondary"
|
||||
style="@style/TextAppearance.OpenTracks.SecondaryHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_description_main"
|
||||
tools:text="90" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -14,40 +14,38 @@ 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">Acerca de OpenTracks</string>
|
||||
<string name="about_description"><i>OpenTracks</i> é unha aplicación para rexistrar as túas actividades deportivas que respecta a túa privacidade.</string>
|
||||
<string name="about_preference_title">Sobre OpenTracks</string>
|
||||
<string name="about_description"><i>OpenTracks</i> é unha aplicación para rexistrar actividades deportivas que respecta a túa privacidade.</string>
|
||||
<string name="about_url">Web do proxecto: <a href="%1$s">%1$s</a></string>
|
||||
<string name="about_version_name">Nome da versión: %1$s</string>
|
||||
<string name="about_version_code">Código da versión: %1$d</string>
|
||||
<string name="about_history">OpenTracks é un fork de <a href="https://code.google.com/archive/p/mytracks/"><i>MyTracks de Google</i></a>(abandonado en 2016).</string>
|
||||
<string name="about_history">OpenTracks é unha bifurcación de <a href="https://code.google.com/archive/p/mytracks/"><i>MyTracks de Google</i></a> (abandonado en 2016).</string>
|
||||
<string name="about_libraries">Bibliotecas</string>
|
||||
<!-- Help -->
|
||||
<string name="help_feature_title">OpenTracks ten as seguintes funcións:</string>
|
||||
<string name="help_feature_content">
|
||||
* crea rutas GPS\n
|
||||
* usa monitor do pulso cardíaco (só Bluetooth LE)\n
|
||||
* anuncios por voz (de tempo ou distancia)\n
|
||||
* crea marcadores (incl. fotos)\n
|
||||
* funciona sen precisar conexión a rede\n
|
||||
* mostra as rutas nun mapa (ver abaixo)
|
||||
</string>
|
||||
<string name="help_track_map_title">¿Como mostrar a ruta nun mapa?</string>
|
||||
<string name="help_feature_title">Características de OpenTracks:</string>
|
||||
<string name="help_feature_content">* crear rutas GPS
|
||||
\n * usar monitor do pulso cardíaco (só Bluetooth LE)
|
||||
\n * anuncios por voz (de tempo ou distancia)
|
||||
\n * crear marcadores (incl. fotos)
|
||||
\n * funciona sen precisar conexión á rede
|
||||
\n * mostra as rutas nun mapa (ver abaixo)</string>
|
||||
<string name="help_track_map_title">Como mostrar a ruta no mapa\?</string>
|
||||
<string name="help_track_map_content"> Usa a icona do mapa pequeno.
|
||||
\n a) (actualizacións en directo) Instala <a href="https://github.com/OpenTracksApp/OSMDashboard"> OSMDashboard </a>. Ofrece mapas en liña ou fóra de liña a través de <a href="https://www.openstreetmap.org"> OpenStreetMap </a>.
|
||||
\n a) (actualizacións en directo) Instala <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>. Proporciona mapas en liña ou sen conexión grazas a <a href="https://www.openstreetmap.org">OpenStreetMap</a>.
|
||||
\n En realidade, OSMDashboard é unha aplicación independente que só pode acceder (temporalmente) aos datos das pistas que se amosarán.
|
||||
\n b) A través dunha aplicación de mapa normal (por exemplo, <a href="http://osmand.net/">OsmAnd</a> e <a href="https://maps.me/">MAPS.ME</a>). Estas aplicacións precisan admitir o formato de ficheiro KMZ (só localizacións e marcas de tempo). De feito, unha aplicación ten que admitir <i> ACTION_VIEW </i> con MIME <i>application/vnd.google-earth.kmz</i>. </string>
|
||||
<string name="help_storage_pictures_title">¿De que xeito garda OpenTracks as fotos tomadas como marcadores?</string>
|
||||
<string name="help_storage_pictures_content">Gárdanse no almacenaxe interno da app (só accesible desde OpenTracks).</string>
|
||||
<string name="help_track_export_title">¿De que xeito exporto/importo as rutas gravadas?</string>
|
||||
<string name="help_track_export_content"> As rutas pódense exportar desde os Axustes como KMZ, KML ou GPX. KMZ/KML inclúe todos os datos; GPX só localización. As ruts compartidas a través da <i>icona compartir</i> compártense como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">¿OpenTracks precisa/utiliza Google Play Service?</string>
|
||||
<string name="help_recording_title">¿Como grava OpenTracks os datos?</string>
|
||||
\n b) A través dunha aplicación de mapa normal (por exemplo, <a href="http://osmand.net/">OsmAnd</a> e <a href="https://maps.me/">MAPS.ME</a>). Estas aplicacións precisan admitir o formato de ficheiro KMZ (só localizacións e marcas de tempo). De feito, unha aplicación ten que admitir <i>ACTION_VIEW</i> con MIME <i>application/vnd.google-earth.kmz</i>. </string>
|
||||
<string name="help_storage_pictures_title">De que xeito garda OpenTracks as fotos tomadas como marcadores\?</string>
|
||||
<string name="help_storage_pictures_content">Gárdanse na almacenaxe interna da app (só accesible desde OpenTracks).</string>
|
||||
<string name="help_track_export_title">De que xeito exporto/importo as rutas gravadas\?</string>
|
||||
<string name="help_track_export_content"> As rutas pódense exportar desde os Axustes como KMZ, KML ou GPX. KMZ/KML inclúe todos os datos; GPX só localización. As rutas compartidas a través da <i>icona compartir</i> compártense como KMZ. </string>
|
||||
<string name="help_data_google_play_services_title">OpenTracks precisa/utiliza Google Play Service\?</string>
|
||||
<string name="help_recording_title">Como grava OpenTracks os datos\?</string>
|
||||
<string name="help_recording_content">
|
||||
OpenTracks usa o sensor GPS do dispositivo para gravar a localización de xeito contínuo.
|
||||
Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, elevación), OpenTracks non pode facer nada ao respecto.</string>
|
||||
<string name="help_data_storage_title">De que xeito garda OpenTracks os datos dos sensores\?</string>
|
||||
<string name="help_data_storage_content"> Os datos dos sensores gárdanse asociados á localización. Respecto do ritmo cardíaco, significa que só se garda <i>unha medida</i> asociada a unha localización. Se te detés ou estás en interiores, non se gardarán datos do sensor (mais serán mostrados). </string>
|
||||
<string name="help_gps_troubleshooting_title">¿OpenTracks non grava as localizacións?</string>
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks non grava as localizacións\?</string>
|
||||
<string name="help_gps_troubleshooting_content"> Podes intentar:
|
||||
\n a) mira que o GPS esté activado,
|
||||
\n b) mellora a recepción GPS (ex. sae ao exterior),
|
||||
@@ -55,7 +53,7 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
\n d) desactiva o aforro de enerxía.
|
||||
\n
|
||||
\n Se isto non axuda, infórmanos do problema. </string>
|
||||
<string name="help_support_title">¿Como podo axudar a OpenTracks?</string>
|
||||
<string name="help_support_title">Como podo axudar a OpenTracks\?</string>
|
||||
<string name="help_support_content"> Podes:
|
||||
\n a) falar de OpenTracks coas túas amizades,
|
||||
\n b) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">propoñer novas funcións</a>,
|
||||
@@ -154,7 +152,7 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="description_recorded_time">Hora da gravación: %1$s</string>
|
||||
<string name="description_speed_ms">Velocidade (m/s)</string>
|
||||
<string name="description_sensor_cadence">Cadencia (rpm)</string>
|
||||
<string name="description_sensor_heart_rate">Frecuencia cardíaca (pulsacións por minuto)</string>
|
||||
<string name="description_sensor_heart_rate">Pulso cardíaco (latexos por minuto)</string>
|
||||
<string name="description_sensor_power">Potencia (W)</string>
|
||||
<string name="description_default_speed_or_pace">Por tipo de actividade</string>
|
||||
<string name="description_speed_imperial">Velocidade (mi/h)</string>
|
||||
@@ -233,8 +231,8 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="permission_gps_failed">OpenTracks precisa permiso para usar o GPS.</string>
|
||||
<!-- Search -->
|
||||
<!-- Sensor State -->
|
||||
<string name="sensor_state_heart_rate">Frecuencia cardíaca</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d bpm</string>
|
||||
<string name="sensor_state_heart_rate">Pulso cardíaco</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d lpm</string>
|
||||
<string name="sensor_state_power">Potencia</string>
|
||||
<string name="sensor_could_not_scan">Non se escanearon dispositivos Bluetooth (fallo %1$i).</string>
|
||||
<string name="bluetooth_disabled">Activa o Bluetooth.</string>
|
||||
@@ -508,10 +506,10 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="value_float_kilometer_hour_recommended">%1$.1f km/h (recomendado)</string>
|
||||
<string name="stats_clock">Reloxo</string>
|
||||
<string name="settings_open_tracks_title">Open Tracks</string>
|
||||
<string name="settings_defaults_summary">O Preferido Unidades, Por Defecto Actividade, Controlar O Nome Por Defecto</string>
|
||||
<string name="settings_defaults_summary">Unidades preferidas, Actividade por defecto, Nome da ruta</string>
|
||||
<string name="settings_announcements_summary">A Distancia, Tempo, Voz Velocidade</string>
|
||||
<string name="settings_open_tracks_summary">Todo Sobre OpenTracks Proxecto</string>
|
||||
<string name="settings_defaults_title">Por defecto Unidades e Actividade</string>
|
||||
<string name="settings_defaults_title">Unidades e Actividade por defecto</string>
|
||||
<string name="settings_ui_title">Interface da app</string>
|
||||
<string name="settings_ui_summary">Aparencia, Gravación, Deseño, Tema</string>
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
@@ -523,7 +521,7 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="settings_import_export_summary">Importación, Exportación, Auto Exportación</string>
|
||||
<string name="settings_units_category">Unidades</string>
|
||||
<string name="settings_activity_defaults_category">Valores por defecto</string>
|
||||
<string name="settings_reset_summary">Axustar a Configuración de Valores por Defecto</string>
|
||||
<string name="settings_reset_summary">Restablecer Axustes dos Valores</string>
|
||||
<string name="menu_select_layout">Elixe disposición</string>
|
||||
<string name="custom_layout_list_title">Disposicións</string>
|
||||
<string name="custom_layout_list_edit_name">Escribe o nome da nova disposición</string>
|
||||
@@ -576,8 +574,8 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="gps_recording_status">%1$s: %2$s</string>
|
||||
<string name="gps_recording_without_signal">OpenTracks está gravando sen datos GPS.</string>
|
||||
<string name="settings_export_filename_title">Formato do nome do ficheiro</string>
|
||||
<string name="settings_announcements_lap_heart_rate">Ritmo cardíaco na volta</string>
|
||||
<string name="settings_announcements_average_heart_rate">Ritmo cardíaco medio</string>
|
||||
<string name="settings_announcements_lap_heart_rate">Pulso durante a volta</string>
|
||||
<string name="settings_announcements_average_heart_rate">Pulso cardíaco medio</string>
|
||||
<string name="image_discard">Descartar</string>
|
||||
<string name="settings_announcements_average_speed_pace">Velocidade/ritmo medio</string>
|
||||
<string name="settings_announcements_lap_speed_pace">Velocidade/ritmo da volta</string>
|
||||
@@ -611,4 +609,7 @@ Se o GPS informa sobre datos pouco precisos (ex.: localización, velocidade, ele
|
||||
<string name="settings_public_api_package_title">Nome do paquete para Public API</string>
|
||||
<string name="track_delete_number_of_tracks">%1$d rutas</string>
|
||||
<string name="introduction_osm_dashboard">OpenTracks non proporciona un mapa. Instala OSMDashboard para ver as gravacións nun mapa.</string>
|
||||
<string name="help_data_google_play_services_content">Non</string>
|
||||
<string name="settings_sensor_heart_rate_max">Zonas: Pulso máximo (lpm)</string>
|
||||
<string name="settings_api_summary">Control remoto e API de estatísticas para outras apps</string>
|
||||
</resources>
|
||||
@@ -1,5 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright 2010 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="about_preference_title">關於 OpenTracks</string>
|
||||
<string name="about_description"><i>OpenTracks</i> 是一個完全尊重您的隱私的運動蹤跡應用程式。</string>
|
||||
<string name="about_url">專案網頁:<a href="%1$s">%1$s</a></string>
|
||||
<string name="about_version_name">版本名稱:%1$s</string>
|
||||
<string name="about_version_code">版本代號:%1$d</string>
|
||||
<string name="about_history">OpenTracks 是一個 <a href="https://code.google.com/archive/p/mytracks/"><i>Google\'s MyTracks</i></a> 的分支 (於 2016 年停止維護)。</string>
|
||||
<string name="about_third_party_data">第三方資料</string>
|
||||
<string name="about_libraries">函式庫</string>
|
||||
<!-- Help -->
|
||||
<string name="help_feature_title">OpenTracks 擁有以下特點:</string>
|
||||
<string name="help_feature_content">
|
||||
* 建立 GPS 蹤跡\n
|
||||
* 使用一個心率感測器 (僅限藍牙 LE)\n
|
||||
* 語音通知 (依時間或距離)\n
|
||||
* 建立標記 (包含圖片)\n
|
||||
* 完全離線工作\n
|
||||
* 在地圖上顯示蹤跡 (見下文)
|
||||
</string>
|
||||
|
||||
<string name="help_track_map_title">如何在地圖顯示一個蹤跡?</string>
|
||||
<string name="help_track_map_content">
|
||||
使用小的地圖圖示。\n
|
||||
a)
|
||||
(即時更新) 安裝 <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>.
|
||||
透過 <a href="https://www.openstreetmap.org">OpenStreetMap</a> 提供線上或離線地圖。\n
|
||||
實際上,OSMDashboard 是一個單獨的應用程式,只能 (暫時) 存取將要顯示的蹤跡資料。
|
||||
|
||||
\n
|
||||
b)
|
||||
透過一個 "普通的" 地圖應用程式 (例如,<a href="http://osmand.net/">OsmAnd</a> 與 <a href="https://maps.me/">MAPS.ME</a>)。
|
||||
這些 APP 需要支援 KMZ 檔案格式 (只有位置與時間戳記)。
|
||||
事實上,APP 需要支援 <i>ACTION_VIEW</i> 與 MIME <i>application/vnd.google-earth.kmz</i>。
|
||||
</string>
|
||||
|
||||
<string name="help_storage_pictures_title">OpenTracks 如何存儲作為標記拍攝的照片?</string>
|
||||
<string name="help_storage_pictures_content">這些儲存在應用程序內部儲存區中 (即,只能在 OpenTracks 中存取)。</string>
|
||||
|
||||
<string name="help_track_export_title">如何匯出/分享 紀錄的蹤跡?</string>
|
||||
<string name="help_track_export_content">
|
||||
可以從設定匯出蹤跡為 KMZ、KML 或 GPX。
|
||||
KMZ/KML 全部資料;GPX 只有位置。
|
||||
通過<i>分享圖示</i>以分享蹤跡為 KMZ。
|
||||
</string>
|
||||
|
||||
<string name="help_data_google_play_services_title">OpenTracks 是否需要/使用 Google Play 服務?</string>
|
||||
<string name="help_data_google_play_services_content">否</string>
|
||||
|
||||
<string name="help_recording_title">OpenTracks 是如何記錄資料的?</string>
|
||||
<string name="help_recording_content">
|
||||
OpenTracks 使用裝置的 GPS 感測器以連續紀錄位置。
|
||||
如果 GPS 裝置回報的資料不准確 (例如,位置、速度、海拔),OpenTracks 對此無能為力。
|
||||
</string>
|
||||
|
||||
<string name="help_data_storage_title">OpenTracks 如何儲存感測器資料?</string>
|
||||
<string name="help_data_storage_content">
|
||||
感測器資料儲存在每個記錄的位置。
|
||||
就心率感測器而言,這意味著只有<i>一個</i>心率測量值被依照位置儲存。
|
||||
如果您是站著不動或在室內,沒有感測器資料會被記錄 (但它會被顯示)。
|
||||
</string>
|
||||
|
||||
<string name="help_gps_troubleshooting_title">OpenTracks 沒有紀錄位置?</string>
|
||||
<string name="help_gps_troubleshooting_content">
|
||||
您能做什麼:\n
|
||||
a) 檢查 GPS 是否啟用,\n
|
||||
b) 改善 GPS 收訊 (例如,前往戶外),\n
|
||||
c) 使用 <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a> app 檢查,以及\n
|
||||
d) 禁用省電。\n
|
||||
\n
|
||||
如果一切都沒有幫助,請回報 bug。
|
||||
</string>
|
||||
|
||||
<string name="help_support_title">我如何支持 OpenTracks?</string>
|
||||
<string name="help_support_content">
|
||||
您可以:\n
|
||||
a) 推廣 OpenTracks,\n
|
||||
b) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">提出建議</a>,\n
|
||||
c) <a href="https://github.com/OpenTracksApp/OpenTracks/issues">回報 bugs</a>,\n
|
||||
d) 幫助軟體開發,\n
|
||||
e) 在 <a href="https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore">Google Play 商店</a> 購買它,\n
|
||||
f) 贊助,以及\n
|
||||
g) 做任何您認為對 OpenTracks 有幫助的事情。
|
||||
</string>
|
||||
|
||||
<string name="open_track_as_KML">開啟為 KML</string>
|
||||
<string name="open_track_as_GPX">開啟為 GPX</string>
|
||||
<string name="open_track_as_trackfileformat">開啟為 %1$s</string>
|
||||
|
||||
<!-- Activity Type -->
|
||||
<string name="activity_type_airplane">飛機</string>
|
||||
<string name="activity_type_atv">越野車</string>
|
||||
<string name="activity_type_biking">騎自行車</string>
|
||||
@@ -14,6 +116,7 @@
|
||||
<string name="activity_type_driving">正在開車</string>
|
||||
<string name="activity_type_driving_bus">駕駛公車</string>
|
||||
<string name="activity_type_driving_car">駕車</string>
|
||||
<string name="activity_type_escooter">電動滑板車</string>
|
||||
<string name="activity_type_ferry">渡輪碼頭</string>
|
||||
<string name="activity_type_frisbee">飛盤</string>
|
||||
<string name="activity_type_gliding">滑翔</string>
|
||||
@@ -66,61 +169,131 @@
|
||||
<string name="activity_type_walking">步行</string>
|
||||
<string name="activity_type_water_skiing">滑水</string>
|
||||
<string name="activity_type_wind_surfing">風帆</string>
|
||||
<string name="activity_type_swimming">游泳</string>
|
||||
<string name="activity_type_swimming_open">開放水域游泳</string>
|
||||
<string name="activity_type_workout">訓練</string>
|
||||
<!-- Description -->
|
||||
<string name="description_activity_type">活動類型:%1$s</string>
|
||||
<string name="description_average_moving_pace_in_minute">平均移動速度:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_average_moving_pace_in_minute">平均移動步速:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_average_moving_speed">平均移動速度:%1$.2f 公里/小時 (%2$.1f 英里/小時)</string>
|
||||
<string name="description_average_pace_in_minute">平均速度:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_average_pace_in_minute">平均步速:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_average_speed">平均速度:%1$.2f 公里/小時 (%2$.1f 英里/小時)</string>
|
||||
<string name="description_altitude_gain">爬升高度:%1$d 公尺 (%2$d 英尺)</string>
|
||||
<string name="description_altitude_loss">下降高度:%1$d m (%2$d ft)</string>
|
||||
<string name="description_altitude_imperial">海拔高度 (英尺)</string>
|
||||
<string name="description_altitude_metric">海拔高度 (公尺)</string>
|
||||
<string name="description_fastest_pace_in_minute">最快速度:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_fastest_pace_in_minute">最高步速:%1$s 分鐘/公里 (%2$s 分鐘/英里)</string>
|
||||
<string name="description_max_altitude">最高海拔:%1$d 公尺 (%2$d 英尺)</string>
|
||||
<string name="description_max_speed">最快速度:%1$.2f 公里/小時 (%2$.1f 英里/小時)</string>
|
||||
<string name="description_max_speed">最高速度:%1$.2f 公里/小時 (%2$.1f 英里/小時)</string>
|
||||
<string name="description_min_altitude">最低海拔:%1$d 公尺 (%2$d 英尺)</string>
|
||||
<string name="description_moving_time">移動時間:%1$s</string>
|
||||
<string name="description_pace_imperial">速度 (分鐘/英里)</string>
|
||||
<string name="description_pace_metric">速度 (分鐘/公里)</string>
|
||||
<string name="description_pace_imperial">步速 (分鐘/英里)</string>
|
||||
<string name="description_pace_nautical">步速 (分鐘/海里)</string>
|
||||
<string name="description_pace_metric">步速 (分鐘/公里)</string>
|
||||
<string name="description_recorded_time">記錄時間:%1$s</string>
|
||||
<string name="description_sensor_cadence">轉速 (rpm)</string>
|
||||
<string name="description_speed_ms">速度 (公尺/秒)</string>
|
||||
<string name="description_sensor_cadence">踏頻 (rpm)</string>
|
||||
<string name="description_sensor_heart_rate">心率 (bpm)</string>
|
||||
<string name="description_sensor_power">功率 (W)</string>
|
||||
<string name="description_default_speed_or_pace">依照活動類型</string>
|
||||
<string name="description_speed_imperial">速度 (英里/小時)</string>
|
||||
<string name="description_speed_nautical">速度 (節)</string>
|
||||
<string name="description_speed_metric">速度 (公里/小時)</string>
|
||||
<string name="description_time">時間</string>
|
||||
<string name="description_total_distance">總距離:%1$.2f 公里 (%2$.1f 英里)</string>
|
||||
<string name="description_total_time">總時間:%1$s</string>
|
||||
<string name="description_speed_source_gps">GPS</string>
|
||||
<!-- Export -->
|
||||
<string name="export_with_photos">包含照片</string>
|
||||
<string name="export_without_photos">不包含照片</string>
|
||||
<string name="export_error_post_workout">運動後匯出失敗,請檢查匯出目錄。</string>
|
||||
<string name="export_cannot_write_to_dir">無法寫入匯出目錄。</string>
|
||||
<string name="export_dir_not_writable">" (不可寫入!)"</string>
|
||||
<string name="export_progress_message">正在匯出至 %1$s…</string>
|
||||
<string name="export_track_already_exists_msg">蹤跡 %1$s 已存在於目標目錄之中。</string>
|
||||
<string name="export_all_do_it_for_all">對所有衝突這麼做</string>
|
||||
<string name="export_track_errors">蹤跡未匯出</string>
|
||||
<string name="export_progress_summary_new_msg">新蹤跡已匯出</string>
|
||||
<string name="export_progress_summary_overwrite_msg">蹤跡覆蓋</string>
|
||||
<string name="export_progress_summary_skip_msg">蹤跡已略過</string>
|
||||
<string name="export_progress_summary_errors_msg">錯誤</string>
|
||||
<!-- External Storage -->
|
||||
<!-- Generic -->
|
||||
<string name="generic_add">新增</string>
|
||||
<string name="generic_delete_selected_confirm_title">確定要刪除所選項目?</string>
|
||||
<string name="generic_description">內容描述</string>
|
||||
<string name="generic_description_line">內容描述:%1$s</string>
|
||||
<string name="generic_name">名稱</string>
|
||||
<string name="generic_name_line">名稱:%1$s</string>
|
||||
<string name="generic_open_track">開啟蹤跡</string>
|
||||
<string name="generic_recording">正在記錄…</string>
|
||||
<string name="generic_save">儲存</string>
|
||||
<string name="generic_tracks">足跡</string>
|
||||
<string name="generic_tracks">蹤跡</string>
|
||||
<string name="generic_overwrite">覆蓋</string>
|
||||
<string name="generic_skip">略過</string>
|
||||
<string name="generic_separator_done_total">/</string>
|
||||
<string name="generic_show_errors">顯示錯誤</string>
|
||||
<plurals name="generic_completed_with_errors">
|
||||
<item quantity="one">已完成,但有一個錯誤</item>
|
||||
<item quantity="other">已完成,但有 %1$d 個錯誤</item>
|
||||
</plurals>
|
||||
<string name="generic_completed">完成</string>
|
||||
<string name="generic_click_twice_cancel">再次點擊返回以取消</string>
|
||||
<string name="generic_choose_an_option">選擇一個選項</string>
|
||||
<string name="generic_undo">撤消</string>
|
||||
<string name="generic_filter">篩選</string>
|
||||
<string name="generic_from">從</string>
|
||||
<string name="generic_to">至</string>
|
||||
<string name="generic_today">今日</string>
|
||||
<string name="generic_yesterday">昨日</string>
|
||||
<string name="generic_dismiss">Dismiss</string>
|
||||
<!-- Gps -->
|
||||
<string name="gps_starting">正在啟用 GPS</string>
|
||||
<string name="gps_wait_for_better_signal">正在等待更清晰的 GPS 訊號</string>
|
||||
<string name="gps_wait_for_signal">正在等待 GPS 訊號</string>
|
||||
<string name="gps_disabled_msg">GPS 禁用</string>
|
||||
<string name="gps_fixed_and_ready">GPS 已修復並準備就緒</string>
|
||||
<string name="gps_recording_status">%1$s:%2$s</string>
|
||||
<string name="gps_recording_without_signal">OpenTracks 紀錄中,不包含 GPS 資料。</string>
|
||||
<!-- Image -->
|
||||
<string name="image_arrow">箭頭</string>
|
||||
<string name="image_marker">標記</string>
|
||||
<string name="image_marker_count">標記數</string>
|
||||
<string name="image_photo_marker">相片標記</string>
|
||||
<string name="image_record">記錄</string>
|
||||
<string name="image_stop">停止</string>
|
||||
<string name="image_track">足跡</string>
|
||||
<string name="image_discard">Discard</string>
|
||||
<string name="image_track">蹤跡</string>
|
||||
<!-- Import -->
|
||||
<string name="import_thread_interrupted">執行緒中斷</string>
|
||||
<string name="import_unsupported_format">未支援的檔案格式</string>
|
||||
<string name="import_parser_error">分析器錯誤:%1$s</string>
|
||||
<string name="import_unable_to_import_file">無法匯入檔案:%1$s</string>
|
||||
<string name="import_no_kml_file_found">在 KMZ 中沒有發現 doc.kml 檔案</string>
|
||||
<string name="import_error_info">%1$s:%2$s</string>
|
||||
<string name="import_error_list_dialog_title">檔案未匯入</string>
|
||||
<string name="import_file_imported">檔案 %1$s 已匯入</string>
|
||||
<string name="import_prevent_reimport">您已設定防止重新匯入蹤跡</string>
|
||||
<string name="import_progress_message">正在從 %1$s 匯入檔案…</string>
|
||||
<string name="import_progress_summary_ok_msg">檔案已匯入</string>
|
||||
<string name="import_progress_summary_exists_msg">已經存在</string>
|
||||
<string name="import_progress_summary_errors_msg">錯誤</string>
|
||||
<!-- Marker -->
|
||||
<string name="marker_add_error">無法插入標記,因為無法取得 GPS 訊號。請再試一次。</string>
|
||||
<string name="marker_add_success">標記已插入</string>
|
||||
<string name="marker_add_canceled">已取消,未新增任何標記</string>
|
||||
<string name="marker_add_photo_canceled">已取消,未加入照片標記</string>
|
||||
<string name="marker_delete_one_confirm_message">系統將永久刪除裝置上的這個標記</string>
|
||||
<string name="marker_delete_one_confirm_title">確定要刪除標記?</string>
|
||||
<string name="marker_delete_multiple_confirm_message">系統將永久刪除裝置上您所選取的這些標記</string>
|
||||
<string name="marker_name_format">標記 %1$d</string>
|
||||
<string name="marker_title">%1$d 個位置 (共 %2$d 個)</string>
|
||||
<!-- Marker Detail -->
|
||||
<!-- Marker Edit -->
|
||||
<string name="marker_edit_marker_type">標記類型 (例如瀑布)</string>
|
||||
<!-- Marker List -->
|
||||
<string name="marker_list_empty_message">您沒有任何標記</string>
|
||||
<!-- Menu -->
|
||||
<string name="menu_aggregated_statistics">彙總的統計資料</string>
|
||||
<string name="menu_delete">刪除</string>
|
||||
<string name="menu_edit">編輯</string>
|
||||
@@ -129,21 +302,83 @@
|
||||
<string name="menu_import_all">全部匯入</string>
|
||||
<string name="menu_insert_marker">插入標記</string>
|
||||
<string name="menu_insert_photo">插入相片</string>
|
||||
<string name="menu_insert_gallery_img">插入圖片庫圖片</string>
|
||||
<string name="menu_markers">標記</string>
|
||||
<string name="menu_search">搜尋</string>
|
||||
<string name="menu_select_all">全選</string>
|
||||
<string name="menu_settings">設定</string>
|
||||
<string name="menu_share">分享</string>
|
||||
<string name="menu_select_layout">選擇布局</string>
|
||||
<string name="menu_show_on_map">在地圖上顯示</string>
|
||||
<string name="menu_start_gps">啟動 GPS</string>
|
||||
<string name="menu_stop_gps">關閉 GPS</string>
|
||||
<string name="menu_voice_rate">語速</string>
|
||||
<string name="menu_resume_track">還原蹤跡</string>
|
||||
<string name="menu_add_custom_layout">新布局</string>
|
||||
<string name="menu_filter">篩選</string>
|
||||
<!-- OpenTracks -->
|
||||
<string name="recording_service">記錄服務</string>
|
||||
<string name="delete_service">刪除服務</string>
|
||||
<!-- Permission -->
|
||||
<string name="permission_gps_failed">OpenTracks 需要授權使用 GPS。</string>
|
||||
<string name="permission_bluetooth_failed">OpenTracks 需要授權使用藍芽。</string>
|
||||
<string name="permission_bluetooth_failed_rejected">您需要手動在系統設定中授權 OpenTracks 存取附近裝置。</string>
|
||||
<!-- Search -->
|
||||
<!-- Sensor State -->
|
||||
<string name="sensor_state_cadence_avg">平均踏頻</string>
|
||||
<string name="sensor_state_cadence_max">最大踏頻</string>
|
||||
<string name="sensor_state_heart_rate">心率</string>
|
||||
<string name="sensor_state_heart_rate_avg">平均心率</string>
|
||||
<string name="sensor_state_heart_rate_max">最大心率</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d bpm</string>
|
||||
<string name="sensor_state_power">電源</string>
|
||||
<string name="sensor_state_power">功率</string>
|
||||
<string name="sensor_state_power_avg">平均功率</string>
|
||||
<string name="sensor_could_not_scan">無法掃描藍牙裝置 (錯誤 %1$i).</string>
|
||||
<string name="bluetooth_disabled">請啟用藍芽。</string>
|
||||
|
||||
<string name="settings_open_tracks_title">開啟蹤跡</string>
|
||||
<string name="settings_open_tracks_summary">所有關於 OpenTracks 專案</string>
|
||||
|
||||
<string name="settings_defaults_title">預設單位與活動</string>
|
||||
<string name="settings_defaults_summary">首選單位、預設活動、蹤跡預設名稱</string>
|
||||
|
||||
<string name="settings_ui_title">使用者介面</string>
|
||||
<string name="settings_ui_summary">外觀、紀錄布局、主題</string>
|
||||
|
||||
<string name="settings_gps_title">GPS</string>
|
||||
<string name="settings_gps_summary">時間間隔、距離間隔、最大距離、精度</string>
|
||||
|
||||
<string name="settings_sensors_title">藍芽感測器</string>
|
||||
<string name="settings_sensors_summary">自行車感測器、輪周、跑步感測器</string>
|
||||
|
||||
<string name="settings_announcements_title">語音通知</string>
|
||||
<string name="settings_announcements_summary">時間、距離、語速</string>
|
||||
|
||||
<string name="settings_import_export_title">匯入/匯出</string>
|
||||
<string name="settings_import_export_summary">匯入、匯出、自動匯出</string>
|
||||
|
||||
<string name="settings_units_category">單位</string>
|
||||
<string name="settings_activity_defaults_category">活動的預設值</string>
|
||||
|
||||
<string name="settings_reset_summary">重置設定為預設值</string>
|
||||
<string name="settings_layout_reset_key" translatable="false">設定布局重置</string>
|
||||
|
||||
<!-- Settings Advanced -->
|
||||
<string name="settings_advanced">進階</string>
|
||||
<string name="settings_default_trackfileformat">匯出/分享檔案格式</string>
|
||||
<string name="settings_export_filename_title">檔名的格式</string>
|
||||
<!-- Settings Chart -->
|
||||
<string name="settings_chart_by_distance">依距離</string>
|
||||
<string name="settings_chart_by_time">依時間</string>
|
||||
<!-- Settings Recording -->
|
||||
<string name="settings_recording_customize_layout_title">自訂您的紀錄布局</string>
|
||||
<string name="settings_recording_customize_layout_select_columns">每列資料欄位</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_title">在鎖定畫面顯示統計資料</string>
|
||||
<string name="settings_recording_show_on_lockscreen_while_recording_summary">當紀錄時,在不解鎖裝置的情況下顯示統計資料。</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_title">維持螢幕開啟</string>
|
||||
<string name="settings_recording_keep_screen_on_while_recording_summary">記錄中,維持螢幕開啟。</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_title">全螢幕</string>
|
||||
<string name="settings_recording_fullscreen_on_while_recording_summary">記錄中,在全螢幕中呈現。</string>
|
||||
<string name="settings_recording_default_activity_title">預設活動類型</string>
|
||||
<string name="settings_recording_location_frequency_summary">每 %1$s記錄一次位置資訊</string>
|
||||
<string name="settings_recording_max_recording_distance_summary">系統會在兩個地點之間的距離大於 %1$s時建立新的區段</string>
|
||||
@@ -155,77 +390,214 @@
|
||||
<string name="settings_recording_track_name_date_iso_8601_option">日期 (ISO 8601)</string>
|
||||
<string name="settings_recording_track_name_date_local_option">日期 (當地)</string>
|
||||
<string name="settings_recording_track_name_number_option">數字</string>
|
||||
<string name="settings_recording_track_name_title">預設足跡名稱</string>
|
||||
<string name="settings_recording_track_name_title">預設蹤跡名稱</string>
|
||||
<string name="settings_recording_idle_speed_title">怠速閾值</string>
|
||||
<string name="settings_night_mode_title">界面主題</string>
|
||||
<string name="settings_night_mode_option_system">系統</string>
|
||||
<string name="settings_night_mode_option_day">日</string>
|
||||
<string name="settings_night_mode_option_night">夜</string>
|
||||
|
||||
<string name="settings_announcements_totaltime_frequency">時間間隔</string>
|
||||
<string name="settings_announcements_distance_frequency">距離間隔</string>
|
||||
<string name="settings_announcements_average_heart_rate">平均心率</string>
|
||||
<string name="settings_announcements_lap_heart_rate">單圈心率</string>
|
||||
<string name="settings_announcements_average_speed_pace">平均速度/步速</string>
|
||||
<string name="settings_announcements_lap_speed_pace">單圈速度/步速</string>
|
||||
|
||||
<!-- Custom Layout -->
|
||||
<string name="custom_layout_list_title">布局</string>
|
||||
<string name="custom_layout_list_edit_name">輸入要新增的佈局名稱</string>
|
||||
<string name="custom_layout_list_edit_already_exists">布局的名稱已經存在</string>
|
||||
<string name="custom_layout_list_layout_removed">佈局已移除</string>
|
||||
<string name="custom_layout_select_layout">選擇布局</string>
|
||||
<string name="stats_custom_layout_default_layout">預設布局</string>
|
||||
<!-- Custom Layout Reset -->
|
||||
<string name="settings_layout_reset">重置自訂布局</string>
|
||||
<string name="settings_layout_reset_confirm_message">所有的布局設定將被還原為預設值。這不會刪除任何裝置上的蹤跡。</string>
|
||||
<string name="settings_layout_reset_confirm_title">重置您的布局?</string>
|
||||
<string name="settings_layout_reset_done">所有的布局設定已被還原為預設值</string>
|
||||
<!-- Settings Reset -->
|
||||
<string name="settings_all_reset">重置</string>
|
||||
<string name="settings_reset_confirm_message">系統會將所有設定還原為預設值。</string>
|
||||
<string name="settings_reset_confirm_title">確定要立即重設?</string>
|
||||
<string name="settings_reset_done">所有設定已還原為預設值</string>
|
||||
<!-- Settings Sensor -->
|
||||
<string name="settings_generic_sensor">通用</string>
|
||||
<string name="settings_cycling_sensor">騎自行車</string>
|
||||
<string name="settings_running_sensor">跑步</string>
|
||||
|
||||
<string name="settings_sensor_bluetooth">藍牙</string>
|
||||
|
||||
<string name="settings_sensor_cycling_distance_speed">距離與速度</string>
|
||||
<string name="settings_sensor_cycling_cadence">踏頻</string>
|
||||
<string name="settings_sensor_running_speed_and_cadence">距離、速度與踏頻</string>
|
||||
<string name="settings_sensor_wheel_circumference">輪周 (公釐)</string>
|
||||
<string name="settings_sensor_bluetooth_service_filter_enabled">僅顯示宣告所需服務的藍芽裝置</string>
|
||||
|
||||
<string name="settings_sensor_heart_rate_max">區間:最大心率 (bpm)</string>
|
||||
|
||||
<!-- Settings Stats -->
|
||||
<string name="settings_stats_rate_title">偏好速率</string>
|
||||
<string name="settings_stats_units_imperial">英制 (英里、英尺)</string>
|
||||
<string name="settings_stats_units_metric">公制 (公里、公尺)</string>
|
||||
<string name="settings_stats_units_nautical">航海 (海里、英尺)</string>
|
||||
<string name="settings_stats_units_title">慣用單位</string>
|
||||
<string name="share_track_share_file_body">你應該會喜歡這個足跡。\n\n請使用 Google 地球或其他地圖繪製軟體查看足跡。\n\n%1$s</string>
|
||||
<string name="share_track_subject">我想跟你分享足跡資訊。</string>
|
||||
<string name="stats_average_moving_pace">平均移動速度</string>
|
||||
|
||||
<!-- Settings public api -->
|
||||
<string name="settings_api_title">公開 API</string>
|
||||
<string name="settings_api_summary">其他 APP 的遠端控制與統計資料 API</string>
|
||||
<string name="settings_public_api_package_title">公開 API 的套件名稱</string>
|
||||
<string name="settings_public_api_enabled_title">公開 API</string>
|
||||
<string name="settings_public_api_enabled_summary_on">其他已安裝的應用程式可以開始或停止紀錄。</string>
|
||||
<string name="settings_public_api_enabled_summary_off">只有 OpenTracks 可以開始或停止紀錄。</string>
|
||||
<string name="settings_public_api_disabled_toast">OpenTracks 公開 AIP 被禁用:它可以在設定中被啟用。</string>
|
||||
<string name="settings_public_api_dashboard_enabled_title">自動資料傳輸</string>
|
||||
<string name="settings_public_api_dashboard_enabled_summary_on">開始紀錄的應用程式也可以存取紀錄的資料。</string>
|
||||
<string name="settings_public_api_dashboard_enabled_summary_off">記錄的資料將不會自動與其他應用程式共用。</string>
|
||||
|
||||
<!-- Settings import/export -->
|
||||
<string name="settings_import_section">匯入</string>
|
||||
<string name="settings_export_section">匯出</string>
|
||||
|
||||
<string name="settings_prevent_reimport_tracks_title">防止重新匯入蹤跡</string>
|
||||
<!-- Share Track -->
|
||||
<string name="share_track_share_file_body">你應該會喜歡這個蹤跡。\n\n請使用 Google 地球或其他地圖繪製軟體查看蹤跡。\n\n%1$s</string>
|
||||
<string name="share_track_subject">我想跟你分享蹤跡資訊。</string>
|
||||
<!-- Stats -->
|
||||
<string name="stats_average_moving_pace">平均移動步速</string>
|
||||
<string name="stats_average_moving_speed">平均移動速度</string>
|
||||
<string name="stats_average_pace">平均速度</string>
|
||||
<string name="stats_average_pace">平均步速</string>
|
||||
<string name="stats_average_speed">平均速度</string>
|
||||
<string name="stats_altitude">海拔高度</string>
|
||||
<string name="stats_fastest_pace">最快速度</string>
|
||||
<string name="stats_fastest_pace">最高步速</string>
|
||||
<string name="stats_gain">增加</string>
|
||||
<string name="stats_loss">減少</string>
|
||||
<string name="stats_coordinates">緯度/經度</string>
|
||||
<string name="stats_latitude">緯度</string>
|
||||
<string name="stats_longitude">經度</string>
|
||||
<string name="stats_max_speed">速限</string>
|
||||
<string name="stats_max_speed">最高速度</string>
|
||||
<string name="stats_moving_time">移動時間</string>
|
||||
<string name="stats_pace">速度</string>
|
||||
<string name="stats_pace">步速</string>
|
||||
<string name="stats_speed">速度</string>
|
||||
<string name="stats_distance">距離</string>
|
||||
<string name="stats_total_time">總時間</string>
|
||||
<string name="track_name_format">%1$d 號足跡</string>
|
||||
<string name="stats_split_interval">分段間隔</string>
|
||||
<string name="stats_sensors_heart_rate">心率</string>
|
||||
<string name="stats_sensors_cadence">踏頻</string>
|
||||
<string name="stats_sensors_power">功率</string>
|
||||
<string name="stats_clock">時鐘</string>
|
||||
<!-- Track -->
|
||||
<string name="track_name_format">%1$d 號蹤跡</string>
|
||||
<string name="track_recording_notification_accuracy">定位精度:%1$s</string>
|
||||
<string name="track_distance_notification">距離:%1$s</string>
|
||||
<string name="track_speed_notification">速度:%1$s</string>
|
||||
<string name="track_pace_notification">步速:%1$s</string>
|
||||
<string name="track_markers">「%1$s」標記</string>
|
||||
<string name="track_delete_one_confirm_message">系統將永久刪除裝置上儲存的這個足跡與其中的標記。</string>
|
||||
<string name="track_delete_one_confirm_title">確定要刪除足跡?</string>
|
||||
<string name="track_delete_multiple_confirm_message">系統將永久刪除您在裝置上所選的足跡與其中的標記。</string>
|
||||
<!-- Track Delete -->
|
||||
<string name="track_delete_one_confirm_message">系統將永久刪除裝置上儲存的這個蹤跡與其中的標記。</string>
|
||||
<string name="track_delete_one_confirm_title">確定要刪除蹤跡?</string>
|
||||
<string name="track_delete_multiple_confirm_message">系統將永久刪除您在裝置上所選的蹤跡與其中的標記。</string>
|
||||
<string name="track_delete_progress_message">刪除中…</string>
|
||||
<string name="track_delete_number_of_tracks">%1$d 蹤跡</string>
|
||||
<string name="track_delete_not_recording">此蹤跡無法被刪除,因為它目前正在錄製。</string>
|
||||
<string name="track_discarding">廢棄蹤跡</string>
|
||||
<!-- Track Detail -->
|
||||
<string name="track_detail_stats_tab">統計資料</string>
|
||||
<string name="track_detail_intervals_tab">間隔</string>
|
||||
<!-- Track Edit -->
|
||||
<string name="track_edit_activity_type">活動類型 (例如健行)</string>
|
||||
<string name="track_edit_activity_type_hint">活動類型</string>
|
||||
<!-- Track List -->
|
||||
<string name="track_list_empty_message">按這裡開始記錄新的冒險</string>
|
||||
<!-- Aggregated Statistics -->
|
||||
<string name="aggregated_stats_empty_message">紀錄您的第一個蹤跡以檢視綜合統計資料</string>
|
||||
<string name="aggregated_stats_filter_no_results">沒有指定篩選的活動</string>
|
||||
<!-- Interval List -->
|
||||
<string name="interval_list_empty_message">還有有任何間格</string>
|
||||
<!-- Unit -->
|
||||
<string name="unit_feet">英尺</string>
|
||||
<string name="unit_kilometer">公里</string>
|
||||
<string name="unit_kilometer_per_hour">公里/小時</string>
|
||||
<string name="unit_meter">公尺</string>
|
||||
<string name="unit_mile">英里</string>
|
||||
<string name="unit_mile_per_hour">英里/小時</string>
|
||||
<string name="unit_nautical_mile">海里</string>
|
||||
<string name="unit_knots">節</string>
|
||||
<string name="unit_minute_per_kilometer">分鐘/公里</string>
|
||||
<string name="unit_minute_per_mile">分鐘/英里</string>
|
||||
<string name="unit_minute_per_nautical_mile">分鐘/海里</string>
|
||||
<!-- Location Coordinates -->
|
||||
<string name="location_coordinate">%1$s°</string>
|
||||
<string name="location_latitude_longitude">%1$s, %2$s</string>
|
||||
<!-- Value -->
|
||||
|
||||
<string name="value_integer_feet_excellent_gps">%1$d 英尺 (GPS 訊號佳)</string>
|
||||
<string name="value_integer_feet_recommended">%1$d 英尺 (建議值)</string>
|
||||
<string name="value_integer_kilometer_hour">%1$d 公里/小時</string>
|
||||
<string name="value_float_kilometer_hour">%1$.1f 公里/小時</string>
|
||||
<string name="value_float_kilometer_hour_recommended">%1$.1f 公里/小時 (建議值)</string>
|
||||
<string name="value_integer_meter_excellent_gps">%1$d 公尺 (GPS 訊號佳)</string>
|
||||
<string name="value_integer_meter_poor_gps">%1$d 公尺 (GPS 訊號差)</string>
|
||||
<string name="value_integer_meter_recommended">%1$d 公尺 (建議值)</string>
|
||||
<string name="value_integer_mile_hour">%1$d 英里/小時</string>
|
||||
<string name="value_integer_knots">%1$d 節</string>
|
||||
<string name="value_float_mile_hour">%1$.1f 英里/小時</string>
|
||||
<string name="value_float_knots">%1$.1f 節</string>
|
||||
<string name="value_float_mile_hour_recommended">%1$.1f 英里/小時 (建議值)</string>
|
||||
<string name="value_float_knots_recommended">%1$.1f 節 (建議值)</string>
|
||||
<string name="value_integer_minute">%1$d 分鐘</string>
|
||||
<string name="value_integer_second">%1$d 秒</string>
|
||||
<string name="value_none">無</string>
|
||||
<string name="value_off">關閉</string>
|
||||
<string name="value_smallest_recommended">最小 (建議值)</string>
|
||||
<!-- Voice -->
|
||||
<plurals name="voiceHours">
|
||||
<item quantity="one">1 小時</item>
|
||||
<item quantity="other">%1$d 小時</item>
|
||||
</plurals>
|
||||
<plurals name="voiceMinutes">
|
||||
<item quantity="one">1 分鐘</item>
|
||||
<item quantity="other">%1$d 分鐘</item>
|
||||
</plurals>
|
||||
<plurals name="voiceSeconds">
|
||||
<item quantity="one">1 秒</item>
|
||||
<item quantity="other">%1$d 秒</item>
|
||||
</plurals>
|
||||
<plurals name="voiceSpeedKilometersPerHour">
|
||||
<item quantity="other">每小時 %1$.1f 公里</item>
|
||||
<item quantity="one">1 公里每小時</item>
|
||||
<item quantity="other">%1$.1f 公里每小時</item>
|
||||
</plurals>
|
||||
<plurals name="voiceSpeedMilesPerHour">
|
||||
<item quantity="other">每小時 %1$.1f 公里</item>
|
||||
<item quantity="one">1 英里每小時</item>
|
||||
<item quantity="other">%1$.1f 英里每小時</item>
|
||||
</plurals>
|
||||
<plurals name="voiceSpeedMKnots">
|
||||
<item quantity="one">1 節</item>
|
||||
<item quantity="other">%1$.1f 節</item>
|
||||
</plurals>
|
||||
<string name="voice_per_kilometer">每公里</string>
|
||||
<string name="voice_per_mile">每英里</string>
|
||||
<string name="voice_per_nautical_mile">每海里</string>
|
||||
<string name="lap_time">單圈時間</string>
|
||||
<string name="pace">步速</string>
|
||||
<string name="lap_speed">單圈速度</string>
|
||||
<string name="speed">平均移動速度</string>
|
||||
<string name="total_distance">總距離</string>
|
||||
<plurals name="voiceDistanceKilometers">
|
||||
<item quantity="one">1 公里</item>
|
||||
<item quantity="other">%1$.1f 公里</item>
|
||||
</plurals>
|
||||
<plurals name="voiceDistanceMiles">
|
||||
<item quantity="one">1 英里</item>
|
||||
<item quantity="other">%1$.1f 英里</item>
|
||||
</plurals>
|
||||
<plurals name="voiceDistanceNauticalMiles">
|
||||
<item quantity="one">1 海里</item>
|
||||
<item quantity="other">%1$.1f 海里</item>
|
||||
</plurals>
|
||||
<string name="average_heart_rate">平均心率</string>
|
||||
<string name="current_heart_rate">目前心率</string>
|
||||
<!-- Waypoint Type -->
|
||||
<string name="waypoint_type_atm">提款機</string>
|
||||
<string name="waypoint_type_bank">銀行</string>
|
||||
<string name="waypoint_type_bar">酒吧</string>
|
||||
@@ -277,4 +649,30 @@
|
||||
<string name="waypoint_type_waterfall">瀑布</string>
|
||||
<string name="waypoint_type_water_fountain">噴泉</string>
|
||||
<string name="waypoint_type_waypoint">途經點</string>
|
||||
<!-- Share image -->
|
||||
<string name="share_image_subject">我想與你分享一張圖片</string>
|
||||
<string name="share_image_body">我認為你可能會對這張圖片感興趣。</string>
|
||||
|
||||
<string name="hold_to_stop">按住以停止</string>
|
||||
|
||||
<string name="instant_export_enabled_summary">在紀錄完成後匯出蹤跡至儲存區</string>
|
||||
<string name="instant_export_enabled_title">即時運動後匯出</string>
|
||||
|
||||
<string name="settings_default_export_uri_title">蹤跡匯出目錄</string>
|
||||
<!-- Fields -->
|
||||
<string name="field_set_primary">主要的</string>
|
||||
<string name="field_set_secondary">次要的</string>
|
||||
<string name="field_remove_from_layout">移除</string>
|
||||
<string name="no_compatible_file_manager_installed">沒有安裝相容的檔案管理器</string>
|
||||
<string name="error_crash_title">%1$s 已崩潰</string>
|
||||
<string name="share_crash_report">分享</string>
|
||||
<string name="report_bug">回報 bug</string>
|
||||
|
||||
<string name="select_show_on_map_behavior">選擇 \"在地圖上顯示\" 行為</string>
|
||||
<string name="show_on_map_format_ask">詢問</string>
|
||||
<string name="show_on_dashboard">OpenTracks 儀表板 API</string>
|
||||
<string name="show_on_dashboard_not_installed">沒有安裝支援 OpenTracks 儀表板 API 的應用程式。</string>
|
||||
<string name="always">總是</string>
|
||||
|
||||
<string name="introduction_osm_dashboard">OpenTracks 本身不提供地圖。請安裝 OSMDashboard 以在地圖上檢視您的紀錄。</string>
|
||||
</resources>
|
||||
|
||||
@@ -235,6 +235,8 @@
|
||||
<item>1.2</item>
|
||||
<item>1.3</item>
|
||||
</string-array>
|
||||
<string name="voice_on_device_speaker_key" translatable="false">voiceOnDeviceSpeaker</string>
|
||||
<bool name="voice_on_device_speaker_default" translatable="false">true</bool>
|
||||
<string name="voice_announce_total_distance_key" translatable="false">voiceAnnounceTotalDistance</string>
|
||||
<string name="voice_announce_moving_time_key" translatable="false">voiceAnnounceMovingTime</string>
|
||||
<string name="voice_announce_average_speed_pace_key" translatable="false">voiceAnnounceAverageSpeedPace</string>
|
||||
|
||||
@@ -575,6 +575,7 @@ limitations under the License.
|
||||
<item quantity="one">1 knot</item>
|
||||
<item quantity="other">%1$.1f knots</item>
|
||||
</plurals>
|
||||
<string name="voice_on_device_speaker_title">Use the device\'s speaker</string>
|
||||
<string name="voice_per_kilometer">per kilometer</string>
|
||||
<string name="voice_per_mile">per mile</string>
|
||||
<string name="voice_per_nautical_mile">per nautical mile</string>
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
android:title="@string/menu_voice_rate"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="@bool/voice_on_device_speaker_default"
|
||||
android:key="@string/voice_on_device_speaker_key"
|
||||
android:title="@string/voice_on_device_speaker_title" />
|
||||
<PreferenceCategory android:title="@string/settings_announcements_title">
|
||||
|
||||
<SwitchPreference
|
||||
|
||||
Reference in New Issue
Block a user