forked from upstream-mirrors/OpenTracks
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 25b6aec0e9 | |||
| 3e40209d15 | |||
| 54ff94f905 | |||
| 7a4faf6b0d | |||
| 8922b00a5f | |||
| 702efa8693 | |||
| e7a8c897a3 | |||
| c59d1d87bd | |||
| a706efb8b3 | |||
| e391e83a00 | |||
| 2940bf20d8 | |||
| 081db5a58b | |||
| b34805272f | |||
| 98443dba99 | |||
| dd6e733d8c | |||
| 92d3439c3b | |||
| bd155cd600 | |||
| e14e53c0ae | |||
| 77a6a63174 | |||
| 40f2463f09 | |||
| e5d1048c8d | |||
| bf3b529fb2 | |||
| d0fde46027 | |||
| 0f348dff10 | |||
| d3f5080e73 | |||
| a453c8ec1e | |||
| 2a60aa8f59 | |||
| 41e7870509 | |||
| 57f66b77ab | |||
| 53572406e9 | |||
| a288255ab1 | |||
| 353c958ae0 | |||
| bc5ab0d7e5 | |||
| 9d915b5640 | |||
| 3aaee270eb | |||
| d53a7156e2 |
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Report issues of Opentracks features
|
||||||
|
title: ''
|
||||||
|
labels: potential bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
If applicable:
|
||||||
|
* add screenshots
|
||||||
|
* add logcat output
|
||||||
|
|
||||||
|
**Technical information**
|
||||||
|
- Device: [e.g. Nexus 7 (2013)]
|
||||||
|
- OS: [e.g. LineageOS 15.1]
|
||||||
|
- Version [e.g. v3.2.4]
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for OpenTracks
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
+7
-3
@@ -7,6 +7,10 @@
|
|||||||
3. Manually update _version code_ and _version name_ in `AndroidManifest.xml` (used by FDroid)
|
3. Manually update _version code_ and _version name_ in `AndroidManifest.xml` (used by FDroid)
|
||||||
4. Create changelog (`_version code_.txt`)
|
4. Create changelog (`_version code_.txt`)
|
||||||
5. Create commit with all changes
|
5. Create commit with all changes
|
||||||
6. Push commits
|
6. Tag newly create commit with _version name_ (e.g., v3.2.1)
|
||||||
7. Tag newly create commit with _version name_ (e.g., v3.2.1)
|
7. Push commits and tags to public repository
|
||||||
8. Push the tagged commit to public repository
|
8. Add changelog to tag (Github releases)
|
||||||
|
|
||||||
|
## Translations (localization)
|
||||||
|
|
||||||
|
Translations of the OpenTracks are handled in Transifex: [https://www.transifex.com/opentracks](https://www.transifex.com/opentracks/).
|
||||||
@@ -30,6 +30,14 @@ To show your tracks on a map, a 3rd party application (e.g., [OsmAnd](https://pl
|
|||||||
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45">
|
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
<div>
|
||||||
|
<img width="20%" src="fastlane/metadata/android/en-US/phoneScreenshots/screenshot_1.png">
|
||||||
|
<img width="20%" src="fastlane/metadata/android/en-US/phoneScreenshots/screenshot_2.png">
|
||||||
|
<img width="20%" src="fastlane/metadata/android/en-US/phoneScreenshots/screenshot_3.png">
|
||||||
|
<img width="20%" src="fastlane/metadata/android/en-US/phoneScreenshots/screenshot_4.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
## Project history
|
## Project history
|
||||||
|
|
||||||
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
|
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
|
||||||
|
|||||||
+7
-7
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,10 +35,14 @@ def getVersionName = { ->
|
|||||||
try {
|
try {
|
||||||
def stdout = new ByteArrayOutputStream()
|
def stdout = new ByteArrayOutputStream()
|
||||||
exec {
|
exec {
|
||||||
commandLine 'git', 'describe', '--tags', '--dirty'
|
commandLine 'git', 'describe', '--tags'
|
||||||
standardOutput = stdout
|
standardOutput = stdout
|
||||||
}
|
}
|
||||||
return stdout.toString().trim()
|
exec {
|
||||||
|
commandLine 'git', 'log', '--format="%h"', '-n 1'
|
||||||
|
standardOutput = stdout
|
||||||
|
}
|
||||||
|
return stdout.toString().replace('\n', '-').replace('"', '').trim()
|
||||||
}
|
}
|
||||||
catch (ignored) {
|
catch (ignored) {
|
||||||
return null
|
return null
|
||||||
@@ -75,10 +79,6 @@ android {
|
|||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
variant.resValue "string", "applicationId", variant.applicationId
|
variant.resValue "string", "applicationId", variant.applicationId
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
disable "AppCompatResource" // TODO Disable complaint to use androidx's SearchView as it is null.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
v3.2.4: OpenTracks
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Settings activity crashes
|
||||||
|
Removed possibility to change voice/split frequency from the context menu
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
v3.2.5: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Disable activity change
|
||||||
|
- Add permission for Android 10: recording location data
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix reset settings
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Preferences
|
||||||
|
- if Settings cannot be loaded reset all preferences
|
||||||
|
- moved access to preferences to PreferencesUtil
|
||||||
|
- moved default of preferences from code to xml
|
||||||
|
- use SummaryProvider
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v3.2.6: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Heart rate monitor: scan for available devices
|
||||||
|
- Remove shortcut to Bluetooth settings
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Preferences: moved default of preferences from code to xml
|
||||||
+4
-5
@@ -27,7 +27,6 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
|
||||||
import de.dennisguse.opentracks.content.Track;
|
import de.dennisguse.opentracks.content.Track;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
@@ -95,7 +94,7 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
// A flush happens at the end
|
// A flush happens at the end
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(1), eq(TRACK_ID_0))).thenReturn(1);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(1), eq(TRACK_ID_0))).thenReturn(1);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
// A flush happens at the end
|
// A flush happens at the end
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
||||||
@@ -156,7 +155,7 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
// A flush happens at the end
|
// A flush happens at the end
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
||||||
@@ -211,7 +210,7 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), anyInt(), anyLong())).thenReturn(1);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), anyInt(), anyLong())).thenReturn(1);
|
||||||
when(contentProviderUtils.getFirstTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_0);
|
when(contentProviderUtils.getFirstTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_0);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_0);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_0);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
contentProviderUtils.deleteTrack(context, TRACK_ID_0);
|
contentProviderUtils.deleteTrack(context, TRACK_ID_0);
|
||||||
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
||||||
|
|||||||
+2
-3
@@ -27,7 +27,6 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
|
||||||
import de.dennisguse.opentracks.content.Track;
|
import de.dennisguse.opentracks.content.Track;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
// A flush happens at the end
|
// A flush happens at the end
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(1), eq(TRACK_ID_0))).thenReturn(1);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(1), eq(TRACK_ID_0))).thenReturn(1);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
||||||
@@ -110,7 +109,7 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|||||||
// A flush happens at the end
|
// A flush happens at the end
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
when(contentProviderUtils.bulkInsertTrackPoint((Location[]) any(), eq(5), eq(TRACK_ID_0))).thenReturn(5);
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getLong(context, R.string.recording_track_id_key))).thenReturn(null);
|
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
||||||
|
|||||||
+9
-9
@@ -79,7 +79,7 @@ public class TrackRecordingServiceTest {
|
|||||||
|
|
||||||
static void updateAutoResumePrefs(Context context, int attempts, int timeoutMins) {
|
static void updateAutoResumePrefs(Context context, int attempts, int timeoutMins) {
|
||||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts);
|
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts);
|
||||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_timeout_key, timeoutMins);
|
PreferencesUtils.setString(context, R.string.auto_resume_track_timeout_key, "" + timeoutMins);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -135,7 +135,7 @@ public class TrackRecordingServiceTest {
|
|||||||
createDummyTrack(trackId, System.currentTimeMillis(), true);
|
createDummyTrack(trackId, System.currentTimeMillis(), true);
|
||||||
|
|
||||||
// Clear the number of attempts and set the timeout to 10 min.
|
// Clear the number of attempts and set the timeout to 10 min.
|
||||||
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default)));
|
||||||
|
|
||||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||||
Intent startIntent = createStartIntent(context);
|
Intent startIntent = createStartIntent(context);
|
||||||
@@ -154,7 +154,7 @@ public class TrackRecordingServiceTest {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testResumeAfterReboot_simulateReboot() throws Exception {
|
public void testResumeAfterReboot_simulateReboot() throws Exception {
|
||||||
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default)));
|
||||||
ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context)));
|
ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context)));
|
||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ public class TrackRecordingServiceTest {
|
|||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
Assert.assertEquals(id, service.getRecordingTrackId());
|
Assert.assertEquals(id, service.getRecordingTrackId());
|
||||||
mServiceRule.unbindService();
|
mServiceRule.unbindService();
|
||||||
Assert.assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
Assert.assertEquals(id, PreferencesUtils.getRecordingTrackId(context));
|
||||||
|
|
||||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ public class TrackRecordingServiceTest {
|
|||||||
createDummyTrack(trackId, System.currentTimeMillis(), false);
|
createDummyTrack(trackId, System.currentTimeMillis(), false);
|
||||||
|
|
||||||
// Clear the number of attempts and set the timeout to 10 min.
|
// Clear the number of attempts and set the timeout to 10 min.
|
||||||
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default)));
|
||||||
|
|
||||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||||
Intent startIntent = createStartIntent(context);
|
Intent startIntent = createStartIntent(context);
|
||||||
@@ -207,7 +207,7 @@ public class TrackRecordingServiceTest {
|
|||||||
createDummyTrack(trackId, System.currentTimeMillis() - 1500 * 60 * 1000, true);
|
createDummyTrack(trackId, System.currentTimeMillis() - 1500 * 60 * 1000, true);
|
||||||
|
|
||||||
// Clear the number of attempts and set the timeout to 10 min.
|
// Clear the number of attempts and set the timeout to 10 min.
|
||||||
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
updateAutoResumePrefs(context, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default)));
|
||||||
|
|
||||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||||
Intent startIntent = createStartIntent(context);
|
Intent startIntent = createStartIntent(context);
|
||||||
@@ -230,7 +230,7 @@ public class TrackRecordingServiceTest {
|
|||||||
createDummyTrack(trackId, System.currentTimeMillis(), true);
|
createDummyTrack(trackId, System.currentTimeMillis(), true);
|
||||||
|
|
||||||
// Set the number of attempts to max.
|
// Set the number of attempts to max.
|
||||||
updateAutoResumePrefs(context, TrackRecordingService.MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
updateAutoResumePrefs(context, TrackRecordingService.MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS, Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default)));
|
||||||
|
|
||||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||||
Intent startIntent = createStartIntent(context);
|
Intent startIntent = createStartIntent(context);
|
||||||
@@ -297,7 +297,7 @@ public class TrackRecordingServiceTest {
|
|||||||
long newTrackId = service.startNewTrack();
|
long newTrackId = service.startNewTrack();
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId);
|
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId);
|
||||||
|
|
||||||
Assert.assertEquals(trackId, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
||||||
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +310,7 @@ public class TrackRecordingServiceTest {
|
|||||||
// Ending the current track when there is no recording should not result in any error.
|
// Ending the current track when there is no recording should not result in any error.
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
Assert.assertFalse(PreferencesUtils.isRecording(context));
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -103,7 +103,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_voiceFrequencyDefault() throws TimeoutException {
|
public void testWithProperties_voiceFrequencyDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT);
|
PreferencesUtils.setInt(context, R.string.voice_frequency_key, Integer.parseInt(context.getResources().getString(R.string.voice_frequency_default)));
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_maxRecordingDistanceDefault() throws TimeoutException {
|
public void testWithProperties_maxRecordingDistanceDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.max_recording_distance_key, PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT);
|
PreferencesUtils.setInt(context, R.string.max_recording_distance_key, Integer.parseInt(context.getResources().getString(R.string.max_recording_distance_default)));
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,8 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_minRecordingDistanceDefault() throws TimeoutException {
|
public void testWithProperties_minRecordingDistanceDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
int minRecordingIntervalDefault = Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default));
|
||||||
|
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, minRecordingIntervalDefault);
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +154,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_splitFrequencyDefault() throws TimeoutException {
|
public void testWithProperties_splitFrequencyDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT);
|
PreferencesUtils.setInt(context, R.string.split_frequency_key, Integer.parseInt(context.getResources().getString(R.string.split_frequency_default)));
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_metricUnitsDefault() throws TimeoutException {
|
public void testWithProperties_metricUnitsDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setString(context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
PreferencesUtils.setString(context, R.string.stats_units_key, context.getString(R.string.stats_units_default));
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +189,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_minRecordingIntervalDefault() throws TimeoutException {
|
public void testWithProperties_minRecordingIntervalDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.min_recording_interval_key, PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT);
|
PreferencesUtils.setInt(context, R.string.min_recording_interval_key, Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default)));
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +203,8 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testWithProperties_minRequiredAccuracyDefault() throws TimeoutException {
|
public void testWithProperties_minRequiredAccuracyDefault() throws TimeoutException {
|
||||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
int recordingGPSAccuracyDefault = Integer.parseInt(context.getResources().getString(R.string.recording_gps_accuracy_default));
|
||||||
|
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, recordingGPSAccuracyDefault);
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +227,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
Track track = providerUtils.getTrack(id);
|
Track track = providerUtils.getTrack(id);
|
||||||
Assert.assertNotNull(track);
|
Assert.assertNotNull(track);
|
||||||
Assert.assertEquals(id, track.getId());
|
Assert.assertEquals(id, track.getId());
|
||||||
Assert.assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
Assert.assertEquals(id, PreferencesUtils.getRecordingTrackId(context));
|
||||||
Assert.assertEquals(id, service.getRecordingTrackId());
|
Assert.assertEquals(id, service.getRecordingTrackId());
|
||||||
|
|
||||||
// Insert a few points, markers and statistics.
|
// Insert a few points, markers and statistics.
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ limitations under the License.
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="de.dennisguse.opentracks"
|
package="de.dennisguse.opentracks"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:versionCode="3101"
|
android:versionCode="3137"
|
||||||
android:versionName="v3.2.3"> <!-- For FDroid. -->
|
android:versionName="v3.2.6"> <!-- For FDroid. -->
|
||||||
<!-- Permission to initialize services -->
|
<!-- Permission to initialize services -->
|
||||||
<application
|
<application
|
||||||
android:name=".Startup"
|
android:name=".Startup"
|
||||||
@@ -124,6 +124,7 @@ limitations under the License.
|
|||||||
android:name=".services.TrackRecordingService"
|
android:name=".services.TrackRecordingService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
android:foregroundServiceType="location|connectedDevice"
|
||||||
android:icon="@drawable/ic_logo_color_24dp"
|
android:icon="@drawable/ic_logo_color_24dp"
|
||||||
android:label="@string/recording_service" />
|
android:label="@string/recording_service" />
|
||||||
</application>
|
</application>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public abstract class AbstractListActivity extends AbstractActivity implements C
|
|||||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
||||||
stopRecording = true;
|
stopRecording = true;
|
||||||
} else {
|
} else {
|
||||||
long recordingTrackId = PreferencesUtils.getLong(this, R.string.recording_track_id_key);
|
long recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
|
||||||
for (long trackId : trackIds) {
|
for (long trackId : trackIds) {
|
||||||
if (trackId == recordingTrackId) {
|
if (trackId == recordingTrackId) {
|
||||||
stopRecording = true;
|
stopRecording = true;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
private boolean recordingTrackPaused;
|
||||||
/*
|
/*
|
||||||
* Note that sharedPreferenceChangeListener cannot be an anonymous inner
|
* Note that sharedPreferenceChangeListener cannot be an anonymous inner
|
||||||
* class. Anonymous inner class will get garbage collected.
|
* class. Anonymous inner class will get garbage collected.
|
||||||
@@ -79,11 +79,11 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
// Note that the key can be null
|
// Note that the key can be null
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(MarkerListActivity.this, R.string.recording_track_id_key))) {
|
if (PreferencesUtils.isKey(MarkerListActivity.this, R.string.recording_track_id_key, key)) {
|
||||||
recordingTrackId = PreferencesUtils.getLong(MarkerListActivity.this, R.string.recording_track_id_key);
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(MarkerListActivity.this);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(MarkerListActivity.this, R.string.recording_track_paused_key))) {
|
if (PreferencesUtils.isKey(MarkerListActivity.this, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(MarkerListActivity.this, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(MarkerListActivity.this);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@@ -128,6 +128,8 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
|
|
||||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
// Callback when an item is selected in the contextual action mode
|
// Callback when an item is selected in the contextual action mode
|
||||||
private ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
private ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
||||||
@@ -143,14 +143,14 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(SearchListActivity.this, R.string.stats_units_key))) {
|
if (PreferencesUtils.isKey(SearchListActivity.this, R.string.stats_units_key, key)) {
|
||||||
metricUnits = PreferencesUtils.isMetricUnits(SearchListActivity.this);
|
metricUnits = PreferencesUtils.isMetricUnits(SearchListActivity.this);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_id_key))) {
|
if (PreferencesUtils.isKey(SearchListActivity.this, R.string.recording_track_id_key, key)) {
|
||||||
recordingTrackId = PreferencesUtils.getLong(SearchListActivity.this, R.string.recording_track_id_key);
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(SearchListActivity.this);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_paused_key))) {
|
if (PreferencesUtils.isKey(SearchListActivity.this, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(SearchListActivity.this, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(SearchListActivity.this);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@@ -168,6 +168,8 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
||||||
|
|
||||||
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.widget.TabHost;
|
|||||||
import android.widget.TabHost.TabContentFactory;
|
import android.widget.TabHost.TabContentFactory;
|
||||||
import android.widget.TabWidget;
|
import android.widget.TabWidget;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentPagerAdapter;
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
@@ -79,6 +80,7 @@ public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
TabInfo info = tabInfos.get(position);
|
TabInfo info = tabInfos.get(position);
|
||||||
return Fragment.instantiate(context, info.clss.getName(), info.bundle);
|
return Fragment.instantiate(context, info.clss.getName(), info.bundle);
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ import de.dennisguse.opentracks.content.WaypointCreationRequest;
|
|||||||
import de.dennisguse.opentracks.fragments.ChartFragment;
|
import de.dennisguse.opentracks.fragments.ChartFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
import de.dennisguse.opentracks.fragments.FrequencyDialogFragment;
|
|
||||||
import de.dennisguse.opentracks.fragments.StatsFragment;
|
import de.dennisguse.opentracks.fragments.StatsFragment;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.util.StatsUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackUtils;
|
import de.dennisguse.opentracks.util.TrackUtils;
|
||||||
|
|
||||||
@@ -94,8 +94,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
private boolean recordingTrackPaused;
|
||||||
private boolean showOnLockScreen = PreferencesUtils.SHOW_TRACKDETAIL_WHILE_RECORDING_ON_LOCKSCREEN;
|
|
||||||
|
|
||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -122,20 +121,18 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
* Note that sharedPreferenceChangeListener cannot be an anonymous inner
|
* Note that sharedPreferenceChangeListener cannot be an anonymous inner
|
||||||
* class. Anonymous inner class will get garbage collected.
|
* class. Anonymous inner class will get garbage collected.
|
||||||
*/
|
*/
|
||||||
private final OnSharedPreferenceChangeListener
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(TrackDetailActivity.this, R.string.recording_track_id_key))) {
|
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_id_key, key)) {
|
||||||
recordingTrackId = PreferencesUtils.getLong(TrackDetailActivity.this, R.string.recording_track_id_key);
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackDetailActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(TrackDetailActivity.this, R.string.recording_track_paused_key))) {
|
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(TrackDetailActivity.this, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackDetailActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(TrackDetailActivity.this, R.string.trackdetail_show_on_lockscreen_while_recording_key))) {
|
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.stats_show_on_lockscreen_while_recording_key, key)) {
|
||||||
showOnLockScreen = PreferencesUtils.getBoolean(TrackDetailActivity.this, R.string.trackdetail_show_on_lockscreen_while_recording_key, PreferencesUtils.SHOW_TRACKDETAIL_WHILE_RECORDING_ON_LOCKSCREEN);
|
|
||||||
setLockscreenPolicy();
|
setLockscreenPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,8 +153,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
private MenuItem insertPhotoMenuItem;
|
private MenuItem insertPhotoMenuItem;
|
||||||
private MenuItem markerListMenuItem;
|
private MenuItem markerListMenuItem;
|
||||||
private MenuItem shareMenuItem;
|
private MenuItem shareMenuItem;
|
||||||
private MenuItem voiceFrequencyMenuItem;
|
|
||||||
private MenuItem splitFrequencyMenuItem;
|
|
||||||
|
|
||||||
private final OnClickListener recordListener = new OnClickListener() {
|
private final OnClickListener recordListener = new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -187,6 +182,8 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
|
hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
|
||||||
photoUri = savedInstanceState != null ? (Uri) savedInstanceState.getParcelable(PHOTO_URI_KEY) : null;
|
photoUri = savedInstanceState != null ? (Uri) savedInstanceState.getParcelable(PHOTO_URI_KEY) : null;
|
||||||
hasPhoto = savedInstanceState != null && savedInstanceState.getBoolean(HAS_PHOTO_KEY, false);
|
hasPhoto = savedInstanceState != null && savedInstanceState.getBoolean(HAS_PHOTO_KEY, false);
|
||||||
@@ -230,12 +227,14 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setLockscreenPolicy() {
|
private void setLockscreenPolicy() {
|
||||||
|
boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackDetailActivity.this);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
setShowWhenLocked(showOnLockScreen);
|
setShowWhenLocked(showOnLockScreen);
|
||||||
|
} else if (showOnLockScreen) {
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
} else {
|
} else {
|
||||||
if (showOnLockScreen)
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
|
||||||
else getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +274,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putString(CURRENT_TAB_TAG_KEY, tabHost.getCurrentTabTag());
|
outState.putString(CURRENT_TAB_TAG_KEY, tabHost.getCurrentTabTag());
|
||||||
if (photoUri != null) {
|
if (photoUri != null) {
|
||||||
@@ -316,8 +315,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
insertPhotoMenuItem = menu.findItem(R.id.track_detail_insert_photo);
|
insertPhotoMenuItem = menu.findItem(R.id.track_detail_insert_photo);
|
||||||
insertPhotoMenuItem.setVisible(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(getPackageManager()) != null);
|
insertPhotoMenuItem.setVisible(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(getPackageManager()) != null);
|
||||||
shareMenuItem = menu.findItem(R.id.track_detail_share);
|
shareMenuItem = menu.findItem(R.id.track_detail_share);
|
||||||
voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency);
|
|
||||||
splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency);
|
|
||||||
markerListMenuItem = menu.findItem(R.id.track_detail_markers);
|
markerListMenuItem = menu.findItem(R.id.track_detail_markers);
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
@@ -359,12 +356,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
.putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId);
|
.putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_voice_frequency:
|
|
||||||
FrequencyDialogFragment.showDialog(getSupportFragmentManager(), R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT, R.string.menu_voice_frequency);
|
|
||||||
return true;
|
|
||||||
case R.id.track_detail_split_frequency:
|
|
||||||
FrequencyDialogFragment.showDialog(getSupportFragmentManager(), R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT, R.string.menu_split_frequency);
|
|
||||||
return true;
|
|
||||||
case R.id.track_detail_edit:
|
case R.id.track_detail_edit:
|
||||||
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
||||||
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||||
@@ -421,10 +412,16 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
/**
|
/**
|
||||||
* Gets the track id.
|
* Gets the track id.
|
||||||
*/
|
*/
|
||||||
|
// TODO Seems to be no used.
|
||||||
|
@Deprecated
|
||||||
public long getTrackId() {
|
public long getTrackId() {
|
||||||
return trackId;
|
return trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setBluetoothHeartRateSensorName(String sensorName) {
|
||||||
|
StatsUtils.setBluetoothHeartRateSensorName(this, sensorName, isRecording());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the data in the intent.
|
* Handles the data in the intent.
|
||||||
*/
|
*/
|
||||||
@@ -466,8 +463,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
insertPhotoMenuItem.setVisible(hasCamera && isRecording() && !isPaused);
|
insertPhotoMenuItem.setVisible(hasCamera && isRecording() && !isPaused);
|
||||||
shareMenuItem.setVisible(!isRecording());
|
shareMenuItem.setVisible(!isRecording());
|
||||||
markerListMenuItem.setShowAsAction(isRecording() ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
markerListMenuItem.setShowAsAction(isRecording() ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||||
voiceFrequencyMenuItem.setVisible(isRecording());
|
|
||||||
splitFrequencyMenuItem.setVisible(isRecording());
|
|
||||||
String title;
|
String title;
|
||||||
if (isRecording()) {
|
if (isRecording()) {
|
||||||
title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording);
|
title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording);
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
|
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
|
||||||
@@ -135,22 +135,17 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(TrackListActivity.this, R.string.stats_units_key))) {
|
if (PreferencesUtils.isKey(TrackListActivity.this, R.string.stats_units_key, key)) {
|
||||||
metricUnits = PreferencesUtils.isMetricUnits(TrackListActivity.this);
|
metricUnits = PreferencesUtils.isMetricUnits(TrackListActivity.this);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(
|
if (PreferencesUtils.isKey(TrackListActivity.this, R.string.recording_track_id_key, key)) {
|
||||||
PreferencesUtils.getKey(TrackListActivity.this, R.string.recording_track_id_key))) {
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackListActivity.this);
|
||||||
recordingTrackId = PreferencesUtils.getLong(
|
|
||||||
TrackListActivity.this, R.string.recording_track_id_key);
|
|
||||||
if (key != null && PreferencesUtils.isRecording(recordingTrackId)) {
|
if (key != null && PreferencesUtils.isRecording(recordingTrackId)) {
|
||||||
trackRecordingServiceConnection.startAndBind();
|
trackRecordingServiceConnection.startAndBind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(
|
if (PreferencesUtils.isKey(TrackListActivity.this, R.string.recording_track_paused_key, key)) {
|
||||||
TrackListActivity.this, R.string.recording_track_paused_key))) {
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackListActivity.this);
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(TrackListActivity.this,
|
|
||||||
R.string.recording_track_paused_key,
|
|
||||||
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@@ -226,12 +221,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
private final OnClickListener recordListener = new OnClickListener() {
|
private final OnClickListener recordListener = new OnClickListener() {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (recordingTrackId == PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
if (!PreferencesUtils.isRecording(recordingTrackId)) {
|
||||||
// Not recording -> Recording
|
// Not recording -> Recording
|
||||||
updateMenuItems(false, true);
|
updateMenuItems(false, true);
|
||||||
startRecording();
|
startRecording();
|
||||||
} else {
|
} else if (recordingTrackPaused) {
|
||||||
if (recordingTrackPaused) {
|
|
||||||
// Paused -> Resume
|
// Paused -> Resume
|
||||||
updateMenuItems(false, true);
|
updateMenuItems(false, true);
|
||||||
trackRecordingServiceConnection.resumeTrack();
|
trackRecordingServiceConnection.resumeTrack();
|
||||||
@@ -242,7 +236,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
trackRecordingServiceConnection.pauseTrack();
|
trackRecordingServiceConnection.pauseTrack();
|
||||||
trackController.update(true, true);
|
trackController.update(true, true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -250,6 +243,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
contentProviderUtils = ContentProviderUtils.Factory.get(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,6 @@ public class SensorDataSetLocation extends Location {
|
|||||||
|
|
||||||
private SensorDataSet sensorDataSet = null;
|
private SensorDataSet sensorDataSet = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* The id of this location from the provider.
|
|
||||||
*/
|
|
||||||
private int id = -1;
|
|
||||||
|
|
||||||
public SensorDataSetLocation(Location location, SensorDataSet sensorDataSet) {
|
public SensorDataSetLocation(Location location, SensorDataSet sensorDataSet) {
|
||||||
super(location);
|
super(location);
|
||||||
this.sensorDataSet = sensorDataSet;
|
this.sensorDataSet = sensorDataSet;
|
||||||
@@ -50,17 +45,8 @@ public class SensorDataSetLocation extends Location {
|
|||||||
this.sensorDataSet = sensorDataSet;
|
this.sensorDataSet = sensorDataSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
super.reset();
|
super.reset();
|
||||||
sensorDataSet = null;
|
sensorDataSet = null;
|
||||||
id = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,13 +254,13 @@ public class TrackDataHub implements DataSourceListener {
|
|||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_id_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_track_id_key, key)) {
|
||||||
recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_paused_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.stats_units_key))) {
|
if (PreferencesUtils.isKey(context, R.string.stats_units_key, key)) {
|
||||||
metricUnits = PreferencesUtils.isMetricUnits(context);
|
metricUnits = PreferencesUtils.isMetricUnits(context);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
||||||
@@ -270,7 +270,7 @@ public class TrackDataHub implements DataSourceListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.stats_rate_key))) {
|
if (PreferencesUtils.isKey(context, R.string.stats_rate_key, key)) {
|
||||||
reportSpeed = PreferencesUtils.isReportSpeed(context);
|
reportSpeed = PreferencesUtils.isReportSpeed(context);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
||||||
@@ -280,8 +280,8 @@ public class TrackDataHub implements DataSourceListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_gps_accuracy_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) {
|
||||||
recordingGpsAccuracy = PreferencesUtils.getInt(context, R.string.recording_gps_accuracy_key, PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
||||||
if (trackDataListener.onRecordingGpsAccuracy(recordingGpsAccuracy)) {
|
if (trackDataListener.onRecordingGpsAccuracy(recordingGpsAccuracy)) {
|
||||||
@@ -290,8 +290,8 @@ public class TrackDataHub implements DataSourceListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_distance_interval_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_distance_interval_key, key)) {
|
||||||
recordingDistanceInterval = PreferencesUtils.getInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) {
|
||||||
if (trackDataListener.onRecordingDistanceIntervalChanged(recordingDistanceInterval)) {
|
if (trackDataListener.onRecordingDistanceIntervalChanged(recordingDistanceInterval)) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ public final class SensorDataSet {
|
|||||||
|
|
||||||
public static final float DATA_UNAVAILABLE = Float.NaN;
|
public static final float DATA_UNAVAILABLE = Float.NaN;
|
||||||
|
|
||||||
//TODO It might be necessary to consider: sensor if sensor was connected as well.
|
//TODO It might be necessary to consider: if sensor was connected as well.
|
||||||
public String sensorName;
|
public String sensorName;
|
||||||
public String sensorAddress;
|
public String sensorAddress;
|
||||||
private float heartRate;
|
private float heartRate;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
|
|
||||||
private boolean metricUnits = true;
|
private boolean metricUnits = true;
|
||||||
private boolean reportSpeed = true;
|
private boolean reportSpeed = true;
|
||||||
private int recordingDistanceInterval = PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT;
|
private int recordingDistanceInterval;
|
||||||
|
|
||||||
// Modes of operation
|
// Modes of operation
|
||||||
private boolean chartByDistance = true;
|
private boolean chartByDistance = true;
|
||||||
@@ -99,6 +99,8 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceIntervalDefault(getContext());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a chartView here to store data thus won't need to reload all the data on every onStart or onResume.
|
* Create a chartView here to store data thus won't need to reload all the data on every onStart or onResume.
|
||||||
*/
|
*/
|
||||||
@@ -263,8 +265,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
}
|
}
|
||||||
reportSpeed = speed;
|
reportSpeed = speed;
|
||||||
chartView.setReportSpeed(reportSpeed);
|
chartView.setReportSpeed(reportSpeed);
|
||||||
boolean chartShowSpeed = PreferencesUtils.getBoolean(
|
boolean chartShowSpeed = PreferencesUtils.shouldChartShowSpeed(getActivity());
|
||||||
getActivity(), R.string.chart_show_speed_key, PreferencesUtils.CHART_SHOW_SPEED_DEFAULT);
|
|
||||||
setSeriesEnabled(ChartView.SPEED_SERIES, chartShowSpeed && reportSpeed);
|
setSeriesEnabled(ChartView.SPEED_SERIES, chartShowSpeed && reportSpeed);
|
||||||
setSeriesEnabled(ChartView.PACE_SERIES, chartShowSpeed && !reportSpeed);
|
setSeriesEnabled(ChartView.PACE_SERIES, chartShowSpeed && !reportSpeed);
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@@ -309,24 +310,24 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
reloadTrackDataHub();
|
reloadTrackDataHub();
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (setSeriesEnabled(ChartView.ELEVATION_SERIES, PreferencesUtils.getBoolean(getActivity(), R.string.chart_show_elevation_key, PreferencesUtils.CHART_SHOW_ELEVATION_DEFAULT))) {
|
if (setSeriesEnabled(ChartView.ELEVATION_SERIES, PreferencesUtils.shouldChartShowElevation(getActivity()))) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean chartShowSpeed = PreferencesUtils.getBoolean(getActivity(), R.string.chart_show_speed_key, PreferencesUtils.CHART_SHOW_SPEED_DEFAULT);
|
boolean chartShowSpeed = PreferencesUtils.shouldChartShowSpeed(getActivity());
|
||||||
if (setSeriesEnabled(ChartView.SPEED_SERIES, chartShowSpeed && reportSpeed)) {
|
if (setSeriesEnabled(ChartView.SPEED_SERIES, chartShowSpeed && reportSpeed)) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (setSeriesEnabled(ChartView.PACE_SERIES, chartShowSpeed && !reportSpeed)) {
|
if (setSeriesEnabled(ChartView.PACE_SERIES, chartShowSpeed && !reportSpeed)) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (setSeriesEnabled(ChartView.POWER_SERIES, PreferencesUtils.getBoolean(getActivity(), R.string.chart_show_power_key, PreferencesUtils.CHART_SHOW_POWER_DEFAULT))) {
|
if (setSeriesEnabled(ChartView.POWER_SERIES, PreferencesUtils.shouldChartShowPower(getActivity()))) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (setSeriesEnabled(ChartView.CADENCE_SERIES, PreferencesUtils.getBoolean(getActivity(), R.string.chart_show_cadence_key, PreferencesUtils.CHART_SHOW_CADENCE_DEFAULT))) {
|
if (setSeriesEnabled(ChartView.CADENCE_SERIES, PreferencesUtils.shouldChartShowCadence(getActivity()))) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (setSeriesEnabled(ChartView.HEART_RATE_SERIES, PreferencesUtils.getBoolean(getActivity(), R.string.chart_show_heart_rate_key, PreferencesUtils.CHART_SHOW_HEART_RATE_DEFAULT))) {
|
if (setSeriesEnabled(ChartView.HEART_RATE_SERIES, PreferencesUtils.shouldChartShowHeartRate(getActivity()))) {
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
|
|||||||
-14
@@ -1,6 +1,5 @@
|
|||||||
package de.dennisguse.opentracks.fragments;
|
package de.dennisguse.opentracks.fragments;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -79,19 +78,6 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Only used by obsolete Androidx preferences. Remove when onAttach(Context) is called.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onAttach(@NonNull Activity activity) {
|
|
||||||
super.onAttach(activity);
|
|
||||||
try {
|
|
||||||
chooseActivityTypeCaller = (ChooseActivityTypeCaller) activity;
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
throw new ClassCastException(activity + " must implement " + ChooseActivityTypeCaller.class.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onAttach(@NonNull Context context) {
|
public void onAttach(@NonNull Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.fragments;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A DialogFragment to configure frequency.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class FrequencyDialogFragment extends DialogFragment {
|
|
||||||
|
|
||||||
private static final String FREQUENCY_DIALOG_TAG = "frequencyDialog";
|
|
||||||
private int preferenceId;
|
|
||||||
private int defaultValue;
|
|
||||||
private int titleId;
|
|
||||||
|
|
||||||
public FrequencyDialogFragment(int preferenceId, int defaultValue, int titleId) {
|
|
||||||
this.preferenceId = preferenceId;
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.titleId = titleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void showDialog(FragmentManager fragmentManager, int preferenceId, int defaultValue, int titleId) {
|
|
||||||
new FrequencyDialogFragment(preferenceId, defaultValue, titleId).show(fragmentManager, FREQUENCY_DIALOG_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NonNull
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
FragmentActivity fragmentActivity = getActivity();
|
|
||||||
|
|
||||||
int frequencyValue = PreferencesUtils.getInt(fragmentActivity, preferenceId, defaultValue);
|
|
||||||
|
|
||||||
return new AlertDialog.Builder(fragmentActivity).setPositiveButton(
|
|
||||||
R.string.generic_ok, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
int listIndex = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
|
|
||||||
PreferencesUtils.setInt(getActivity(), preferenceId, getFrequencyValue(listIndex));
|
|
||||||
}
|
|
||||||
}).setSingleChoiceItems(
|
|
||||||
getFrequencyDisplayOptions(fragmentActivity), getListIndex(frequencyValue), null)
|
|
||||||
.setTitle(titleId).create();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the frequency display options.
|
|
||||||
*/
|
|
||||||
private String[] getFrequencyDisplayOptions(FragmentActivity fragmentActivity) {
|
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(fragmentActivity);
|
|
||||||
return StringUtils.getFrequencyOptions(fragmentActivity, metricUnits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list index for a frequency value.
|
|
||||||
* Returns 0 if the value is not on the list.
|
|
||||||
*/
|
|
||||||
private int getListIndex(int frequencyValue) {
|
|
||||||
String[] values = getResources().getStringArray(R.array.frequency_values);
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
if (frequencyValue == Integer.parseInt(values[i])) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the frequency value from a list index.
|
|
||||||
*
|
|
||||||
* @param listIndex the list index
|
|
||||||
*/
|
|
||||||
private int getFrequencyValue(int listIndex) {
|
|
||||||
String[] values = getResources().getStringArray(R.array.frequency_values);
|
|
||||||
return Integer.parseInt(values[listIndex]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -45,7 +45,6 @@ import de.dennisguse.opentracks.services.ITrackRecordingService;
|
|||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.stats.TripStatistics;
|
import de.dennisguse.opentracks.stats.TripStatistics;
|
||||||
import de.dennisguse.opentracks.util.LocationUtils;
|
import de.dennisguse.opentracks.util.LocationUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
import de.dennisguse.opentracks.util.StatsUtils;
|
import de.dennisguse.opentracks.util.StatsUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
import de.dennisguse.opentracks.util.UnitConversions;
|
||||||
@@ -67,7 +66,6 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
|||||||
|
|
||||||
private Location lastLocation = null;
|
private Location lastLocation = null;
|
||||||
private TripStatistics lastTripStatistics = null;
|
private TripStatistics lastTripStatistics = null;
|
||||||
private SensorDataSet sensorDataSet = null;
|
|
||||||
|
|
||||||
private final Runnable updateUIeachSecond = new Runnable() {
|
private final Runnable updateUIeachSecond = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -82,7 +80,7 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
private String category = "";
|
private String category = "";
|
||||||
private int recordingGpsAccuracy = PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT;
|
private int recordingGpsAccuracy;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
@@ -92,6 +90,9 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
|
recordingGpsAccuracy = Integer.parseInt(getContext().getResources().getString(R.string.recording_gps_accuracy_default));
|
||||||
|
|
||||||
handlerUpdateUI = new Handler();
|
handlerUpdateUI = new Handler();
|
||||||
|
|
||||||
Spinner activityTypeIcon = getView().findViewById(R.id.stats_activity_type_icon);
|
Spinner activityTypeIcon = getView().findViewById(R.id.stats_activity_type_icon);
|
||||||
@@ -304,9 +305,10 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
|||||||
*/
|
*/
|
||||||
private void updateSensorDataUI() {
|
private void updateSensorDataUI() {
|
||||||
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
|
|
||||||
|
SensorDataSet sensorDataSet = null;
|
||||||
if (trackRecordingService == null) {
|
if (trackRecordingService == null) {
|
||||||
Log.d(STATS_FRAGMENT_TAG, "Cannot get the track recording service.");
|
Log.d(STATS_FRAGMENT_TAG, "Cannot get the track recording service.");
|
||||||
sensorDataSet = null;
|
|
||||||
} else {
|
} else {
|
||||||
//TODO sensorState = trackRecordingService.getSensorState();
|
//TODO sensorState = trackRecordingService.getSensorState();
|
||||||
sensorDataSet = trackRecordingService.getSensorData();
|
sensorDataSet = trackRecordingService.getSensorData();
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
|
||||||
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.content.Track;
|
import de.dennisguse.opentracks.content.Track;
|
||||||
import de.dennisguse.opentracks.content.TracksColumns;
|
import de.dennisguse.opentracks.content.TracksColumns;
|
||||||
@@ -100,7 +99,7 @@ public class ExportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|||||||
try {
|
try {
|
||||||
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
|
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
|
||||||
boolean isRecording = PreferencesUtils.isRecording(exportActivity);
|
boolean isRecording = PreferencesUtils.isRecording(exportActivity);
|
||||||
boolean isPaused = PreferencesUtils.getBoolean(exportActivity, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
boolean isPaused = PreferencesUtils.isRecordingTrackPaused(exportActivity);
|
||||||
// Get the wake lock if not recording or paused
|
// Get the wake lock if not recording or paused
|
||||||
if (!isRecording || isPaused) {
|
if (!isRecording || isPaused) {
|
||||||
wakeLock = SystemUtils.acquireWakeLock(exportActivity, wakeLock);
|
wakeLock = SystemUtils.acquireWakeLock(exportActivity, wakeLock);
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
this.importTrackId = importTrackId;
|
this.importTrackId = importTrackId;
|
||||||
this.contentProviderUtils = contentProviderUtils;
|
this.contentProviderUtils = contentProviderUtils;
|
||||||
this.recordingDistanceInterval = PreferencesUtils.getInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
this.recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context);
|
||||||
trackIds = new ArrayList<>();
|
trackIds = new ArrayList<>();
|
||||||
waypoints = new ArrayList<>();
|
waypoints = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
|
||||||
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.content.Track;
|
import de.dennisguse.opentracks.content.Track;
|
||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
@@ -104,7 +103,7 @@ public class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|||||||
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
|
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
|
||||||
// Get the wake lock if not recording or paused
|
// Get the wake lock if not recording or paused
|
||||||
boolean isRecording = PreferencesUtils.isRecording(importActivity);
|
boolean isRecording = PreferencesUtils.isRecording(importActivity);
|
||||||
boolean isPaused = PreferencesUtils.getBoolean(importActivity, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
boolean isPaused = PreferencesUtils.isRecordingTrackPaused(importActivity);
|
||||||
if (!isRecording || isPaused) {
|
if (!isRecording || isPaused) {
|
||||||
wakeLock = SystemUtils.acquireWakeLock(importActivity, wakeLock);
|
wakeLock = SystemUtils.acquireWakeLock(importActivity, wakeLock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
* @param trackId the trackId
|
* @param trackId the trackId
|
||||||
*/
|
*/
|
||||||
private void cleanImport(long trackId) {
|
private void cleanImport(long trackId) {
|
||||||
if (trackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
if (PreferencesUtils.isRecording(trackId)) {
|
||||||
ContentProviderUtils contentProviderUtils = ContentProviderUtils.Factory.get(context);
|
ContentProviderUtils contentProviderUtils = ContentProviderUtils.Factory.get(context);
|
||||||
contentProviderUtils.deleteTrack(context, trackId);
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ import de.dennisguse.opentracks.content.Waypoint.WaypointType;
|
|||||||
import de.dennisguse.opentracks.content.WaypointCreationRequest;
|
import de.dennisguse.opentracks.content.WaypointCreationRequest;
|
||||||
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
||||||
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
||||||
import de.dennisguse.opentracks.services.sensors.RemoteSensorManagerFactory;
|
|
||||||
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
|
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
|
||||||
import de.dennisguse.opentracks.services.tasks.PeriodicTaskExecutor;
|
import de.dennisguse.opentracks.services.tasks.PeriodicTaskExecutor;
|
||||||
import de.dennisguse.opentracks.services.tasks.SplitPeriodicTaskFactory;
|
import de.dennisguse.opentracks.services.tasks.SplitPeriodicTaskFactory;
|
||||||
@@ -118,52 +117,49 @@ public class TrackRecordingService extends Service {
|
|||||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_id_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_track_id_key, key)) {
|
||||||
// Only through the TrackRecordingService can one stop a recording and set the recordingTrackId to -1L.
|
// Only through the TrackRecordingService can one stop a recording and set the recordingTrackId to -1L.
|
||||||
if (PreferencesUtils.isRecording(context)) {
|
if (PreferencesUtils.isRecording(context)) {
|
||||||
recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_paused_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.stats_units_key))) {
|
if (PreferencesUtils.isKey(context, R.string.stats_units_key, key)) {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
|
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
|
||||||
voiceExecutor.setMetricUnits(metricUnits);
|
voiceExecutor.setMetricUnits(metricUnits);
|
||||||
splitExecutor.setMetricUnits(metricUnits);
|
splitExecutor.setMetricUnits(metricUnits);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.voice_frequency_key))) {
|
if (PreferencesUtils.isKey(context, R.string.voice_frequency_key, key)) {
|
||||||
voiceExecutor.setTaskFrequency(PreferencesUtils.getInt(context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT));
|
voiceExecutor.setTaskFrequency(PreferencesUtils.getVoiceFrequency(context));
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.split_frequency_key))) {
|
if (PreferencesUtils.isKey(context, R.string.split_frequency_key, key)) {
|
||||||
splitExecutor.setTaskFrequency(PreferencesUtils.getInt(context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT));
|
splitExecutor.setTaskFrequency(PreferencesUtils.getSplitFrequency(context));
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.min_recording_interval_key))) {
|
if (PreferencesUtils.isKey(context, R.string.min_recording_interval_key, key)) {
|
||||||
int minRecordingInterval = PreferencesUtils.getInt(context, R.string.min_recording_interval_key, PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT);
|
int minRecordingInterval = PreferencesUtils.getMinRecordingInterval(context);
|
||||||
switch (minRecordingInterval) {
|
if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
|
||||||
case PreferencesUtils.MIN_RECORDING_INTERVAL_ADAPT_BATTERY_LIFE:
|
// Choose battery life over moving time accuracy.
|
||||||
// Choose battery life over moving time accuracy.
|
locationListenerPolicy = new AdaptiveLocationListenerPolicy(30 * UnitConversions.ONE_SECOND, 5 * ONE_MINUTE, 5);
|
||||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(30 * UnitConversions.ONE_SECOND, 5 * ONE_MINUTE, 5);
|
} else if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
|
||||||
break;
|
// Get all the updates.
|
||||||
case PreferencesUtils.MIN_RECORDING_INTERVAL_ADAPT_ACCURACY:
|
locationListenerPolicy = new AdaptiveLocationListenerPolicy(UnitConversions.ONE_SECOND, 30 * UnitConversions.ONE_SECOND, 0);
|
||||||
// Get all the updates.
|
} else {
|
||||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(UnitConversions.ONE_SECOND, 30 * UnitConversions.ONE_SECOND, 0);
|
locationListenerPolicy = new AbsoluteLocationListenerPolicy(minRecordingInterval * UnitConversions.ONE_SECOND);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
locationListenerPolicy = new AbsoluteLocationListenerPolicy(minRecordingInterval * UnitConversions.ONE_SECOND);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_distance_interval_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_distance_interval_key, key)) {
|
||||||
recordingDistanceInterval = PreferencesUtils.getInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.max_recording_distance_key))) {
|
if (PreferencesUtils.isKey(context, R.string.max_recording_distance_key, key)) {
|
||||||
maxRecordingDistance = PreferencesUtils.getInt(context, R.string.max_recording_distance_key, PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT);
|
maxRecordingDistance = PreferencesUtils.getMaxRecordingDistance(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_gps_accuracy_key))) {
|
if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) {
|
||||||
recordingGpsAccuracy = PreferencesUtils.getInt(context, R.string.recording_gps_accuracy_key, PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
||||||
}
|
}
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.auto_resume_track_timeout_key))) {
|
if (PreferencesUtils.isKey(context, R.string.auto_resume_track_timeout_key, key)) {
|
||||||
autoResumeTrackTimeout = PreferencesUtils.getInt(context, R.string.auto_resume_track_timeout_key, PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
autoResumeTrackTimeout = PreferencesUtils.getAutoResumeTrackTimeout(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -266,7 +262,7 @@ public class TrackRecordingService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
if (remoteSensorManager != null) {
|
if (remoteSensorManager != null) {
|
||||||
RemoteSensorManagerFactory.releaseSystemSensorManager();
|
remoteSensorManager.stop();
|
||||||
remoteSensorManager = null;
|
remoteSensorManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,17 +461,19 @@ public class TrackRecordingService extends Service {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int retries = PreferencesUtils.getInt(this, R.string.auto_resume_track_current_retry_key, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT);
|
int retries = PreferencesUtils.getAutoResumeTrackCurrentRetryDefault(this);
|
||||||
if (retries >= MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS) {
|
if (retries >= MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS) {
|
||||||
Log.d(TAG, "Not resuming. Exceeded maximum retry attempts.");
|
Log.d(TAG, "Not resuming. Exceeded maximum retry attempts.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PreferencesUtils.setInt(this, R.string.auto_resume_track_current_retry_key, retries + 1);
|
PreferencesUtils.incrementAutoResumeTrackCurrentRetryDefault(this);
|
||||||
|
|
||||||
if (autoResumeTrackTimeout == PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_NEVER) {
|
if (autoResumeTrackTimeout == Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_never))) {
|
||||||
Log.d(TAG, "Not resuming. Auto-resume track timeout set to never.");
|
Log.d(TAG, "Not resuming. Auto-resume track timeout set to never.");
|
||||||
return false;
|
return false;
|
||||||
} else if (autoResumeTrackTimeout == PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_ALWAYS) {
|
}
|
||||||
|
|
||||||
|
if (autoResumeTrackTimeout == Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_always))) {
|
||||||
Log.d(TAG, "Resuming. Auto-resume track timeout set to always.");
|
Log.d(TAG, "Resuming. Auto-resume track timeout set to always.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -509,13 +507,13 @@ public class TrackRecordingService extends Service {
|
|||||||
|
|
||||||
// Update shared preferences
|
// Update shared preferences
|
||||||
updateRecordingState(trackId, false);
|
updateRecordingState(trackId, false);
|
||||||
PreferencesUtils.setInt(this, R.string.auto_resume_track_current_retry_key, 0);
|
PreferencesUtils.resetAutoResumeTrackCurrentRetryDefault(this);
|
||||||
|
|
||||||
// Update database
|
// Update database
|
||||||
track.setId(trackId);
|
track.setId(trackId);
|
||||||
track.setName(TrackNameUtils.getTrackName(this, trackId, now));
|
track.setName(TrackNameUtils.getTrackName(this, trackId, now));
|
||||||
|
|
||||||
String category = PreferencesUtils.getString(this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
String category = PreferencesUtils.getDefaultActivity(this);
|
||||||
track.setCategory(category);
|
track.setCategory(category);
|
||||||
track.setIcon(TrackIconUtils.getIconValue(this, category));
|
track.setIcon(TrackIconUtils.getIconValue(this, category));
|
||||||
track.setTripStatistics(trackTripStatisticsUpdater.getTripStatistics());
|
track.setTripStatistics(trackTripStatisticsUpdater.getTripStatistics());
|
||||||
@@ -595,7 +593,8 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
private void startRecording(boolean trackStarted) {
|
private void startRecording(boolean trackStarted) {
|
||||||
// Update instance variables
|
// Update instance variables
|
||||||
remoteSensorManager = RemoteSensorManagerFactory.getSystemSensorManager(this);
|
remoteSensorManager = new BluetoothRemoteSensorManager(this);
|
||||||
|
remoteSensorManager.start();
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
currentSegmentHasLocation = false;
|
currentSegmentHasLocation = false;
|
||||||
isIdle = false;
|
isIdle = false;
|
||||||
@@ -693,7 +692,7 @@ public class TrackRecordingService extends Service {
|
|||||||
|
|
||||||
// Update instance variables
|
// Update instance variables
|
||||||
if (remoteSensorManager != null) {
|
if (remoteSensorManager != null) {
|
||||||
RemoteSensorManagerFactory.releaseSystemSensorManager();
|
remoteSensorManager.stop();
|
||||||
remoteSensorManager = null;
|
remoteSensorManager = null;
|
||||||
}
|
}
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
|
|||||||
+3
-3
@@ -203,9 +203,9 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death
|
|||||||
if (PreferencesUtils.isRecording(context)) {
|
if (PreferencesUtils.isRecording(context)) {
|
||||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
PreferencesUtils.setLong(context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||||
}
|
}
|
||||||
boolean recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
boolean recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(context);
|
||||||
if (!recordingTrackPaused) {
|
if (!recordingTrackPaused) {
|
||||||
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
PreferencesUtils.defaultRecordingTrackPaused(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death
|
|||||||
try {
|
try {
|
||||||
if (showEditor) {
|
if (showEditor) {
|
||||||
// Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L.
|
// Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L.
|
||||||
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
|
long recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
||||||
trackRecordingService.endCurrentTrack();
|
trackRecordingService.endCurrentTrack();
|
||||||
if (PreferencesUtils.isRecording(context)) {
|
if (PreferencesUtils.isRecording(context)) {
|
||||||
Intent intent = IntentUtils.newIntent(context, TrackEditActivity.class)
|
Intent intent = IntentUtils.newIntent(context, TrackEditActivity.class)
|
||||||
|
|||||||
+14
-6
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothGatt;
|
|||||||
import android.bluetooth.BluetoothGattCallback;
|
import android.bluetooth.BluetoothGattCallback;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
import android.bluetooth.BluetoothGattDescriptor;
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
import android.bluetooth.BluetoothGattService;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -36,7 +37,6 @@ import de.dennisguse.opentracks.util.BluetoothUtils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages connection to Bluetooth LE heart rate monitor.
|
* Manages connection to Bluetooth LE heart rate monitor.
|
||||||
* TODO: shutdown connection.
|
|
||||||
*/
|
*/
|
||||||
public class BluetoothConnectionManager {
|
public class BluetoothConnectionManager {
|
||||||
|
|
||||||
@@ -46,7 +46,6 @@ public class BluetoothConnectionManager {
|
|||||||
static final int MESSAGE_READ = 3;
|
static final int MESSAGE_READ = 3;
|
||||||
static final int MESSAGE_DISCONNECTED = 4;
|
static final int MESSAGE_DISCONNECTED = 4;
|
||||||
|
|
||||||
private static final UUID HEART_RATE_SERVICE_UUID = new UUID(0x180D00001000L, 0x800000805f9b34fbL);
|
|
||||||
private static final UUID HEART_RATE_MEASUREMENT_CHAR_UUID = new UUID(0x2A3700001000L, 0x800000805f9b34fbL);
|
private static final UUID HEART_RATE_MEASUREMENT_CHAR_UUID = new UUID(0x2A3700001000L, 0x800000805f9b34fbL);
|
||||||
private static final UUID CLIENT_CHARACTERISTIC_CONFIG_UUID = new UUID(0x290200001000L, 0x800000805f9b34fbL);
|
private static final UUID CLIENT_CHARACTERISTIC_CONFIG_UUID = new UUID(0x290200001000L, 0x800000805f9b34fbL);
|
||||||
|
|
||||||
@@ -91,10 +90,18 @@ public class BluetoothConnectionManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServicesDiscovered(@NonNull BluetoothGatt gatt, int status) {
|
public void onServicesDiscovered(@NonNull BluetoothGatt gatt, int status) {
|
||||||
BluetoothGattCharacteristic characteristic = gatt
|
BluetoothGattService service = gatt.getService(BluetoothUtils.HEART_RATE_SERVICE_UUID);
|
||||||
.getService(HEART_RATE_SERVICE_UUID)
|
if (service == null) {
|
||||||
.getCharacteristic(HEART_RATE_MEASUREMENT_CHAR_UUID);
|
Log.e(TAG, "Could not get heart rate service for " + gatt.getDevice().getAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BluetoothGattCharacteristic characteristic = service.getCharacteristic(HEART_RATE_MEASUREMENT_CHAR_UUID);
|
||||||
|
if (characteristic == null) {
|
||||||
|
Log.e(TAG, "Could not get BluetoothCharacteristic for " + gatt.getDevice().getAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
gatt.setCharacteristicNotification(characteristic, true);
|
gatt.setCharacteristicNotification(characteristic, true);
|
||||||
|
|
||||||
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
|
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
|
||||||
@@ -132,8 +139,9 @@ public class BluetoothConnectionManager {
|
|||||||
|
|
||||||
Log.d(TAG, "Connecting to: " + bluetoothDevice);
|
Log.d(TAG, "Connecting to: " + bluetoothDevice);
|
||||||
|
|
||||||
setState(SensorState.CONNECTING);
|
|
||||||
bluetoothGatt = bluetoothDevice.connectGatt(this.context, true, this.connectCallback);
|
bluetoothGatt = bluetoothDevice.connectGatt(this.context, true, this.connectCallback);
|
||||||
|
|
||||||
|
setState(SensorState.CONNECTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void disconnect() {
|
public synchronized void disconnect() {
|
||||||
|
|||||||
+10
-46
@@ -26,15 +26,14 @@ import android.os.Message;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
||||||
|
import de.dennisguse.opentracks.util.BluetoothUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bluetooth sensor manager.
|
* Bluetooth LE sensor manager.
|
||||||
|
* Should only be instantiated once!
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
@@ -44,11 +43,12 @@ public class BluetoothRemoteSensorManager {
|
|||||||
|
|
||||||
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
|
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
|
||||||
|
|
||||||
private static final BluetoothAdapter bluetoothAdapter = getDefaultBluetoothAdapter();
|
private static final BluetoothAdapter bluetoothAdapter = BluetoothUtils.getDefaultBluetoothAdapter(TAG);
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
private final SharedPreferences sharedPreferences;
|
private final SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
// Handler that gets information back from the bluetoothConnectionManager
|
// Handler that gets information back from the bluetoothConnectionManager
|
||||||
private final Handler messageHandler = new Handler(Looper.getMainLooper()) {
|
private final Handler messageHandler = new Handler(Looper.getMainLooper()) {
|
||||||
@Override
|
@Override
|
||||||
@@ -85,8 +85,8 @@ public class BluetoothRemoteSensorManager {
|
|||||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (bluetoothConnectionManager != null && key == null || key.equals(PreferencesUtils.getKey(context, R.string.bluetooth_sensor_key))) {
|
if (bluetoothConnectionManager != null && PreferencesUtils.isKey(context, R.string.settings_sensor_bluetooth_heart_rate_key, key)) {
|
||||||
String address = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
String address = PreferencesUtils.getBluetoothHeartRateSensorAddress(context);
|
||||||
if (address.equals(PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT)) {
|
if (address.equals(PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT)) {
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
@@ -107,48 +107,11 @@ public class BluetoothRemoteSensorManager {
|
|||||||
/**
|
/**
|
||||||
* @param context the context
|
* @param context the context
|
||||||
*/
|
*/
|
||||||
BluetoothRemoteSensorManager(Context context) {
|
public BluetoothRemoteSensorManager(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(context);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BluetoothAdapter getDefaultBluetoothAdapter() {
|
|
||||||
// If from the main application thread, return directly
|
|
||||||
if (Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
|
|
||||||
return BluetoothAdapter.getDefaultAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the default adapter from the main application thread
|
|
||||||
final ArrayList<BluetoothAdapter> adapters = new ArrayList<>(1);
|
|
||||||
final Object mutex = new Object();
|
|
||||||
|
|
||||||
Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
handler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
adapters.add(BluetoothAdapter.getDefaultAdapter());
|
|
||||||
synchronized (mutex) {
|
|
||||||
mutex.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
while (adapters.isEmpty()) {
|
|
||||||
synchronized (mutex) {
|
|
||||||
try {
|
|
||||||
mutex.wait(UnitConversions.ONE_SECOND);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Log.e(TAG, "Interrupted while waiting for default bluetooth adapter", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapters.get(0) == null) {
|
|
||||||
Log.w(TAG, "No bluetooth adapter found.");
|
|
||||||
}
|
|
||||||
return adapters.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
startCurrentSensor();
|
startCurrentSensor();
|
||||||
@@ -182,7 +145,8 @@ public class BluetoothRemoteSensorManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String address = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
// String address = PreferencesUtils.getString(context, R.string.settings_sensor_bluetooth_heart_rate_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
||||||
|
String address = PreferencesUtils.getBluetoothHeartRateSensorAddress(context);
|
||||||
if (PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(address)) {
|
if (PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(address)) {
|
||||||
Log.w(TAG, "No bluetooth address.");
|
Log.w(TAG, "No bluetooth address.");
|
||||||
return;
|
return;
|
||||||
|
|||||||
-64
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.services.sensors;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory of {@link BluetoothRemoteSensorManager}.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
public class RemoteSensorManagerFactory {
|
|
||||||
|
|
||||||
private static BluetoothRemoteSensorManager remoteSensorManagerSystem = null;
|
|
||||||
|
|
||||||
|
|
||||||
private RemoteSensorManagerFactory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the system sensor manager.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
*/
|
|
||||||
public static BluetoothRemoteSensorManager getSystemSensorManager(Context context) {
|
|
||||||
releaseSystemSensorManager();
|
|
||||||
remoteSensorManagerSystem = getSensorManager(context);
|
|
||||||
remoteSensorManagerSystem.start();
|
|
||||||
return remoteSensorManagerSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the system sensor manager.
|
|
||||||
*/
|
|
||||||
public static void releaseSystemSensorManager() {
|
|
||||||
if (remoteSensorManagerSystem != null) {
|
|
||||||
remoteSensorManagerSystem.stop();
|
|
||||||
}
|
|
||||||
remoteSensorManagerSystem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sensor manager.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
*/
|
|
||||||
private static BluetoothRemoteSensorManager getSensorManager(Context context) {
|
|
||||||
return new BluetoothRemoteSensorManager(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,9 +17,9 @@ package de.dennisguse.opentracks.services.tasks;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
import de.dennisguse.opentracks.stats.TripStatistics;
|
import de.dennisguse.opentracks.stats.TripStatistics;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
import de.dennisguse.opentracks.util.UnitConversions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,13 +35,14 @@ public class PeriodicTaskExecutor {
|
|||||||
private final TrackRecordingService trackRecordingService;
|
private final TrackRecordingService trackRecordingService;
|
||||||
private final PeriodicTaskFactory periodicTaskFactory;
|
private final PeriodicTaskFactory periodicTaskFactory;
|
||||||
|
|
||||||
|
private final int TASK_FREQUENCY_OFF;
|
||||||
/**
|
/**
|
||||||
* The task frequency.
|
* The task frequency.
|
||||||
* A positive value is a time frequency (minutes).
|
* A positive value is a time frequency (minutes).
|
||||||
* A negative value is a distance frequency (km or mi).
|
* A negative value is a distance frequency (km or mi).
|
||||||
* A zero value is to turn off periodic task.
|
* A zero value is to turn off periodic task.
|
||||||
*/
|
*/
|
||||||
private int taskFrequency = PreferencesUtils.FREQUENCY_OFF;
|
private int taskFrequency;
|
||||||
|
|
||||||
private PeriodicTask periodicTask;
|
private PeriodicTask periodicTask;
|
||||||
|
|
||||||
@@ -56,6 +57,9 @@ public class PeriodicTaskExecutor {
|
|||||||
public PeriodicTaskExecutor(TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
|
public PeriodicTaskExecutor(TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
|
||||||
this.trackRecordingService = trackRecordingService;
|
this.trackRecordingService = trackRecordingService;
|
||||||
this.periodicTaskFactory = periodicTaskFactory;
|
this.periodicTaskFactory = periodicTaskFactory;
|
||||||
|
|
||||||
|
TASK_FREQUENCY_OFF = Integer.parseInt(trackRecordingService.getBaseContext().getResources().getString(R.string.frequency_off));
|
||||||
|
taskFrequency = TASK_FREQUENCY_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +75,7 @@ public class PeriodicTaskExecutor {
|
|||||||
timerTaskExecutor.shutdown();
|
timerTaskExecutor.shutdown();
|
||||||
timerTaskExecutor = null;
|
timerTaskExecutor = null;
|
||||||
}
|
}
|
||||||
if (taskFrequency == PreferencesUtils.FREQUENCY_OFF) {
|
if (taskFrequency == TASK_FREQUENCY_OFF) {
|
||||||
Log.d(TAG, "Task frequency is off.");
|
Log.d(TAG, "Task frequency is off.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import androidx.preference.PreferenceDialogFragmentCompat;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.util.HackUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
|
||||||
@@ -42,14 +43,6 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
|
|||||||
*/
|
*/
|
||||||
public class ActivityTypePreference extends DialogPreference {
|
public class ActivityTypePreference extends DialogPreference {
|
||||||
|
|
||||||
private SummaryProvider<DialogPreference> summaryProvider = new SummaryProvider<DialogPreference>() {
|
|
||||||
@Override
|
|
||||||
public CharSequence provideSummary(DialogPreference preference) {
|
|
||||||
String defaultActivity = PreferencesUtils.getString(ActivityTypePreference.this.getContext(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
|
||||||
return defaultActivity != null && !defaultActivity.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? defaultActivity : getContext().getString(R.string.value_unknown);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public ActivityTypePreference(Context context, AttributeSet attrs) {
|
public ActivityTypePreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
setDialogLayoutResource(R.layout.preference_activity_type);
|
setDialogLayoutResource(R.layout.preference_activity_type);
|
||||||
@@ -57,8 +50,14 @@ public class ActivityTypePreference extends DialogPreference {
|
|||||||
setNegativeButtonText(android.R.string.cancel);
|
setNegativeButtonText(android.R.string.cancel);
|
||||||
setDialogIcon(null);
|
setDialogIcon(null);
|
||||||
setPersistent(true);
|
setPersistent(true);
|
||||||
//TODO: for some reason the summary is not updated; after changing it. Enable summaryprovider, when fixed.
|
|
||||||
// setSummaryProvider(summaryProvider);
|
SummaryProvider<DialogPreference> summaryProvider = new SummaryProvider<DialogPreference>() {
|
||||||
|
@Override
|
||||||
|
public CharSequence provideSummary(DialogPreference preference) {
|
||||||
|
return PreferencesUtils.getDefaultActivity(ActivityTypePreference.this.getContext());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setSummaryProvider(summaryProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,7 +86,7 @@ public class ActivityTypePreference extends DialogPreference {
|
|||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
|
|
||||||
textView = view.findViewById(R.id.activity_type_preference_text_view);
|
textView = view.findViewById(R.id.activity_type_preference_text_view);
|
||||||
String category = PreferencesUtils.getString(context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
String category = PreferencesUtils.getDefaultActivity(context);
|
||||||
textView.setText(category);
|
textView.setText(category);
|
||||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
|
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
|
||||||
textView.setAdapter(adapter);
|
textView.setAdapter(adapter);
|
||||||
@@ -132,7 +131,7 @@ public class ActivityTypePreference extends DialogPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showIconSelectDialog() {
|
private void showIconSelectDialog() {
|
||||||
String category = PreferencesUtils.getString(getActivity(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
String category = PreferencesUtils.getDefaultActivity(getActivity());
|
||||||
ChooseActivityTypeDialogFragment.showDialog(getActivity().getSupportFragmentManager(), category);
|
ChooseActivityTypeDialogFragment.showDialog(getActivity().getSupportFragmentManager(), category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +140,8 @@ public class ActivityTypePreference extends DialogPreference {
|
|||||||
if (positiveResult) {
|
if (positiveResult) {
|
||||||
String newDefaultActivity = textView.getText().toString();
|
String newDefaultActivity = textView.getText().toString();
|
||||||
if (getPreference().callChangeListener(newDefaultActivity)) {
|
if (getPreference().callChangeListener(newDefaultActivity)) {
|
||||||
PreferencesUtils.setString(getActivity(), R.string.default_activity_key, newDefaultActivity);
|
PreferencesUtils.setDefaultActivity(getActivity(), newDefaultActivity);
|
||||||
|
HackUtils.invalidatePreference(getPreference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package de.dennisguse.opentracks.settings;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class BluetoothLeAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a unique list (by address) of devices.
|
||||||
|
*/
|
||||||
|
private final List<Device> devices = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return devices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return devices.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return devices.get(position).hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View currentView = convertView;
|
||||||
|
if (convertView == null) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||||
|
//TODO Check if there is a better way to achieve identical look and feel to ListPreference.
|
||||||
|
//Use material design single choice; for old style use: android.R.layout.select_dialog_singlechoice
|
||||||
|
currentView = inflater.inflate(androidx.appcompat.R.layout.select_dialog_singlechoice_material, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device device = devices.get(position);
|
||||||
|
TextView textView = currentView.findViewById(android.R.id.text1);
|
||||||
|
textView.setText(device.getName());
|
||||||
|
|
||||||
|
return currentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String name, String address) {
|
||||||
|
Device device = new Device(name, address);
|
||||||
|
if (!devices.contains(device)) {
|
||||||
|
devices.add(new Device(name, address));
|
||||||
|
} else {
|
||||||
|
for (Device currentDevice : devices) {
|
||||||
|
if (currentDevice.getAddress().equals(address)) {
|
||||||
|
currentDevice.setName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(BluetoothDevice bluetoothDevice) {
|
||||||
|
add(bluetoothDevice.getName(), bluetoothDevice.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device get(int index) {
|
||||||
|
return devices.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Device {
|
||||||
|
private String name;
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
public Device(String name, String address) {
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the address is identical.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof Device)) return false;
|
||||||
|
Device device = (Device) o;
|
||||||
|
return address.equals(device.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
package de.dennisguse.opentracks.settings;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.le.BluetoothLeScanner;
|
||||||
|
import android.bluetooth.le.ScanCallback;
|
||||||
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
import android.bluetooth.le.ScanResult;
|
||||||
|
import android.bluetooth.le.ScanSettings;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.ParcelUuid;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.preference.DialogPreference;
|
||||||
|
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.util.BluetoothUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference to select a discoverable Bluetooth LE device.
|
||||||
|
* Based upon ListPreference.
|
||||||
|
*/
|
||||||
|
public class BluetoothLePreference extends DialogPreference {
|
||||||
|
|
||||||
|
private final static String TAG = BluetoothLePreference.class.getSimpleName();
|
||||||
|
|
||||||
|
public BluetoothLePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BluetoothLePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BluetoothLePreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BluetoothLePreference(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
private boolean valueSet = false;
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
final boolean changed = !TextUtils.equals(this.value, value);
|
||||||
|
if (changed || !valueSet) {
|
||||||
|
this.value = value;
|
||||||
|
valueSet = true;
|
||||||
|
persistString(value);
|
||||||
|
if (changed) {
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetInitialValue(Object defaultValue) {
|
||||||
|
setValue(getPersistedString((String) defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getSummary() {
|
||||||
|
return getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BluetoothLePreferenceDialog extends PreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
|
private int selectedEntryIndex;
|
||||||
|
private BluetoothLeAdapter listAdapter = new BluetoothLeAdapter();
|
||||||
|
|
||||||
|
private BluetoothLeScanner scanner = null;
|
||||||
|
private ScanCallback scanCallback = new ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
|
super.onScanResult(callbackType, result);
|
||||||
|
Log.d(TAG, "Found device " + result.getDevice().getName() + " " + result);
|
||||||
|
|
||||||
|
listAdapter.add(result.getDevice());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBatchScanResults(List<ScanResult> results) {
|
||||||
|
for (ScanResult scanResult : results) {
|
||||||
|
listAdapter.add(scanResult.getDevice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScanFailed(int errorCode) {
|
||||||
|
super.onScanFailed(errorCode);
|
||||||
|
Log.e(TAG, "Bluetooth scan failed with errorCode " + errorCode);
|
||||||
|
Toast.makeText(getContext(), R.string.sensor_could_not_scan, Toast.LENGTH_LONG).show();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static BluetoothLePreferenceDialog newInstance(String key) {
|
||||||
|
final BluetoothLePreferenceDialog fragment = new BluetoothLePreferenceDialog();
|
||||||
|
final Bundle b = new Bundle(1);
|
||||||
|
b.putString(ARG_KEY, key);
|
||||||
|
fragment.setArguments(b);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
BluetoothAdapter bluetoothAdapter = BluetoothUtils.getDefaultBluetoothAdapter(TAG);
|
||||||
|
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
|
||||||
|
Log.w(TAG, "Bluetooth adapter is present or not enabled.");
|
||||||
|
Toast.makeText(getContext(), R.string.bluetooth_disabled, Toast.LENGTH_SHORT).show();
|
||||||
|
dismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bluetoothAdapter.isDiscovering()) {
|
||||||
|
Log.i(TAG, "Cancelling ongoing bluetooth discovery.");
|
||||||
|
bluetoothAdapter.cancelDiscovery();
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner = bluetoothAdapter.getBluetoothLeScanner();
|
||||||
|
if (scanner == null) {
|
||||||
|
Log.e(TAG, "BluetoothLeScanner is null.");
|
||||||
|
dismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String deviceNone = getContext().getString(R.string.sensor_type_value_none);
|
||||||
|
listAdapter.add(getContext().getString(R.string.value_none), deviceNone);
|
||||||
|
selectedEntryIndex = 0;
|
||||||
|
|
||||||
|
BluetoothLePreference preference = (BluetoothLePreference) getPreference();
|
||||||
|
String deviceSelected = preference.getValue();
|
||||||
|
if (!deviceNone.equals(deviceSelected)) {
|
||||||
|
listAdapter.add(preference.getValue(), preference.getValue());
|
||||||
|
selectedEntryIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(BluetoothUtils.HEART_RATE_SERVICE_UUID));
|
||||||
|
List<ScanFilter> scanFilter = new ArrayList<>();
|
||||||
|
scanFilter.add(scanFilterBuilder.build());
|
||||||
|
|
||||||
|
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
|
||||||
|
scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
|
||||||
|
|
||||||
|
scanner.startScan(scanFilter, scanSettingsBuilder.build(), scanCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Behave like ListPreferenceDialogFragmentCompat, but uses a custom listAdapter.
|
||||||
|
@Override
|
||||||
|
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||||
|
super.onPrepareDialogBuilder(builder);
|
||||||
|
|
||||||
|
builder.setSingleChoiceItems(listAdapter, selectedEntryIndex,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
selectedEntryIndex = which;
|
||||||
|
|
||||||
|
BluetoothLePreferenceDialog.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setIcon(android.R.drawable.stat_sys_data_bluetooth);
|
||||||
|
builder.setPositiveButton(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDialogClosed(boolean positiveResult) {
|
||||||
|
if (scanner != null) {
|
||||||
|
scanner.stopScan(scanCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (positiveResult && selectedEntryIndex >= 0) {
|
||||||
|
String value = listAdapter.get(selectedEntryIndex).getAddress();
|
||||||
|
BluetoothLePreference preference = (BluetoothLePreference) getPreference();
|
||||||
|
if (preference.callChangeListener(value)) {
|
||||||
|
preference.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,213 +1,163 @@
|
|||||||
package de.dennisguse.opentracks.settings;
|
package de.dennisguse.opentracks.settings;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.util.BluetoothUtils;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
import de.dennisguse.opentracks.util.UnitConversions;
|
||||||
|
|
||||||
final class PreferenceHelper {
|
final class PreferenceHelper {
|
||||||
|
|
||||||
/**
|
static String[] getMinRecordingIntervalEntries(Context context) {
|
||||||
* Sets the min recording interval options.
|
String[] entryValues = context.getResources().getStringArray(R.array.min_recording_interval_values);
|
||||||
*
|
String[] entries = new String[entryValues.length];
|
||||||
* @param options the options
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
* @param values the values
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
*/
|
|
||||||
static void setMinRecordingIntervalOptions(Context context, String[] options, String[] values) {
|
if (value == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
|
||||||
for (int i = 0; i < values.length; i++) {
|
entries[i] = context.getString(R.string.value_adapt_accuracy);
|
||||||
int value = Integer.parseInt(values[i]);
|
} else if (value == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
|
||||||
switch (value) {
|
entries[i] = context.getString(R.string.value_adapt_battery_life);
|
||||||
case PreferencesUtils.MIN_RECORDING_INTERVAL_ADAPT_BATTERY_LIFE:
|
} else if (value == PreferencesUtils.getMinRecordingIntervalDefault(context)) {
|
||||||
options[i] = context.getString(R.string.value_adapt_battery_life);
|
entries[i] = context.getString(R.string.value_smallest_recommended);
|
||||||
break;
|
} else {
|
||||||
case PreferencesUtils.MIN_RECORDING_INTERVAL_ADAPT_ACCURACY:
|
entries[i] = value < 60 ? context.getString(R.string.value_integer_second, value) : context.getString(R.string.value_integer_minute, value / 60);
|
||||||
options[i] = context.getString(R.string.value_adapt_accuracy);
|
|
||||||
break;
|
|
||||||
case PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT:
|
|
||||||
options[i] = context.getString(R.string.value_smallest_recommended);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
options[i] = value < 60 ? context.getString(R.string.value_integer_second, value) : context.getString(R.string.value_integer_minute, value / 60);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static String[] getRecordingDistanceIntervalEntries(Context context, boolean metricUnits) {
|
||||||
* Sets the recording distance interval options.
|
String[] entryValues = context.getResources().getStringArray(R.array.recording_distance_interval_values);
|
||||||
*
|
String[] entries = new String[entryValues.length];
|
||||||
* @param options the options
|
|
||||||
* @param values the values
|
final int recordingDistanceIntervalDefault = PreferencesUtils.getRecordingDistanceIntervalDefault(context);
|
||||||
* @param metricUnits true for metric units
|
|
||||||
*/
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
static void setRecordingDistanceIntervalOptions(Context context, String[] options, String[] values, boolean metricUnits) {
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
int value = Integer.parseInt(values[i]);
|
|
||||||
String displayValue;
|
String displayValue;
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
displayValue = context.getString(R.string.value_integer_meter, value);
|
displayValue = context.getString(R.string.value_integer_meter, value);
|
||||||
if (value == PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT) {
|
if (value == recordingDistanceIntervalDefault) {
|
||||||
options[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
entries[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
||||||
} else {
|
} else {
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int feet = (int) (value * UnitConversions.M_TO_FT);
|
int feet = (int) (value * UnitConversions.M_TO_FT);
|
||||||
displayValue = context.getString(R.string.value_integer_feet, feet);
|
displayValue = context.getString(R.string.value_integer_feet, feet);
|
||||||
if (value == PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT) {
|
if (value == recordingDistanceIntervalDefault) {
|
||||||
options[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
entries[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
||||||
} else {
|
} else {
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static String[] getMaxRecordingDistanceEntries(Context context, boolean metricUnits) {
|
||||||
* Sets the max recording distance options.
|
String[] entryValues = context.getResources().getStringArray(R.array.max_recording_distance_values);
|
||||||
*
|
String[] entries = new String[entryValues.length];
|
||||||
* @param options the options
|
|
||||||
* @param values the values
|
final int maxRecordingDistanceDefault = Integer.parseInt(context.getResources().getString(R.string.max_recording_distance_default));
|
||||||
* @param metricUnits true for metric units
|
|
||||||
*/
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
static void setMaxRecordingDistanceOptions(Context context, String[] options, String[] values, boolean metricUnits) {
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
int value = Integer.parseInt(values[i]);
|
|
||||||
String displayValue;
|
String displayValue;
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
displayValue = context.getString(R.string.value_integer_meter, value);
|
displayValue = context.getString(R.string.value_integer_meter, value);
|
||||||
if (value == PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT) {
|
if (value == maxRecordingDistanceDefault) {
|
||||||
options[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
entries[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
||||||
} else {
|
} else {
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int feet = (int) (value * UnitConversions.M_TO_FT);
|
int feet = (int) (value * UnitConversions.M_TO_FT);
|
||||||
if (feet < 2000) {
|
if (feet < 2000) {
|
||||||
displayValue = context.getString(R.string.value_integer_feet, feet);
|
displayValue = context.getString(R.string.value_integer_feet, feet);
|
||||||
if (value == PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT) {
|
if (value == maxRecordingDistanceDefault) {
|
||||||
options[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
entries[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
||||||
} else {
|
} else {
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double mile = feet * UnitConversions.FT_TO_MI;
|
double mile = feet * UnitConversions.FT_TO_MI;
|
||||||
displayValue = context.getString(R.string.value_float_mile, mile);
|
displayValue = context.getString(R.string.value_float_mile, mile);
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static String[] getRecordingGpsAccuracyEntries(Context context, boolean metricUnits) {
|
||||||
* Sets the recording gps accuracy options.
|
String[] entryValues = context.getResources().getStringArray(R.array.recording_gps_accuracy_values);
|
||||||
*
|
String[] entries = new String[entryValues.length];
|
||||||
* @param options the options
|
|
||||||
* @param values the values
|
final int recordingGPSAccuracyDefault = Integer.parseInt(context.getResources().getString(R.string.recording_gps_accuracy_default));
|
||||||
* @param metricUnits true for metric units
|
final int recordingGPSAccuracyExcellent = Integer.parseInt(context.getResources().getString(R.string.recording_gps_accuracy_excellent));
|
||||||
*/
|
final int recordingGPSAccuracyPoor = Integer.parseInt(context.getResources().getString(R.string.recording_gps_accuracy_poor));
|
||||||
static void setRecordingGpsAccuracyOptions(Context context, String[] options, String[] values, boolean metricUnits) {
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
int value = Integer.parseInt(values[i]);
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
String displayValue;
|
String displayValue;
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
displayValue = context.getString(R.string.value_integer_meter, value);
|
displayValue = context.getString(R.string.value_integer_meter, value);
|
||||||
switch (value) {
|
if (value == recordingGPSAccuracyDefault) {
|
||||||
case PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT:
|
entries[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
||||||
options[i] = context.getString(R.string.value_integer_meter_recommended, value);
|
} else if (value == recordingGPSAccuracyExcellent) {
|
||||||
break;
|
entries[i] = context.getString(R.string.value_integer_meter_excellent_gps, value);
|
||||||
case PreferencesUtils.RECORDING_GPS_ACCURACY_EXCELLENT:
|
} else if (value == recordingGPSAccuracyPoor) {
|
||||||
options[i] = context.getString(R.string.value_integer_meter_excellent_gps, value);
|
entries[i] = context.getString(R.string.value_integer_meter_poor_gps, value);
|
||||||
break;
|
} else {
|
||||||
case PreferencesUtils.RECORDING_GPS_ACCURACY_POOR:
|
entries[i] = displayValue;
|
||||||
options[i] = context.getString(R.string.value_integer_meter_poor_gps, value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
options[i] = displayValue;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int feet = (int) (value * UnitConversions.M_TO_FT);
|
int feet = (int) (value * UnitConversions.M_TO_FT);
|
||||||
if (feet < 2000) {
|
if (feet < 2000) {
|
||||||
displayValue = context.getString(R.string.value_integer_feet, feet);
|
displayValue = context.getString(R.string.value_integer_feet, feet);
|
||||||
switch (value) {
|
|
||||||
case PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT:
|
if (value == recordingGPSAccuracyDefault) {
|
||||||
options[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
entries[i] = context.getString(R.string.value_integer_feet_recommended, feet);
|
||||||
break;
|
} else if (value == recordingGPSAccuracyExcellent) {
|
||||||
case PreferencesUtils.RECORDING_GPS_ACCURACY_EXCELLENT:
|
entries[i] = context.getString(R.string.value_integer_feet_excellent_gps, feet);
|
||||||
options[i] = context.getString(R.string.value_integer_feet_excellent_gps, feet);
|
} else {
|
||||||
break;
|
entries[i] = displayValue;
|
||||||
default:
|
|
||||||
options[i] = displayValue;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double mile = feet * UnitConversions.FT_TO_MI;
|
double mile = feet * UnitConversions.FT_TO_MI;
|
||||||
displayValue = context.getString(R.string.value_float_mile, mile);
|
displayValue = context.getString(R.string.value_float_mile, mile);
|
||||||
if (value == PreferencesUtils.RECORDING_GPS_ACCURACY_POOR) {
|
if (value == recordingGPSAccuracyPoor) {
|
||||||
options[i] = context.getString(R.string.value_float_mile_poor_gps, mile);
|
entries[i] = context.getString(R.string.value_float_mile_poor_gps, mile);
|
||||||
} else {
|
} else {
|
||||||
options[i] = displayValue;
|
entries[i] = displayValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static String[] getAutoResumeTrackTimeoutEntries(Context context) {
|
||||||
* Sets the auto resume track timeout options.
|
String[] entryValues = context.getResources().getStringArray(R.array.auto_resume_track_timeout_values);
|
||||||
*
|
String[] entries = new String[entryValues.length];
|
||||||
* @param options the options
|
|
||||||
* @param values the values
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
*/
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
static void setAutoResumeTrackTimeoutOptions(Context context, String[] options, String[] values) {
|
if (value == Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_never))) {
|
||||||
for (int i = 0; i < values.length; i++) {
|
entries[i] = context.getString(R.string.value_never);
|
||||||
int value = Integer.parseInt(values[i]);
|
} else if (value == Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_always))) {
|
||||||
switch (value) {
|
entries[i] = context.getString(R.string.value_always);
|
||||||
case PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_NEVER:
|
} else {
|
||||||
options[i] = context.getString(R.string.value_never);
|
entries[i] = context.getString(R.string.value_integer_minute, value);
|
||||||
break;
|
|
||||||
case PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_ALWAYS:
|
|
||||||
options[i] = context.getString(R.string.value_always);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
options[i] = context.getString(R.string.value_integer_minute, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return entries;
|
||||||
* Configures the bluetooth sensor.
|
|
||||||
*/
|
|
||||||
static void configureBluetoothSensorList(ListPreference preference) {
|
|
||||||
Context context = preference.getContext();
|
|
||||||
|
|
||||||
String value = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
|
||||||
List<String> devicesNameList = new ArrayList<>();
|
|
||||||
List<String> devicesAddressList = new ArrayList<>();
|
|
||||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
if (bluetoothAdapter != null) {
|
|
||||||
BluetoothUtils.populateDeviceLists(bluetoothAdapter, devicesNameList, devicesAddressList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Was the previously configured device unpaired? Then forget it.
|
|
||||||
if (!devicesAddressList.contains(value)) {
|
|
||||||
value = PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT;
|
|
||||||
PreferencesUtils.setString(context, R.string.bluetooth_sensor_key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
devicesNameList.add(0, context.getString(R.string.value_none));
|
|
||||||
devicesAddressList.add(0, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
|
||||||
|
|
||||||
String[] values = devicesAddressList.toArray(new String[0]);
|
|
||||||
preference.setEntryValues(values);
|
|
||||||
|
|
||||||
String[] options = devicesNameList.toArray(new String[0]);
|
|
||||||
preference.setEntries(options);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.os.Bundle;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.preference.DialogPreference;
|
import androidx.preference.DialogPreference;
|
||||||
import androidx.preference.PreferenceDialogFragmentCompat;
|
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||||
|
|
||||||
@@ -17,6 +18,10 @@ public class ResetDialogPreference extends DialogPreference {
|
|||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ResetCallback {
|
||||||
|
void onReset();
|
||||||
|
}
|
||||||
|
|
||||||
public static class ResetPreferenceDialog extends PreferenceDialogFragmentCompat {
|
public static class ResetPreferenceDialog extends PreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
static PreferenceDialogFragmentCompat newInstance(String preferenceKey) {
|
static PreferenceDialogFragmentCompat newInstance(String preferenceKey) {
|
||||||
@@ -31,9 +36,14 @@ public class ResetDialogPreference extends DialogPreference {
|
|||||||
@Override
|
@Override
|
||||||
public void onDialogClosed(boolean positiveResult) {
|
public void onDialogClosed(boolean positiveResult) {
|
||||||
if (positiveResult) {
|
if (positiveResult) {
|
||||||
PreferencesUtils.resetPreferences(getActivity(), true);
|
FragmentActivity activity = getActivity();
|
||||||
|
|
||||||
Toast.makeText(getActivity(), R.string.settings_reset_done, Toast.LENGTH_SHORT).show();
|
PreferencesUtils.resetPreferences(activity, true);
|
||||||
|
Toast.makeText(activity, R.string.settings_reset_done, Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
if (activity instanceof ResetCallback) {
|
||||||
|
((ResetCallback) activity).onReset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package de.dennisguse.opentracks.settings;
|
|||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
@@ -12,12 +13,16 @@ import androidx.preference.PreferenceFragmentCompat;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.util.BluetoothUtils;
|
||||||
|
import de.dennisguse.opentracks.util.HackUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
public class SettingsActivity extends AppCompatActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
|
public class SettingsActivity extends AppCompatActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ResetDialogPreference.ResetCallback {
|
||||||
|
|
||||||
private PrefsFragment prefsFragment = new PrefsFragment();
|
private static final String TAG = SettingsActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private PrefsFragment prefsFragment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -29,7 +34,7 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
toolbar.setTitle(R.string.menu_settings);
|
toolbar.setTitle(R.string.menu_settings);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
getSupportFragmentManager().beginTransaction().replace(R.id.settings_fragment, prefsFragment).commit();
|
onReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -37,6 +42,12 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
prefsFragment.setDefaultActivity(iconValue);
|
prefsFragment.setDefaultActivity(iconValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReset() {
|
||||||
|
prefsFragment = new PrefsFragment();
|
||||||
|
getSupportFragmentManager().beginTransaction().replace(R.id.settings_fragment, prefsFragment).commit();
|
||||||
|
}
|
||||||
|
|
||||||
public static class PrefsFragment extends PreferenceFragmentCompat {
|
public static class PrefsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -46,14 +57,15 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
if (PreferencesUtils.isKey(getActivity(), R.string.recording_track_id_key, key)) {
|
||||||
@Override
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
updateUI();
|
public void run() {
|
||||||
}
|
updateReset();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
if (key == null || key.equals(PreferencesUtils.getKey(getActivity(), R.string.stats_units_key))) {
|
}
|
||||||
|
if (PreferencesUtils.isKey(getActivity(), R.string.stats_units_key, key)) {
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -61,6 +73,14 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (PreferencesUtils.isKey(getActivity(), R.string.stats_rate_key, key)) {
|
||||||
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateSpeed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,15 +89,25 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
setPreferencesFromResource(R.xml.settings, rootKey);
|
try {
|
||||||
updateUnits();
|
setPreferencesFromResource(R.xml.settings, rootKey);
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
// Some sharedPreference is broken: delete all and reset them; it is just a last resort...
|
||||||
|
Toast.makeText(getContext(), R.string.settings_error_initial_values_restored, Toast.LENGTH_LONG).show();
|
||||||
|
PreferencesUtils.resetPreferences(getContext(), true);
|
||||||
|
|
||||||
|
setPreferencesFromResource(R.xml.settings, rootKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
PreferencesUtils.getSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
PreferencesUtils.getSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
updateUI();
|
updateSpeed();
|
||||||
|
updateUnits();
|
||||||
|
updateReset();
|
||||||
|
updateBluetooth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,41 +116,6 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
PreferencesUtils.getSharedPreferences(getActivity()).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
PreferencesUtils.getSharedPreferences(getActivity()).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configFrequencyPreference(int key, boolean metricUnits) {
|
|
||||||
ListPreference preference = findPreference(getString(key));
|
|
||||||
|
|
||||||
String[] options = StringUtils.getFrequencyOptions(getActivity(), metricUnits);
|
|
||||||
preference.setEntries(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configListPreference(int key, int valueArray, boolean metricUnits) {
|
|
||||||
//TODO Can we make values an int array?
|
|
||||||
String[] values = getResources().getStringArray(valueArray);
|
|
||||||
final String[] options = new String[values.length];
|
|
||||||
switch (key) {
|
|
||||||
case R.string.min_recording_interval_key:
|
|
||||||
PreferenceHelper.setMinRecordingIntervalOptions(getActivity(), options, values);
|
|
||||||
break;
|
|
||||||
case R.string.recording_distance_interval_key:
|
|
||||||
PreferenceHelper.setRecordingDistanceIntervalOptions(getActivity(), options, values, metricUnits);
|
|
||||||
break;
|
|
||||||
case R.string.max_recording_distance_key:
|
|
||||||
PreferenceHelper.setMaxRecordingDistanceOptions(getActivity(), options, values, metricUnits);
|
|
||||||
break;
|
|
||||||
case R.string.recording_gps_accuracy_key:
|
|
||||||
PreferenceHelper.setRecordingGpsAccuracyOptions(getActivity(), options, values, metricUnits);
|
|
||||||
break;
|
|
||||||
case R.string.auto_resume_track_timeout_key:
|
|
||||||
PreferenceHelper.setAutoResumeTrackTimeoutOptions(getActivity(), options, values);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ListPreference listPreference = findPreference(getString(key));
|
|
||||||
listPreference.setEntries(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisplayPreferenceDialog(Preference preference) {
|
public void onDisplayPreferenceDialog(Preference preference) {
|
||||||
DialogFragment dialogFragment = null;
|
DialogFragment dialogFragment = null;
|
||||||
@@ -129,6 +124,8 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
} else if (preference instanceof ActivityTypePreference) {
|
} else if (preference instanceof ActivityTypePreference) {
|
||||||
activityPreferenceDialog = ActivityTypePreference.ActivityPreferenceDialog.newInstance(preference.getKey());
|
activityPreferenceDialog = ActivityTypePreference.ActivityPreferenceDialog.newInstance(preference.getKey());
|
||||||
dialogFragment = activityPreferenceDialog;
|
dialogFragment = activityPreferenceDialog;
|
||||||
|
} else if (preference instanceof BluetoothLePreference) {
|
||||||
|
dialogFragment = BluetoothLePreference.BluetoothLePreferenceDialog.newInstance(preference.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialogFragment != null) {
|
if (dialogFragment != null) {
|
||||||
@@ -146,37 +143,53 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUI() {
|
private void updateReset() {
|
||||||
final boolean isRecording = PreferencesUtils.isRecording(getActivity());
|
final boolean isRecording = PreferencesUtils.isRecording(getActivity());
|
||||||
Preference resetPreference = findPreference(getString(R.string.settings_reset_key));
|
Preference resetPreference = findPreference(getString(R.string.settings_reset_key));
|
||||||
resetPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : "");
|
resetPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : "");
|
||||||
resetPreference.setEnabled(!isRecording);
|
resetPreference.setEnabled(!isRecording);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSpeed() {
|
||||||
Preference speedCheckBoxPreference = findPreference(getString(R.string.chart_show_speed_key));
|
Preference speedCheckBoxPreference = findPreference(getString(R.string.chart_show_speed_key));
|
||||||
speedCheckBoxPreference.setTitle(PreferencesUtils.isReportSpeed(getActivity()) ? R.string.stats_speed : R.string.stats_pace);
|
speedCheckBoxPreference.setTitle(PreferencesUtils.isReportSpeed(getActivity()) ? R.string.stats_speed : R.string.stats_pace);
|
||||||
|
}
|
||||||
|
|
||||||
ListPreference bluetoothPreference = findPreference(getString(R.string.bluetooth_sensor_key));
|
private void updateBluetooth() {
|
||||||
PreferenceHelper.configureBluetoothSensorList(bluetoothPreference);
|
// Disable Bluetooth preference if device does not have Bluetooth
|
||||||
|
BluetoothLePreference bluetoothPreference = findPreference(getString(R.string.settings_sensor_bluetooth_heart_rate_key));
|
||||||
|
bluetoothPreference.setVisible(BluetoothUtils.hasBluetooth(TAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUnits() {
|
private void updateUnits() {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(getActivity());
|
boolean metricUnits = PreferencesUtils.isMetricUnits(getActivity());
|
||||||
|
|
||||||
configFrequencyPreference(R.string.voice_frequency_key, metricUnits);
|
ListPreference voiceFrequency = findPreference(getString(R.string.voice_frequency_key));
|
||||||
configFrequencyPreference(R.string.split_frequency_key, metricUnits);
|
voiceFrequency.setEntries(StringUtils.getFrequencyOptions(getActivity(), metricUnits));
|
||||||
configListPreference(R.string.min_recording_interval_key, R.array.min_recording_interval_values, metricUnits);
|
|
||||||
configListPreference(R.string.recording_distance_interval_key, R.array.recording_distance_interval_values, metricUnits);
|
|
||||||
configListPreference(R.string.max_recording_distance_key, R.array.max_recording_distance_values, metricUnits);
|
|
||||||
configListPreference(R.string.recording_gps_accuracy_key, R.array.recording_gps_accuracy_values, metricUnits);
|
|
||||||
configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits);
|
|
||||||
configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits);
|
|
||||||
|
|
||||||
final ListPreference statsRatePreferences = findPreference(getString(R.string.stats_rate_key));
|
ListPreference splitFrequency = findPreference(getString(R.string.split_frequency_key));
|
||||||
String[] options = getResources().getStringArray(metricUnits ? R.array.stats_rate_metric_options : R.array.stats_rate_imperial_options);
|
splitFrequency.setEntries(StringUtils.getFrequencyOptions(getActivity(), metricUnits));
|
||||||
statsRatePreferences.setEntries(options);
|
|
||||||
//TODO This is a hack!!! Need to manually updated the summary as otherwise it will only be updated after scrolling down and up again (bring the object out of view).
|
ListPreference minRecordingInterval = findPreference(getString(R.string.min_recording_interval_key));
|
||||||
//Check if this is still needed after upgraded PreferenceFragment.
|
minRecordingInterval.setEntries(PreferenceHelper.getMinRecordingIntervalEntries(getActivity()));
|
||||||
statsRatePreferences.setSummary(statsRatePreferences.getEntry());
|
|
||||||
|
ListPreference recordingDistanceInterval = findPreference(getString(R.string.recording_distance_interval_key));
|
||||||
|
recordingDistanceInterval.setEntries(PreferenceHelper.getRecordingDistanceIntervalEntries(getActivity(), metricUnits));
|
||||||
|
|
||||||
|
ListPreference maxRecordingDistance = findPreference(getString(R.string.max_recording_distance_key));
|
||||||
|
maxRecordingDistance.setEntries(PreferenceHelper.getMaxRecordingDistanceEntries(getActivity(), metricUnits));
|
||||||
|
|
||||||
|
ListPreference recordingGpsAccuracy = findPreference(getString(R.string.recording_gps_accuracy_key));
|
||||||
|
recordingGpsAccuracy.setEntries(PreferenceHelper.getRecordingGpsAccuracyEntries(getActivity(), metricUnits));
|
||||||
|
|
||||||
|
ListPreference autoresumeTrack = findPreference(getString(R.string.auto_resume_track_timeout_key));
|
||||||
|
autoresumeTrack.setEntries(PreferenceHelper.getAutoResumeTrackTimeoutEntries(getActivity()));
|
||||||
|
|
||||||
|
ListPreference statsRatePreferences = findPreference(getString(R.string.stats_rate_key));
|
||||||
|
String[] entries = getResources().getStringArray(metricUnits ? R.array.stats_rate_metric_options : R.array.stats_rate_imperial_options);
|
||||||
|
statsRatePreferences.setEntries(entries);
|
||||||
|
|
||||||
|
HackUtils.invalidatePreference(statsRatePreferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
package de.dennisguse.opentracks.util;
|
package de.dennisguse.opentracks.util;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothClass;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for dealing with bluetooth devices.
|
* Utilities for dealing with bluetooth devices.
|
||||||
@@ -30,29 +31,50 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class BluetoothUtils {
|
public class BluetoothUtils {
|
||||||
|
|
||||||
|
public static final UUID HEART_RATE_SERVICE_UUID = new UUID(0x180D00001000L, 0x800000805f9b34fbL);
|
||||||
|
|
||||||
private BluetoothUtils() {
|
private BluetoothUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static BluetoothAdapter getDefaultBluetoothAdapter(final String TAG) {
|
||||||
* Populates the device names and the device addresses with all the suitable
|
// If from the main application thread, return directly
|
||||||
* bluetooth devices.
|
if (Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
|
||||||
*
|
return BluetoothAdapter.getDefaultAdapter();
|
||||||
* @param bluetoothAdapter the bluetooth adapter
|
}
|
||||||
* @param deviceNames list of device names
|
|
||||||
* @param deviceAddresses list of device addresses
|
|
||||||
*/
|
|
||||||
public static void populateDeviceLists(BluetoothAdapter bluetoothAdapter, List<String> deviceNames, List<String> deviceAddresses) {
|
|
||||||
// Ensure the bluetooth adapter is not in discovery mode.
|
|
||||||
bluetoothAdapter.cancelDiscovery();
|
|
||||||
|
|
||||||
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
|
// Get the default adapter from the main application thread
|
||||||
for (BluetoothDevice device : pairedDevices) {
|
final ArrayList<BluetoothAdapter> adapters = new ArrayList<>(1);
|
||||||
BluetoothClass bluetoothClass = device.getBluetoothClass();
|
final Object mutex = new Object();
|
||||||
if (bluetoothClass != null && (bluetoothClass.getDeviceClass() & BluetoothClass.Device.HEALTH_PULSE_RATE) != 0) {
|
|
||||||
deviceAddresses.add(device.getAddress());
|
Handler handler = new Handler(Looper.getMainLooper());
|
||||||
deviceNames.add(device.getName());
|
handler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
adapters.add(BluetoothAdapter.getDefaultAdapter());
|
||||||
|
synchronized (mutex) {
|
||||||
|
mutex.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (adapters.isEmpty()) {
|
||||||
|
synchronized (mutex) {
|
||||||
|
try {
|
||||||
|
mutex.wait(UnitConversions.ONE_SECOND);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(TAG, "Interrupted while waiting for default bluetooth adapter", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adapters.get(0) == null) {
|
||||||
|
Log.w(TAG, "No bluetooth adapter found.");
|
||||||
|
}
|
||||||
|
return adapters.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasBluetooth(final String TAG) {
|
||||||
|
return BluetoothUtils.getDefaultBluetoothAdapter(TAG) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int parseHeartRate(BluetoothGattCharacteristic characteristic) {
|
public static int parseHeartRate(BluetoothGattCharacteristic characteristic) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package de.dennisguse.opentracks.util;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
public class HackUtils {
|
||||||
|
|
||||||
|
private HackUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a redraw of the summary of a preference if it was set programmatically.
|
||||||
|
* Need to trigger androidx.preference.preferences.notifyChanged() to trigger a redraw, but method is protected.
|
||||||
|
* This workaround also works when this preference has not changed, but it's entries (see R.string.stats_rate_key).
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public static void invalidatePreference(@NonNull Preference preference) {
|
||||||
|
boolean isEnabled = preference.isEnabled();
|
||||||
|
preference.setEnabled(!isEnabled);
|
||||||
|
preference.setEnabled(isEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,6 @@ public class IntentUtils {
|
|||||||
* @param context the context
|
* @param context the context
|
||||||
* @param trackIds the track ids
|
* @param trackIds the track ids
|
||||||
*/
|
*/
|
||||||
//TODO Share mulitple tracks in different files!
|
|
||||||
public static Intent newShareFileIntent(Context context, long[] trackIds) {
|
public static Intent newShareFileIntent(Context context, long[] trackIds) {
|
||||||
if (trackIds.length == 0) {
|
if (trackIds.length == 0) {
|
||||||
throw new RuntimeException("Need to share at least one track.");
|
throw new RuntimeException("Need to share at least one track.");
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import de.dennisguse.opentracks.content.Track;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
//TODO Cleanup: rename variables
|
|
||||||
public class LocationUtils {
|
public class LocationUtils {
|
||||||
|
|
||||||
private static final String TAG = LocationUtils.class.getSimpleName();
|
private static final String TAG = LocationUtils.class.getSimpleName();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
@@ -31,67 +32,8 @@ import de.dennisguse.opentracks.R;
|
|||||||
*/
|
*/
|
||||||
public class PreferencesUtils {
|
public class PreferencesUtils {
|
||||||
|
|
||||||
/*
|
|
||||||
* Preferences values.
|
|
||||||
* The defaults need to match the defaults in the xml files.
|
|
||||||
*/
|
|
||||||
public static final int AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT = 0;
|
|
||||||
|
|
||||||
// Values for auto_resume_track_timeout_key
|
|
||||||
public static final int AUTO_RESUME_TRACK_TIMEOUT_ALWAYS = -1;
|
|
||||||
public static final int AUTO_RESUME_TRACK_TIMEOUT_DEFAULT = 10;
|
|
||||||
public static final int AUTO_RESUME_TRACK_TIMEOUT_NEVER = 0;
|
|
||||||
|
|
||||||
public static final String BLUETOOTH_SENSOR_DEFAULT = "";
|
public static final String BLUETOOTH_SENSOR_DEFAULT = "";
|
||||||
|
|
||||||
public static final boolean CHART_SHOW_CADENCE_DEFAULT = true;
|
|
||||||
public static final boolean CHART_SHOW_ELEVATION_DEFAULT = true;
|
|
||||||
public static final boolean CHART_SHOW_HEART_RATE_DEFAULT = true;
|
|
||||||
public static final boolean CHART_SHOW_POWER_DEFAULT = true;
|
|
||||||
public static final boolean CHART_SHOW_SPEED_DEFAULT = true;
|
|
||||||
@Deprecated
|
|
||||||
//NOTE: is at the moment still used to determine if a track is currently recorded; better ask the service directly.
|
|
||||||
//NOTE: This is also used to recover from a reboot, but this data should not be exposed to the whole application.
|
|
||||||
public static final long RECORDING_TRACK_ID_DEFAULT = -1L;
|
|
||||||
|
|
||||||
public static final String DEFAULT_ACTIVITY_DEFAULT = "";
|
|
||||||
|
|
||||||
// Value for split_frequency_key and voice_frequency_key
|
|
||||||
public static final int FREQUENCY_OFF = 0;
|
|
||||||
|
|
||||||
public static final int MAX_RECORDING_DISTANCE_DEFAULT = 200;
|
|
||||||
|
|
||||||
// Values for min_recording_interval_key
|
|
||||||
public static final int MIN_RECORDING_INTERVAL_ADAPT_ACCURACY = -1;
|
|
||||||
public static final int MIN_RECORDING_INTERVAL_ADAPT_BATTERY_LIFE = -2;
|
|
||||||
public static final int MIN_RECORDING_INTERVAL_DEFAULT = 0;
|
|
||||||
|
|
||||||
public static final int RECORDING_DISTANCE_INTERVAL_DEFAULT = 10;
|
|
||||||
|
|
||||||
// Values for recording_gps_accuracy
|
|
||||||
public static final int RECORDING_GPS_ACCURACY_DEFAULT = 50;
|
|
||||||
public static final int RECORDING_GPS_ACCURACY_EXCELLENT = 10;
|
|
||||||
public static final int RECORDING_GPS_ACCURACY_POOR = 2000;
|
|
||||||
static final boolean STATS_SHOW_COORDINATE_DEFAULT = false;
|
|
||||||
public static final boolean RECORDING_TRACK_PAUSED_DEFAULT = true;
|
|
||||||
|
|
||||||
public static final int SPLIT_FREQUENCY_DEFAULT = 0;
|
|
||||||
static final boolean STATS_SHOW_ELEVATION_DEFAULT = false;
|
|
||||||
static final String TRACK_NAME_DEFAULT = "DATE_ISO_8601";
|
|
||||||
private static final String CHART_X_AXIS_DEFAULT = "DISTANCE";
|
|
||||||
public static final String STATS_UNITS_DEFAULT = "METRIC";
|
|
||||||
// Stats
|
|
||||||
private static final String STATS_RATE_DEFAULT = "SPEED";
|
|
||||||
|
|
||||||
public static final boolean SHOW_TRACKDETAIL_WHILE_RECORDING_ON_LOCKSCREEN = false;
|
|
||||||
|
|
||||||
// Track widget
|
|
||||||
public static final int TRACK_WIDGET_ITEM1_DEFAULT = 3; // moving time
|
|
||||||
public static final int TRACK_WIDGET_ITEM2_DEFAULT = 0; // distance
|
|
||||||
public static final int TRACK_WIDGET_ITEM3_DEFAULT = 1; // total time
|
|
||||||
public static final int TRACK_WIDGET_ITEM4_DEFAULT = 2; // average speed
|
|
||||||
public static final int VOICE_FREQUENCY_DEFAULT = 0;
|
|
||||||
|
|
||||||
private PreferencesUtils() {
|
private PreferencesUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,16 +41,60 @@ public class PreferencesUtils {
|
|||||||
return PreferenceManager.getDefaultSharedPreferences(context);
|
return PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
//NOTE: is at the moment still used to determine if a track is currently recorded; better ask the service directly.
|
||||||
|
//NOTE: This is also used to recover from a reboot, but this data should not be exposed to the whole application.
|
||||||
|
public static final long RECORDING_TRACK_ID_DEFAULT = -1L;
|
||||||
|
|
||||||
|
public static long getRecordingTrackId(Context context) {
|
||||||
|
return PreferencesUtils.getLong(context, R.string.recording_track_id_key, RECORDING_TRACK_ID_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public static final int AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT = 0;
|
||||||
|
|
||||||
|
public static int getAutoResumeTrackCurrentRetryDefault(Context context) {
|
||||||
|
return PreferencesUtils.getInt(context, R.string.auto_resume_track_current_retry_key, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetAutoResumeTrackCurrentRetryDefault(Context context) {
|
||||||
|
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void incrementAutoResumeTrackCurrentRetryDefault(Context context) {
|
||||||
|
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, getAutoResumeTrackCurrentRetryDefault(context) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDefaultActivity(Context context) {
|
||||||
|
return PreferencesUtils.getString(context, R.string.default_activity_key, context.getString(R.string.default_activity_default));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultActivity(Context context, String newDefaultActivity) {
|
||||||
|
PreferencesUtils.setString(context, R.string.default_activity_key, newDefaultActivity);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a preference key
|
* Gets a preference key
|
||||||
*
|
*
|
||||||
* @param context the context
|
* @param context the context
|
||||||
* @param keyId the key id
|
* @param keyId the key id
|
||||||
*/
|
*/
|
||||||
public static String getKey(Context context, int keyId) {
|
private static String getKey(Context context, int keyId) {
|
||||||
return context.getString(keyId);
|
return context.getString(keyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares if keyId and key belong to the same shared preference key.
|
||||||
|
*
|
||||||
|
* @param keyId The resource id of the key
|
||||||
|
* @param key
|
||||||
|
* @return true if key == null or key belongs to keyId
|
||||||
|
*/
|
||||||
|
public static boolean isKey(Context context, int keyId, String key) {
|
||||||
|
return key == null || key.equals(PreferencesUtils.getKey(context, keyId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a boolean preference value.
|
* Gets a boolean preference value.
|
||||||
*
|
*
|
||||||
@@ -180,9 +166,9 @@ public class PreferencesUtils {
|
|||||||
* @param context the context
|
* @param context the context
|
||||||
* @param keyId the key id
|
* @param keyId the key id
|
||||||
*/
|
*/
|
||||||
public static long getLong(Context context, int keyId) {
|
private static long getLong(Context context, int keyId, long defaultValue) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
||||||
return sharedPreferences.getLong(getKey(context, keyId), -1L);
|
return sharedPreferences.getLong(getKey(context, keyId), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,7 +217,8 @@ public class PreferencesUtils {
|
|||||||
* @param context the context
|
* @param context the context
|
||||||
*/
|
*/
|
||||||
public static boolean isMetricUnits(Context context) {
|
public static boolean isMetricUnits(Context context) {
|
||||||
return STATS_UNITS_DEFAULT.equals(getString(context, R.string.stats_units_key, STATS_UNITS_DEFAULT));
|
final String STATS_UNIT = context.getString(R.string.stats_units_default);
|
||||||
|
return STATS_UNIT.equals(getString(context, R.string.stats_units_key, STATS_UNIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -241,20 +228,134 @@ public class PreferencesUtils {
|
|||||||
* @param context the context
|
* @param context the context
|
||||||
*/
|
*/
|
||||||
public static boolean isReportSpeed(Context context) {
|
public static boolean isReportSpeed(Context context) {
|
||||||
|
final String STATS_RATE_DEFAULT = context.getString(R.string.stats_rate_default);
|
||||||
return STATS_RATE_DEFAULT.equals(getString(context, R.string.stats_rate_key, STATS_RATE_DEFAULT));
|
return STATS_RATE_DEFAULT.equals(getString(context, R.string.stats_rate_key, STATS_RATE_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static int getAutoResumeTrackTimeout(Context context) {
|
||||||
* Returns true if chart x axis is by distance, false if by time.
|
final int AUTO_RESUME_TRACK_TIMEOUT = Integer.parseInt(context.getResources().getString(R.string.auto_resume_track_timeout_default));
|
||||||
*
|
return PreferencesUtils.getInt(context, R.string.auto_resume_track_timeout_key, AUTO_RESUME_TRACK_TIMEOUT);
|
||||||
* @param context the context
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
public static boolean isRecordingTrackPaused(Context context) {
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, isRecordingTrackPausedDefault(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRecordingTrackPausedDefault(Context context) {
|
||||||
|
return context.getResources().getBoolean(R.bool.recording_track_paused_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void defaultRecordingTrackPaused(Context context) {
|
||||||
|
final boolean RECORDING_TRACK_PAUSED = context.getResources().getBoolean(R.bool.recording_track_paused_default);
|
||||||
|
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, RECORDING_TRACK_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBluetoothHeartRateSensorAddressDefault(Context context) {
|
||||||
|
return PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(getBluetoothHeartRateSensorAddress(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBluetoothHeartRateSensorAddress(Context context) {
|
||||||
|
return PreferencesUtils.getString(context, R.string.settings_sensor_bluetooth_heart_rate_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isChartByDistance(Context context) {
|
public static boolean isChartByDistance(Context context) {
|
||||||
|
final String CHART_X_AXIS_DEFAULT = context.getString(R.string.chart_x_axis_default);
|
||||||
return CHART_X_AXIS_DEFAULT.equals(getString(context, R.string.chart_x_axis_key, CHART_X_AXIS_DEFAULT));
|
return CHART_X_AXIS_DEFAULT.equals(getString(context, R.string.chart_x_axis_key, CHART_X_AXIS_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean shouldChartShowCadence(Context context) {
|
||||||
|
final boolean CHART_SHOW_CADENCE = context.getResources().getBoolean(R.bool.chart_show_cadence_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.chart_show_cadence_key, CHART_SHOW_CADENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldChartShowElevation(Context context) {
|
||||||
|
final boolean CHART_SHOW_ELEVATION = context.getResources().getBoolean(R.bool.chart_show_elevation_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.chart_show_elevation_key, CHART_SHOW_ELEVATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldChartShowHeartRate(Context context) {
|
||||||
|
final boolean CHART_SHOW_HEARTRATE = context.getResources().getBoolean(R.bool.chart_show_heart_rate_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.chart_show_heart_rate_key, CHART_SHOW_HEARTRATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldChartShowPower(Context context) {
|
||||||
|
final boolean CHART_SHOW_POWER = context.getResources().getBoolean(R.bool.chart_show_power_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.chart_show_power_key, CHART_SHOW_POWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldChartShowSpeed(Context context) {
|
||||||
|
final boolean CHART_SHOW_SPEED = context.getResources().getBoolean(R.bool.chart_show_speed_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.chart_show_speed_key, CHART_SHOW_SPEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldShowStatsOnLockscreen(Context context) {
|
||||||
|
final boolean STATS_SHOW_ON_LOCKSCREEN_DEFAULT = context.getResources().getBoolean(R.bool.stats_show_on_lockscreen_while_recording_default);
|
||||||
|
return getBoolean(context, R.string.stats_show_on_lockscreen_while_recording_key, STATS_SHOW_ON_LOCKSCREEN_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isShowStatsGradeElevation(Context context) {
|
||||||
|
final boolean STATS_SHOW_GRADE_ELEVATION = context.getResources().getBoolean(R.bool.stats_show_grade_elevation_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.stats_show_grade_elevation_key, STATS_SHOW_GRADE_ELEVATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isStatsShowCoordinate(Context context) {
|
||||||
|
final boolean STATS_SHOW_COORDINATE = context.getResources().getBoolean(R.bool.stats_show_coordinate_default);
|
||||||
|
return PreferencesUtils.getBoolean(context, R.string.stats_show_coordinate_key, STATS_SHOW_COORDINATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getVoiceFrequency(Context context) {
|
||||||
|
final int VOICE_FREQUENCY_DEFAULT = Integer.parseInt(context.getResources().getString(R.string.voice_frequency_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.voice_frequency_key, VOICE_FREQUENCY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSplitFrequency(Context context) {
|
||||||
|
final int SPLIT_FREQUENCY_DEFAULT = Integer.parseInt(context.getResources().getString(R.string.split_frequency_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.split_frequency_key, SPLIT_FREQUENCY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRecordingDistanceInterval(Context context) {
|
||||||
|
final int RECORDING_DISTANCE_INTERVAL = Integer.parseInt(context.getResources().getString(R.string.recording_distance_interval_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.recording_distance_interval_key, getRecordingDistanceIntervalDefault(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRecordingDistanceIntervalDefault(Context context) {
|
||||||
|
return Integer.parseInt(context.getResources().getString(R.string.recording_distance_interval_default));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMaxRecordingDistance(Context context) {
|
||||||
|
final int MAX_RECORDING_DISTANCE = Integer.parseInt(context.getResources().getString(R.string.max_recording_distance_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.max_recording_distance_key, MAX_RECORDING_DISTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMinRecordingInterval(Context context) {
|
||||||
|
final int MIN_RECORDING_INTERVAL = Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.min_recording_interval_key, MIN_RECORDING_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMinRecordingIntervalAdaptAccuracy(Context context) {
|
||||||
|
return Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_adapt_accuracy));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMinRecordingIntervalAdaptBatteryLife(Context context) {
|
||||||
|
return Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_adapt_battery_life));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMinRecordingIntervalDefault(Context context) {
|
||||||
|
return Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static int getRecordingGPSAccuracy(Context context) {
|
||||||
|
final int RECORDING_GPS_ACCURACY = Integer.parseInt(context.getResources().getString(R.string.recording_gps_accuracy_default));
|
||||||
|
return PreferencesUtils.getInt(context, R.string.recording_gps_accuracy_key, RECORDING_GPS_ACCURACY);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isRecording(Context context) {
|
public static boolean isRecording(Context context) {
|
||||||
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
|
long recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
||||||
return recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
return recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +364,10 @@ public class PreferencesUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void resetPreferences(Context context, boolean readAgain) {
|
public static void resetPreferences(Context context, boolean readAgain) {
|
||||||
|
if (readAgain) {
|
||||||
|
// We want to really clear settings now.
|
||||||
|
getSharedPreferences(context).edit().clear().commit();
|
||||||
|
}
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.settings, readAgain);
|
PreferenceManager.setDefaultValues(context, R.xml.settings, readAgain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class StatsUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set elevation
|
// Set elevation
|
||||||
boolean showGradeElevation = PreferencesUtils.getBoolean(activity, R.string.stats_show_grade_elevation_key, PreferencesUtils.STATS_SHOW_ELEVATION_DEFAULT) && isRecording;
|
boolean showGradeElevation = isRecording && PreferencesUtils.isShowStatsGradeElevation(activity);
|
||||||
View elevationContainer = activity.findViewById(R.id.stats_elevation);
|
View elevationContainer = activity.findViewById(R.id.stats_elevation);
|
||||||
elevationContainer.setVisibility(showGradeElevation ? View.VISIBLE : View.GONE);
|
elevationContainer.setVisibility(showGradeElevation ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public class StatsUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set coordinate
|
// Set coordinate
|
||||||
boolean showCoordinate = isRecording && PreferencesUtils.getBoolean(activity, R.string.stats_show_coordinate_key, PreferencesUtils.STATS_SHOW_COORDINATE_DEFAULT);
|
boolean showCoordinate = isRecording && PreferencesUtils.isStatsShowCoordinate(activity);
|
||||||
|
|
||||||
View coordinateSeparator = activity.findViewById(R.id.stats_coordinate_separator);
|
View coordinateSeparator = activity.findViewById(R.id.stats_coordinate_separator);
|
||||||
coordinateSeparator.setVisibility(showCoordinate ? View.VISIBLE : View.GONE);
|
coordinateSeparator.setVisibility(showCoordinate ? View.VISIBLE : View.GONE);
|
||||||
@@ -108,7 +108,7 @@ public class StatsUtils {
|
|||||||
public static void setSensorData(Activity activity, SensorDataSet sensorDataSet, boolean isRecording) {
|
public static void setSensorData(Activity activity, SensorDataSet sensorDataSet, boolean isRecording) {
|
||||||
// heart rate
|
// heart rate
|
||||||
int isVisible = View.VISIBLE;
|
int isVisible = View.VISIBLE;
|
||||||
if (!isRecording || PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(PreferencesUtils.getString(activity, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT))) {
|
if (!isRecording || PreferencesUtils.isBluetoothHeartRateSensorAddressDefault(activity)) {
|
||||||
isVisible = View.INVISIBLE;
|
isVisible = View.INVISIBLE;
|
||||||
}
|
}
|
||||||
activity.findViewById(R.id.stats_sensor_container).setVisibility(isVisible);
|
activity.findViewById(R.id.stats_sensor_container).setVisibility(isVisible);
|
||||||
@@ -125,11 +125,18 @@ public class StatsUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heartRateValue.setText(heartRate);
|
setBluetoothHeartRateSensorName(activity, sensor, isRecording);
|
||||||
heartRateSensor.setText(sensor);
|
heartRateSensor.setText(sensor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBluetoothHeartRateSensorName(Activity activity, String sensorName, boolean isRecording) {
|
||||||
|
if (isRecording) {
|
||||||
|
TextView heartRateSensor = activity.findViewById(R.id.stats_sensor_heart_rate_sensor_value);
|
||||||
|
heartRateSensor.setText(sensorName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the total time value.
|
* Sets the total time value.
|
||||||
*
|
*
|
||||||
@@ -151,6 +158,7 @@ public class StatsUtils {
|
|||||||
public static void setTripStatisticsValues(Activity activity, TripStatistics tripStatistics, String trackIconValue) {
|
public static void setTripStatisticsValues(Activity activity, TripStatistics tripStatistics, String trackIconValue) {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(activity);
|
boolean metricUnits = PreferencesUtils.isMetricUnits(activity);
|
||||||
boolean reportSpeed = PreferencesUtils.isReportSpeed(activity);
|
boolean reportSpeed = PreferencesUtils.isReportSpeed(activity);
|
||||||
|
boolean isRecording = PreferencesUtils.isRecording(activity);
|
||||||
|
|
||||||
// Set total distance
|
// Set total distance
|
||||||
{
|
{
|
||||||
@@ -173,6 +181,7 @@ public class StatsUtils {
|
|||||||
if (trackIconValue != null) {
|
if (trackIconValue != null) {
|
||||||
TrackIconUtils.setIconSpinner(spinner, trackIconValue);
|
TrackIconUtils.setIconSpinner(spinner, trackIconValue);
|
||||||
}
|
}
|
||||||
|
spinner.setEnabled(isRecording);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set time
|
// Set time
|
||||||
@@ -241,7 +250,7 @@ public class StatsUtils {
|
|||||||
|
|
||||||
// Set elevation
|
// Set elevation
|
||||||
{
|
{
|
||||||
boolean showElevation = PreferencesUtils.getBoolean(activity, R.string.stats_show_grade_elevation_key, PreferencesUtils.STATS_SHOW_ELEVATION_DEFAULT);
|
boolean showElevation = PreferencesUtils.isShowStatsGradeElevation(activity);
|
||||||
View gradeElevationSeparator = activity.findViewById(R.id.stats_elevation_separator);
|
View gradeElevationSeparator = activity.findViewById(R.id.stats_elevation_separator);
|
||||||
gradeElevationSeparator.setVisibility(showElevation ? View.VISIBLE : View.GONE);
|
gradeElevationSeparator.setVisibility(showElevation ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ public class StringUtils {
|
|||||||
String[] options = new String[values.length];
|
String[] options = new String[values.length];
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
int value = Integer.parseInt(values[i]);
|
int value = Integer.parseInt(values[i]);
|
||||||
if (value == PreferencesUtils.FREQUENCY_OFF) {
|
if (context.getString(R.string.frequency_off).equals(values[i])) {
|
||||||
options[i] = context.getString(R.string.value_off);
|
options[i] = context.getString(R.string.value_off);
|
||||||
} else if (value < 0) {
|
} else if (value < 0) {
|
||||||
options[i] = context.getString(metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile, Math.abs(value));
|
options[i] = context.getString(metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile, Math.abs(value));
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class TrackNameUtils {
|
|||||||
* @param startTime the track start time
|
* @param startTime the track start time
|
||||||
*/
|
*/
|
||||||
public static String getTrackName(Context context, long trackId, long startTime) {
|
public static String getTrackName(Context context, long trackId, long startTime) {
|
||||||
String trackName = PreferencesUtils.getString(context, R.string.track_name_key, PreferencesUtils.TRACK_NAME_DEFAULT);
|
String trackName = PreferencesUtils.getString(context, R.string.track_name_key, context.getString(R.string.track_name_default));
|
||||||
|
|
||||||
if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_local_value))) {
|
if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_local_value))) {
|
||||||
return StringUtils.formatDateTime(context, startTime);
|
return StringUtils.formatDateTime(context, startTime);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ limitations under the License.
|
|||||||
android:id="@+id/track_detail_markers"
|
android:id="@+id/track_detail_markers"
|
||||||
android:icon="@drawable/ic_marker_show_24dp"
|
android:icon="@drawable/ic_marker_show_24dp"
|
||||||
android:orderInCategory="5"
|
android:orderInCategory="5"
|
||||||
android:showAsAction="ifRoom"
|
app:showAsAction="ifRoom"
|
||||||
android:title="@string/menu_markers" />
|
android:title="@string/menu_markers" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/track_detail_edit"
|
android:id="@+id/track_detail_edit"
|
||||||
@@ -54,15 +54,6 @@ limitations under the License.
|
|||||||
android:icon="@drawable/ic_delete_forever_24dp"
|
android:icon="@drawable/ic_delete_forever_24dp"
|
||||||
android:orderInCategory="10"
|
android:orderInCategory="10"
|
||||||
android:title="@string/menu_delete" />
|
android:title="@string/menu_delete" />
|
||||||
<item
|
|
||||||
android:id="@+id/track_detail_voice_frequency"
|
|
||||||
android:orderInCategory="11"
|
|
||||||
android:title="@string/menu_voice_frequency" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/track_detail_split_frequency"
|
|
||||||
android:icon="@drawable/ic_split_frequency_24dp"
|
|
||||||
android:orderInCategory="12"
|
|
||||||
android:title="@string/menu_split_frequency" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/track_detail_settings"
|
android:id="@+id/track_detail_settings"
|
||||||
android:icon="@drawable/ic_settings_24dp"
|
android:icon="@drawable/ic_settings_24dp"
|
||||||
|
|||||||
@@ -15,20 +15,68 @@ limitations under the License.
|
|||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_web_url" translatable="false">https://github.com/dennisguse/opentracks</string>
|
<string name="app_web_url" translatable="false">https://github.com/dennisguse/opentracks</string>
|
||||||
<string name="chart_x_axis_distance" translatable="false">DISTANCE</string>
|
|
||||||
<string name="chart_x_axis_time" translatable="false">TIME</string>
|
|
||||||
<!-- List here all used libraries (will be shown in the about activity -->
|
<!-- List here all used libraries (will be shown in the about activity -->
|
||||||
<string name="third_party_libraries" translatable="false"><a href="https://developer.android.com/topic/libraries/support-library/">Google\'s androidX support</a> (Apache License, Version 2.0)</string>
|
<string name="third_party_libraries" translatable="false"><a href="https://developer.android.com/topic/libraries/support-library/">Google\'s androidX support</a> (Apache License, Version 2.0)</string>
|
||||||
|
|
||||||
<string name="marker_statistics_icon_url" translatable="false">http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png</string>
|
<string name="marker_statistics_icon_url" translatable="false">http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png</string>
|
||||||
<string name="marker_waypoint_icon_url" translatable="false">http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png</string>
|
<string name="marker_waypoint_icon_url" translatable="false">http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png</string>
|
||||||
<string name="sensor_type_value_none" translatable="false">NONE</string>
|
|
||||||
<string name="sensor_unit_beats_per_minute" translatable="false">BPM</string>
|
<string name="sensor_unit_beats_per_minute" translatable="false">BPM</string>
|
||||||
<string name="settings_recording_track_name_date_iso_8601_value" translatable="false">DATE_ISO_8601</string>
|
|
||||||
<string name="settings_recording_track_name_date_local_value" translatable="false">DATE_LOCAL</string>
|
|
||||||
<string name="settings_recording_track_name_number_value" translatable="false">NUMBER</string>
|
|
||||||
<string name="stats_rate_pace" translatable="false">PACE</string>
|
|
||||||
<string name="stats_rate_speed" translatable="false">SPEED</string>
|
|
||||||
<string name="stats_units_imperial" translatable="false">IMPERIAL</string>
|
|
||||||
<string name="stats_units_metric" translatable="false">METRIC</string>
|
|
||||||
<string name="value_unknown" translatable="false">-</string>
|
<string name="value_unknown" translatable="false">-</string>
|
||||||
|
|
||||||
|
<string-array name="waypoint_types">
|
||||||
|
<item>@string/waypoint_type_atm</item>
|
||||||
|
<item>@string/waypoint_type_bank</item>
|
||||||
|
<item>@string/waypoint_type_bar</item>
|
||||||
|
<item>@string/waypoint_type_barbecue</item>
|
||||||
|
<item>@string/waypoint_type_building</item>
|
||||||
|
<item>@string/waypoint_type_bus_stop</item>
|
||||||
|
<item>@string/waypoint_type_cafe</item>
|
||||||
|
<item>@string/waypoint_type_campfire</item>
|
||||||
|
<item>@string/waypoint_type_campground</item>
|
||||||
|
<item>@string/waypoint_type_church</item>
|
||||||
|
<item>@string/waypoint_type_coffee_house</item>
|
||||||
|
<item>@string/waypoint_type_convenience_store</item>
|
||||||
|
<item>@string/waypoint_type_drinking_water</item>
|
||||||
|
<item>@string/waypoint_type_falling_rocks</item>
|
||||||
|
<item>@string/waypoint_type_ferry</item>
|
||||||
|
<item>@string/waypoint_type_fire_place</item>
|
||||||
|
<item>@string/waypoint_type_fire_station</item>
|
||||||
|
<item>@string/waypoint_type_fishing</item>
|
||||||
|
<item>@string/waypoint_type_gas_station</item>
|
||||||
|
<item>@string/waypoint_type_golf_course</item>
|
||||||
|
<item>@string/waypoint_type_grocery_store</item>
|
||||||
|
<item>@string/waypoint_type_hair_dresser</item>
|
||||||
|
<item>@string/waypoint_type_harbor</item>
|
||||||
|
<item>@string/waypoint_type_hiking_path</item>
|
||||||
|
<item>@string/waypoint_type_hotel</item>
|
||||||
|
<item>@string/waypoint_type_house</item>
|
||||||
|
<item>@string/waypoint_type_information</item>
|
||||||
|
<item>@string/waypoint_type_intersection</item>
|
||||||
|
<item>@string/waypoint_type_mail_box</item>
|
||||||
|
<item>@string/waypoint_type_market</item>
|
||||||
|
<item>@string/waypoint_type_meeting_point</item>
|
||||||
|
<item>@string/waypoint_type_opera</item>
|
||||||
|
<item>@string/waypoint_type_parking</item>
|
||||||
|
<item>@string/waypoint_type_police_station</item>
|
||||||
|
<item>@string/waypoint_type_post_office</item>
|
||||||
|
<item>@string/waypoint_type_pothole</item>
|
||||||
|
<item>@string/waypoint_type_railway_crossing</item>
|
||||||
|
<item>@string/waypoint_type_restaurant</item>
|
||||||
|
<item>@string/waypoint_type_shopping</item>
|
||||||
|
<item>@string/waypoint_type_sight</item>
|
||||||
|
<item>@string/waypoint_type_store</item>
|
||||||
|
<item>@string/waypoint_type_swimming_pool</item>
|
||||||
|
<item>@string/waypoint_type_telephone</item>
|
||||||
|
<item>@string/waypoint_type_theater</item>
|
||||||
|
<item>@string/waypoint_type_toilet</item>
|
||||||
|
<item>@string/waypoint_type_tourist_information</item>
|
||||||
|
<item>@string/waypoint_type_tree</item>
|
||||||
|
<item>@string/waypoint_type_tunnel</item>
|
||||||
|
<item>@string/waypoint_type_waterfall</item>
|
||||||
|
<item>@string/waypoint_type_water_fountain</item>
|
||||||
|
<item>@string/waypoint_type_waypoint</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?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>
|
|
||||||
<!-- Keys for persisted preferences. Sorted alphabetically. DO NOT TRANSLATE. -->
|
|
||||||
<string name="auto_resume_track_timeout_key" translatable="false">autoResumeTrackTimeout</string>
|
|
||||||
<string name="chart_show_cadence_key" translatable="false">chartShowCadence</string>
|
|
||||||
<string name="chart_show_elevation_key" translatable="false">chartShowElevation</string>
|
|
||||||
<string name="chart_show_heart_rate_key" translatable="false">chartShowHeartRate</string>
|
|
||||||
<string name="chart_show_power_key" translatable="false">chartShowPower</string>
|
|
||||||
<string name="chart_show_speed_key" translatable="false">chartShowSpeed</string>
|
|
||||||
<string name="chart_x_axis_key" translatable="false">chartXAxis</string>
|
|
||||||
<string name="default_activity_key" translatable="false">defaultActivity</string>
|
|
||||||
<string name="max_recording_distance_key" translatable="false">maxRecordingDistance</string>
|
|
||||||
<string name="min_recording_interval_key" translatable="false">minRecordingInterval</string>
|
|
||||||
<string name="recording_distance_interval_key" translatable="false">recordingDistanceInterval</string>
|
|
||||||
<string name="recording_gps_accuracy_key" translatable="false">recordingGpsAccuracy</string>
|
|
||||||
<string name="split_frequency_key" translatable="false">splitFrequency</string>
|
|
||||||
|
|
||||||
<string name="stats_rate_key" translatable="false">statsRate</string>
|
|
||||||
<string name="stats_show_coordinate_key" translatable="false">statsShowCoordinate</string>
|
|
||||||
<string name="stats_show_grade_elevation_key" translatable="false">statsShowGradeElevation</string>
|
|
||||||
<string name="stats_units_key" translatable="false">statsUnits</string>
|
|
||||||
<string name="trackdetail_show_on_lockscreen_while_recording_key" translatable="false">trackdetail_show_on_lockscreen_while_recording</string>
|
|
||||||
<string name="track_name_key" translatable="false">trackName</string>
|
|
||||||
<string name="voice_frequency_key" translatable="false">voiceFrequency</string>
|
|
||||||
<!-- Keys for persistend preferences. But they should not get backed up or restored. -->
|
|
||||||
<string name="auto_resume_track_current_retry_key" translatable="false">autoResumeTrackCurrentRetry</string>
|
|
||||||
<string name="bluetooth_sensor_key" translatable="false">bluetoothSensor</string>
|
|
||||||
<string name="recording_track_id_key" translatable="false">recordingTrackId</string>
|
|
||||||
<string name="recording_track_paused_key" translatable="false">recordingTrackPaused</string>
|
|
||||||
<!-- Keys for non-persisted preferences. Sorted alphabetically. DO NOT TRANSLATE. -->
|
|
||||||
<string name="settings_recording_key" translatable="false">settingsRecording</string>
|
|
||||||
<string name="settings_reset_key" translatable="false">settingsReset</string>
|
|
||||||
<string name="settings_sensor_bluetooth_pairing_key" translatable="false">settingsSensorBluetoothPairing</string>
|
|
||||||
<string name="settings_stats_key" translatable="false">settingsStats</string>
|
|
||||||
</resources>
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?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>
|
||||||
|
<!-- Keys for persisted preferences that are used by internally. -->
|
||||||
|
<!--But they should not get backed up or restored.-->
|
||||||
|
<string name="auto_resume_track_current_retry_key" translatable="false">autoResumeTrackCurrentRetry</string>
|
||||||
|
<string name="recording_track_id_key" translatable="false">recordingTrackId</string>
|
||||||
|
|
||||||
|
<string name="recording_track_paused_key" translatable="false">recordingTrackPaused</string>
|
||||||
|
<bool name="recording_track_paused_default" translatable="false">true</bool>
|
||||||
|
</resources>
|
||||||
+116
-102
@@ -1,21 +1,40 @@
|
|||||||
<?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>
|
<resources>
|
||||||
<!-- Do not translate any arrays in this file. -->
|
<!-- Do not translate anything in this file directly. -->
|
||||||
|
<string name="chart_show_cadence_key" translatable="false">chartShowCadence</string>
|
||||||
|
<bool name="chart_show_cadence_default" translatable="false">true</bool>
|
||||||
|
|
||||||
|
<string name="chart_show_elevation_key" translatable="false">chartShowElevation</string>
|
||||||
|
<bool name="chart_show_elevation_default" translatable="false">true</bool>
|
||||||
|
|
||||||
|
<string name="chart_show_heart_rate_key" translatable="false">chartShowHeartRate</string>
|
||||||
|
<bool name="chart_show_heart_rate_default" translatable="false">true</bool>
|
||||||
|
|
||||||
|
<string name="chart_show_power_key" translatable="false">chartShowPower</string>
|
||||||
|
<bool name="chart_show_power_default" translatable="false">true</bool>
|
||||||
|
|
||||||
|
<string name="chart_show_speed_key" translatable="false">chartShowSpeed</string>
|
||||||
|
<bool name="chart_show_speed_default" translatable="false">true</bool>
|
||||||
|
|
||||||
|
<string name="stats_show_coordinate_key" translatable="false">statsShowCoordinate</string>
|
||||||
|
<bool name="stats_show_coordinate_default" translatable="false">false</bool>
|
||||||
|
|
||||||
|
<string name="stats_show_grade_elevation_key" translatable="false">statsShowGradeElevation</string>
|
||||||
|
<bool name="stats_show_grade_elevation_default" translatable="false">false</bool>
|
||||||
|
|
||||||
|
<string name="stats_show_on_lockscreen_while_recording_key" translatable="false">trackdetail_show_on_lockscreen_while_recording</string>
|
||||||
|
<bool name="stats_show_on_lockscreen_while_recording_default" translatable="false">false</bool>
|
||||||
|
|
||||||
|
<string name="settings_reset_key" translatable="false">settingsReset</string>
|
||||||
|
|
||||||
|
<string name="settings_sensor_bluetooth_heart_rate_key" translatable="false">bluetoothSensor</string>
|
||||||
|
<string name="sensor_type_value_none" translatable="false">NONE</string>
|
||||||
|
|
||||||
|
<string name="default_activity_key" translatable="false">defaultActivity</string>
|
||||||
|
<string name="default_activity_default" translatable="false">@string/activity_type_unknown</string>
|
||||||
<string-array name="activity_types">
|
<string-array name="activity_types">
|
||||||
|
<item>@string/default_activity_default</item>
|
||||||
|
|
||||||
<item>@string/activity_type_airplane</item>
|
<item>@string/activity_type_airplane</item>
|
||||||
<item>@string/activity_type_atv</item>
|
<item>@string/activity_type_atv</item>
|
||||||
<item>@string/activity_type_biking</item>
|
<item>@string/activity_type_biking</item>
|
||||||
@@ -77,29 +96,44 @@ limitations under the License.
|
|||||||
<item>@string/activity_type_trail_running</item>
|
<item>@string/activity_type_trail_running</item>
|
||||||
<item>@string/activity_type_train</item>
|
<item>@string/activity_type_train</item>
|
||||||
<item>@string/activity_type_ultimate_frisbee</item>
|
<item>@string/activity_type_ultimate_frisbee</item>
|
||||||
<item>@string/activity_type_unknown</item>
|
|
||||||
<item>@string/activity_type_wakeboarding</item>
|
<item>@string/activity_type_wakeboarding</item>
|
||||||
<item>@string/activity_type_walking</item>
|
<item>@string/activity_type_walking</item>
|
||||||
<item>@string/activity_type_water_skiing</item>
|
<item>@string/activity_type_water_skiing</item>
|
||||||
<item>@string/activity_type_wind_surfing</item>
|
<item>@string/activity_type_wind_surfing</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="auto_resume_track_timeout_key" translatable="false">autoResumeTrackTimeout</string>
|
||||||
|
<string name="auto_resume_track_timeout_default" translatable="false">10</string>
|
||||||
|
<string name="auto_resume_track_timeout_always" translatable="false">-1</string>
|
||||||
|
<string name="auto_resume_track_timeout_never" translatable="false">0</string>
|
||||||
<string-array name="auto_resume_track_timeout_values">
|
<string-array name="auto_resume_track_timeout_values">
|
||||||
<item>0</item>
|
<item>@string/auto_resume_track_timeout_never</item>
|
||||||
<item>5</item>
|
<item>5</item>
|
||||||
<item>10</item>
|
<item>@string/auto_resume_track_timeout_default</item>
|
||||||
<item>15</item>
|
<item>15</item>
|
||||||
<item>-1</item>
|
<item>@string/auto_resume_track_timeout_always</item>
|
||||||
</string-array>
|
|
||||||
<string-array name="chart_x_axis_options">
|
|
||||||
<item>@string/settings_chart_by_distance</item>
|
|
||||||
<item>@string/settings_chart_by_time</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="chart_x_axis_key" translatable="false">chartXAxis</string>
|
||||||
|
<string name="chart_x_axis_default" translatable="false">@string/chart_x_axis_distance</string>
|
||||||
<string-array name="chart_x_axis_values">
|
<string-array name="chart_x_axis_values">
|
||||||
<item>@string/chart_x_axis_distance</item>
|
<item>@string/chart_x_axis_distance</item>
|
||||||
<item>@string/chart_x_axis_time</item>
|
<item>@string/chart_x_axis_time</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string name="chart_x_axis_time" translatable="false">TIME</string>
|
||||||
|
<string name="chart_x_axis_distance" translatable="false">DISTANCE</string>
|
||||||
|
<string-array name="chart_x_axis_options">
|
||||||
|
<item>@string/settings_chart_by_distance</item>
|
||||||
|
<item>@string/settings_chart_by_time</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string name="split_frequency_key" translatable="false">splitFrequency</string>
|
||||||
|
<string name="split_frequency_default" translatable="false">@string/frequency_off</string>
|
||||||
|
<string name="voice_frequency_key" translatable="false">voiceFrequency</string>
|
||||||
|
<string name="voice_frequency_default" translatable="false">@string/frequency_off</string>
|
||||||
|
<string name="frequency_off" translatable="false">0</string>
|
||||||
<string-array name="frequency_values">
|
<string-array name="frequency_values">
|
||||||
<item>0</item>
|
<item>@string/frequency_off</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
<item>2</item>
|
<item>2</item>
|
||||||
<item>5</item>
|
<item>5</item>
|
||||||
@@ -114,18 +148,38 @@ limitations under the License.
|
|||||||
<item>-50</item>
|
<item>-50</item>
|
||||||
<item>-100</item>
|
<item>-100</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="recording_distance_interval_key" translatable="false">recordingDistanceInterval</string>
|
||||||
|
<string name="recording_distance_interval_default" translatable="false">10</string>
|
||||||
|
<string-array name="recording_distance_interval_values">
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>@string/recording_distance_interval_default</item>
|
||||||
|
<item>20</item>
|
||||||
|
<item>50</item>
|
||||||
|
<item>100</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string name="max_recording_distance_key" translatable="false">maxRecordingDistance</string>
|
||||||
|
<string name="max_recording_distance_default" translatable="false">200</string>
|
||||||
<string-array name="max_recording_distance_values">
|
<string-array name="max_recording_distance_values">
|
||||||
<item>50</item>
|
<item>50</item>
|
||||||
<item>100</item>
|
<item>100</item>
|
||||||
<item>200</item>
|
<item>@string/max_recording_distance_default</item>
|
||||||
<item>500</item>
|
<item>500</item>
|
||||||
<item>1000</item>
|
<item>1000</item>
|
||||||
<item>5000</item>
|
<item>5000</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="min_recording_interval_key" translatable="false">minRecordingInterval</string>
|
||||||
|
<string name="min_recording_interval_default" translatable="false">0</string>
|
||||||
|
<string name="min_recording_interval_adapt_accuracy" translatable="false">-1</string>
|
||||||
|
<string name="min_recording_interval_adapt_battery_life" translatable="false">-2</string>
|
||||||
<string-array name="min_recording_interval_values">
|
<string-array name="min_recording_interval_values">
|
||||||
<item>-2</item>
|
<item>@string/min_recording_interval_adapt_battery_life</item>
|
||||||
<item>-1</item>
|
<item>@string/min_recording_interval_adapt_accuracy</item>
|
||||||
<item>0</item>
|
<item>@string/min_recording_interval_default</item>
|
||||||
<item>2</item>
|
<item>2</item>
|
||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
@@ -140,26 +194,25 @@ limitations under the License.
|
|||||||
<item>900</item>
|
<item>900</item>
|
||||||
<item>1800</item>
|
<item>1800</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="recording_distance_interval_values">
|
|
||||||
<item>1</item>
|
<string name="recording_gps_accuracy_key" translatable="false">recordingGpsAccuracy</string>
|
||||||
<item>2</item>
|
<string name="recording_gps_accuracy_default" translatable="false">50</string>
|
||||||
<item>5</item>
|
<string name="recording_gps_accuracy_excellent" translatable="false">10</string>
|
||||||
<item>10</item>
|
<string name="recording_gps_accuracy_poor" translatable="false">2000</string>
|
||||||
<item>20</item>
|
|
||||||
<item>50</item>
|
|
||||||
<item>100</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="recording_gps_accuracy_values">
|
<string-array name="recording_gps_accuracy_values">
|
||||||
<item>10</item>
|
<item>@string/recording_gps_accuracy_excellent</item>
|
||||||
<item>20</item>
|
<item>20</item>
|
||||||
<item>30</item>
|
<item>30</item>
|
||||||
<item>50</item>
|
<item>@string/recording_gps_accuracy_default</item>
|
||||||
<item>100</item>
|
<item>100</item>
|
||||||
<item>200</item>
|
<item>200</item>
|
||||||
<item>500</item>
|
<item>500</item>
|
||||||
<item>1000</item>
|
<item>1000</item>
|
||||||
<item>2000</item>
|
<item>@string/recording_gps_accuracy_poor</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="stats_rate_key" translatable="false">statsRate</string>
|
||||||
|
<string name="stats_rate_default" translatable="false">@string/stats_rate_speed</string>
|
||||||
<string-array name="stats_rate_imperial_options">
|
<string-array name="stats_rate_imperial_options">
|
||||||
<item>@string/description_speed_imperial</item>
|
<item>@string/description_speed_imperial</item>
|
||||||
<item>@string/description_pace_imperial</item>
|
<item>@string/description_pace_imperial</item>
|
||||||
@@ -168,79 +221,40 @@ limitations under the License.
|
|||||||
<item>@string/description_speed_metric</item>
|
<item>@string/description_speed_metric</item>
|
||||||
<item>@string/description_pace_metric</item>
|
<item>@string/description_pace_metric</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="stats_rate_pace" translatable="false">PACE</string>
|
||||||
|
<string name="stats_rate_speed" translatable="false">SPEED</string>
|
||||||
<string-array name="stats_rate_values">
|
<string-array name="stats_rate_values">
|
||||||
<item>@string/stats_rate_speed</item>
|
<item>@string/stats_rate_speed</item>
|
||||||
<item>@string/stats_rate_pace</item>
|
<item>@string/stats_rate_pace</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="stats_units_key" translatable="false">statsUnits</string>
|
||||||
|
<string name="stats_units_default" translatable="false">@string/stats_units_metric</string>
|
||||||
|
<string-array name="stats_units_values">
|
||||||
|
<item>@string/stats_units_metric</item>
|
||||||
|
<item>@string/stats_units_imperial</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="stats_units_metric" translatable="false">METRIC</string>
|
||||||
|
<string name="stats_units_imperial" translatable="false">IMPERIAL</string>
|
||||||
<string-array name="stats_units_options">
|
<string-array name="stats_units_options">
|
||||||
<item>@string/settings_stats_units_metric</item>
|
<item>@string/settings_stats_units_metric</item>
|
||||||
<item>@string/settings_stats_units_imperial</item>
|
<item>@string/settings_stats_units_imperial</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="stats_units_values">
|
|
||||||
<item>@string/stats_units_metric</item>
|
<string name="track_name_key" translatable="false">trackName</string>
|
||||||
<item>@string/stats_units_imperial</item>
|
<string name="track_name_default" translatable="false">@string/settings_recording_track_name_date_iso_8601_value</string>
|
||||||
|
<string name="settings_recording_track_name_date_iso_8601_value" translatable="false">DATE_ISO_8601</string>
|
||||||
|
<string name="settings_recording_track_name_date_local_value" translatable="false">DATE_LOCAL</string>
|
||||||
|
<string name="settings_recording_track_name_number_value" translatable="false">NUMBER</string>
|
||||||
|
<string-array name="track_name_values">
|
||||||
|
<item>@string/settings_recording_track_name_date_local_value</item>
|
||||||
|
<item>@string/settings_recording_track_name_date_iso_8601_value</item>
|
||||||
|
<item>@string/settings_recording_track_name_number_value</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="track_name_options">
|
<string-array name="track_name_options">
|
||||||
<item>@string/settings_recording_track_name_date_local_option</item>
|
<item>@string/settings_recording_track_name_date_local_option</item>
|
||||||
<item>@string/settings_recording_track_name_date_iso_8601_option</item>
|
<item>@string/settings_recording_track_name_date_iso_8601_option</item>
|
||||||
<item>@string/settings_recording_track_name_number_option</item>
|
<item>@string/settings_recording_track_name_number_option</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="track_name_values">
|
|
||||||
<item>@string/settings_recording_track_name_date_local_value</item>
|
|
||||||
<item>@string/settings_recording_track_name_date_iso_8601_value</item>
|
|
||||||
<item>@string/settings_recording_track_name_number_value</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="waypoint_types">
|
|
||||||
<item>@string/waypoint_type_atm</item>
|
|
||||||
<item>@string/waypoint_type_bank</item>
|
|
||||||
<item>@string/waypoint_type_bar</item>
|
|
||||||
<item>@string/waypoint_type_barbecue</item>
|
|
||||||
<item>@string/waypoint_type_building</item>
|
|
||||||
<item>@string/waypoint_type_bus_stop</item>
|
|
||||||
<item>@string/waypoint_type_cafe</item>
|
|
||||||
<item>@string/waypoint_type_campfire</item>
|
|
||||||
<item>@string/waypoint_type_campground</item>
|
|
||||||
<item>@string/waypoint_type_church</item>
|
|
||||||
<item>@string/waypoint_type_coffee_house</item>
|
|
||||||
<item>@string/waypoint_type_convenience_store</item>
|
|
||||||
<item>@string/waypoint_type_drinking_water</item>
|
|
||||||
<item>@string/waypoint_type_falling_rocks</item>
|
|
||||||
<item>@string/waypoint_type_ferry</item>
|
|
||||||
<item>@string/waypoint_type_fire_place</item>
|
|
||||||
<item>@string/waypoint_type_fire_station</item>
|
|
||||||
<item>@string/waypoint_type_fishing</item>
|
|
||||||
<item>@string/waypoint_type_gas_station</item>
|
|
||||||
<item>@string/waypoint_type_golf_course</item>
|
|
||||||
<item>@string/waypoint_type_grocery_store</item>
|
|
||||||
<item>@string/waypoint_type_hair_dresser</item>
|
|
||||||
<item>@string/waypoint_type_harbor</item>
|
|
||||||
<item>@string/waypoint_type_hiking_path</item>
|
|
||||||
<item>@string/waypoint_type_hotel</item>
|
|
||||||
<item>@string/waypoint_type_house</item>
|
|
||||||
<item>@string/waypoint_type_information</item>
|
|
||||||
<item>@string/waypoint_type_intersection</item>
|
|
||||||
<item>@string/waypoint_type_mail_box</item>
|
|
||||||
<item>@string/waypoint_type_market</item>
|
|
||||||
<item>@string/waypoint_type_meeting_point</item>
|
|
||||||
<item>@string/waypoint_type_opera</item>
|
|
||||||
<item>@string/waypoint_type_parking</item>
|
|
||||||
<item>@string/waypoint_type_police_station</item>
|
|
||||||
<item>@string/waypoint_type_post_office</item>
|
|
||||||
<item>@string/waypoint_type_pothole</item>
|
|
||||||
<item>@string/waypoint_type_railway_crossing</item>
|
|
||||||
<item>@string/waypoint_type_restaurant</item>
|
|
||||||
<item>@string/waypoint_type_shopping</item>
|
|
||||||
<item>@string/waypoint_type_sight</item>
|
|
||||||
<item>@string/waypoint_type_store</item>
|
|
||||||
<item>@string/waypoint_type_swimming_pool</item>
|
|
||||||
<item>@string/waypoint_type_telephone</item>
|
|
||||||
<item>@string/waypoint_type_theater</item>
|
|
||||||
<item>@string/waypoint_type_toilet</item>
|
|
||||||
<item>@string/waypoint_type_tourist_information</item>
|
|
||||||
<item>@string/waypoint_type_tree</item>
|
|
||||||
<item>@string/waypoint_type_tunnel</item>
|
|
||||||
<item>@string/waypoint_type_waterfall</item>
|
|
||||||
<item>@string/waypoint_type_water_fountain</item>
|
|
||||||
<item>@string/waypoint_type_waypoint</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1055,7 +1055,13 @@ limitations under the License.
|
|||||||
Sending
|
Sending
|
||||||
</string>
|
</string>
|
||||||
<string name="sensor_not_known" translation_description="Error message if sensor is not available in Android (e.g., pairing was removed in Bluetooth Settings).">
|
<string name="sensor_not_known" translation_description="Error message if sensor is not available in Android (e.g., pairing was removed in Bluetooth Settings).">
|
||||||
Sensor %1$s is not known. Please check the settings.
|
Sensor %1$s is unknown. Please check the settings.
|
||||||
|
</string>
|
||||||
|
<string name="sensor_could_not_scan">
|
||||||
|
Could not scan for Bluetooth devices (error %1$i).
|
||||||
|
</string>
|
||||||
|
<string name="bluetooth_disabled">
|
||||||
|
Please enable Bluetooth.
|
||||||
</string>
|
</string>
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="settings_not_while_recording" translation_description="In settings, the summary for an option that is not available during a
|
<string name="settings_not_while_recording" translation_description="In settings, the summary for an option that is not available during a
|
||||||
@@ -1219,7 +1225,11 @@ limitations under the License.
|
|||||||
All settings have been reverted to the default values
|
All settings have been reverted to the default values
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<!-- Settings Sensor -->
|
<string name="settings_error_initial_values_restored" translation_description="If the ">
|
||||||
|
Sorry, but an error occurred. All settings have been reverted to the default values.
|
||||||
|
</string>
|
||||||
|
|
||||||
|
<!-- Settings Sensor -->
|
||||||
<string name="settings_sensor" translation_description="In the 'Settings' page, the option to change the sensor settings.
|
<string name="settings_sensor" translation_description="In the 'Settings' page, the option to change the sensor settings.
|
||||||
|
|
||||||
Character limit: ~26 (1 line)">
|
Character limit: ~26 (1 line)">
|
||||||
|
|||||||
@@ -14,44 +14,45 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:title="@string/menu_settings">
|
android:title="@string/menu_settings">
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/track_detail_stats_tab">
|
<PreferenceCategory android:title="@string/track_detail_stats_tab">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="@string/stats_units_metric"
|
android:defaultValue="@string/stats_units_default"
|
||||||
android:entries="@array/stats_units_options"
|
android:entries="@array/stats_units_options"
|
||||||
android:entryValues="@array/stats_units_values"
|
android:entryValues="@array/stats_units_values"
|
||||||
android:key="@string/stats_units_key"
|
android:key="@string/stats_units_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_stats_units_title"
|
||||||
android:title="@string/settings_stats_units_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="@string/stats_rate_speed"
|
android:defaultValue="@string/stats_rate_default"
|
||||||
android:entries="@array/stats_rate_metric_options"
|
android:entries="@array/stats_rate_metric_options"
|
||||||
android:entryValues="@array/stats_rate_values"
|
android:entryValues="@array/stats_rate_values"
|
||||||
android:key="@string/stats_rate_key"
|
android:key="@string/stats_rate_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_stats_rate_title"
|
||||||
android:title="@string/settings_stats_rate_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/settings_show">
|
<PreferenceCategory android:title="@string/settings_show">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="@bool/stats_show_grade_elevation_default"
|
||||||
android:key="@string/stats_show_grade_elevation_key"
|
android:key="@string/stats_show_grade_elevation_key"
|
||||||
android:title="@string/settings_stats_grade_elevation" />
|
android:title="@string/settings_stats_grade_elevation" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="@bool/stats_show_coordinate_default"
|
||||||
android:key="@string/stats_show_coordinate_key"
|
android:key="@string/stats_show_coordinate_key"
|
||||||
android:title="@string/settings_stats_coordinate" />
|
android:title="@string/settings_stats_coordinate" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/track_detail_chart_tab">
|
<PreferenceCategory android:title="@string/track_detail_chart_tab">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="@string/chart_x_axis_distance"
|
android:defaultValue="@string/chart_x_axis_default"
|
||||||
android:entries="@array/chart_x_axis_options"
|
android:entries="@array/chart_x_axis_options"
|
||||||
android:entryValues="@array/chart_x_axis_values"
|
android:entryValues="@array/chart_x_axis_values"
|
||||||
android:key="@string/chart_x_axis_key"
|
android:key="@string/chart_x_axis_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_chart_x_axis"
|
||||||
android:title="@string/settings_chart_x_axis" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="@string/chart_show_elevation_key"
|
android:key="@string/chart_show_elevation_key"
|
||||||
@@ -68,80 +69,71 @@ limitations under the License.
|
|||||||
|
|
||||||
<PreferenceCategory android:title="@string/settings_recording">
|
<PreferenceCategory android:title="@string/settings_recording">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="@bool/stats_show_on_lockscreen_while_recording_default"
|
||||||
android:key="@string/trackdetail_show_on_lockscreen_while_recording_key"
|
android:key="@string/stats_show_on_lockscreen_while_recording_key"
|
||||||
android:summary="@string/settings_recording_show_on_lockscreen_while_recording_summary"
|
android:summary="@string/settings_recording_show_on_lockscreen_while_recording_summary"
|
||||||
android:title="@string/settings_recording_show_on_lockscreen_while_recording_title" />
|
android:title="@string/settings_recording_show_on_lockscreen_while_recording_title" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="@string/voice_frequency_default"
|
||||||
android:entryValues="@array/frequency_values"
|
android:entryValues="@array/frequency_values"
|
||||||
android:key="@string/voice_frequency_key"
|
android:key="@string/voice_frequency_key"
|
||||||
android:summary="%s"
|
android:title="@string/menu_voice_frequency"
|
||||||
android:title="@string/menu_voice_frequency" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="@string/split_frequency_default"
|
||||||
android:entryValues="@array/frequency_values"
|
android:entryValues="@array/frequency_values"
|
||||||
android:key="@string/split_frequency_key"
|
android:key="@string/split_frequency_key"
|
||||||
android:summary="%s"
|
android:title="@string/menu_split_frequency"
|
||||||
android:title="@string/menu_split_frequency" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="@string/settings_recording_track_name_date_iso_8601_value"
|
android:defaultValue="@string/track_name_default"
|
||||||
android:entries="@array/track_name_options"
|
android:entries="@array/track_name_options"
|
||||||
android:entryValues="@array/track_name_values"
|
android:entryValues="@array/track_name_values"
|
||||||
android:key="@string/track_name_key"
|
android:key="@string/track_name_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_track_name_title"
|
||||||
android:title="@string/settings_recording_track_name_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="@string/min_recording_interval_default"
|
||||||
android:entryValues="@array/min_recording_interval_values"
|
android:entryValues="@array/min_recording_interval_values"
|
||||||
android:key="@string/min_recording_interval_key"
|
android:key="@string/min_recording_interval_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_min_recording_interval_title"
|
||||||
android:title="@string/settings_recording_min_recording_interval_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="10"
|
android:defaultValue="@string/recording_distance_interval_default"
|
||||||
android:entryValues="@array/recording_distance_interval_values"
|
android:entryValues="@array/recording_distance_interval_values"
|
||||||
android:key="@string/recording_distance_interval_key"
|
android:key="@string/recording_distance_interval_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_min_recording_distance_title"
|
||||||
android:title="@string/settings_recording_min_recording_distance_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="200"
|
android:defaultValue="@string/max_recording_distance_default"
|
||||||
android:entryValues="@array/max_recording_distance_values"
|
android:entryValues="@array/max_recording_distance_values"
|
||||||
android:key="@string/max_recording_distance_key"
|
android:key="@string/max_recording_distance_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_max_recording_distance_title"
|
||||||
android:title="@string/settings_recording_max_recording_distance_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="50"
|
android:defaultValue="@string/recording_gps_accuracy_default"
|
||||||
android:entryValues="@array/recording_gps_accuracy_values"
|
android:entryValues="@array/recording_gps_accuracy_values"
|
||||||
android:key="@string/recording_gps_accuracy_key"
|
android:key="@string/recording_gps_accuracy_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_min_required_accuracy_title"
|
||||||
android:title="@string/settings_recording_min_required_accuracy_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="10"
|
android:defaultValue="@string/auto_resume_track_timeout_default"
|
||||||
android:entries="@array/auto_resume_track_timeout_values"
|
android:entries="@array/auto_resume_track_timeout_values"
|
||||||
android:entryValues="@array/auto_resume_track_timeout_values"
|
android:entryValues="@array/auto_resume_track_timeout_values"
|
||||||
android:key="@string/auto_resume_track_timeout_key"
|
android:key="@string/auto_resume_track_timeout_key"
|
||||||
android:summary="%s"
|
android:title="@string/settings_recording_auto_resume_track_timeout_title"
|
||||||
android:title="@string/settings_recording_auto_resume_track_timeout_title" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<de.dennisguse.opentracks.settings.ActivityTypePreference
|
<de.dennisguse.opentracks.settings.ActivityTypePreference
|
||||||
android:defaultValue="@string/activity_type_running"
|
android:defaultValue="@string/default_activity_default"
|
||||||
android:key="@string/default_activity_key"
|
android:key="@string/default_activity_key"
|
||||||
android:title="@string/settings_recording_default_activity_title" />
|
android:title="@string/settings_recording_default_activity_title" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory android:title="@string/settings_sensor_bluetooth">
|
||||||
android:title="@string/settings_sensor">
|
<de.dennisguse.opentracks.settings.BluetoothLePreference
|
||||||
<ListPreference
|
|
||||||
android:defaultValue="@string/sensor_type_value_none"
|
android:defaultValue="@string/sensor_type_value_none"
|
||||||
android:key="@string/bluetooth_sensor_key"
|
android:key="@string/settings_sensor_bluetooth_heart_rate_key"
|
||||||
android:summary="%s"
|
android:title="@string/sensor_state_heart_rate" />
|
||||||
android:title="@string/settings_sensor_bluetooth_sensor" />
|
|
||||||
<Preference
|
|
||||||
android:key="@string/settings_sensor_bluetooth_pairing_key"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summary="@string/settings_sensor_bluetooth_pairing_summary"
|
|
||||||
android:title="@string/settings_sensor_bluetooth_pairing">
|
|
||||||
<intent android:action="android.settings.BLUETOOTH_SETTINGS" />
|
|
||||||
</Preference>
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/generic_tracks">
|
<PreferenceCategory android:title="@string/generic_tracks">
|
||||||
@@ -159,8 +151,8 @@ limitations under the License.
|
|||||||
|
|
||||||
<PreferenceCategory android:title="@string/settings_reset">
|
<PreferenceCategory android:title="@string/settings_reset">
|
||||||
<de.dennisguse.opentracks.settings.ResetDialogPreference
|
<de.dennisguse.opentracks.settings.ResetDialogPreference
|
||||||
android:dialogTitle="@string/settings_reset_confirm_title"
|
|
||||||
android:dialogMessage="@string/settings_reset_confirm_message"
|
android:dialogMessage="@string/settings_reset_confirm_message"
|
||||||
|
android:dialogTitle="@string/settings_reset_confirm_title"
|
||||||
android:key="@string/settings_reset_key"
|
android:key="@string/settings_reset_key"
|
||||||
android:negativeButtonText="@string/generic_cancel"
|
android:negativeButtonText="@string/generic_cancel"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
|
|||||||
Reference in New Issue
Block a user