forked from upstream-mirrors/OpenTracks
-53
@@ -1,53 +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.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* This is a simple location listener policy that will always dictate the same polling interval.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
|
||||
|
||||
private final Duration interval;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param interval the interval to request for gps signal
|
||||
*/
|
||||
public AbsoluteLocationListenerPolicy(Duration interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getDesiredPollingInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinDistance_m() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIdleTime(Duration idleTime) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
-76
@@ -1,76 +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.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* A {@link LocationListenerPolicy} that will change based on how long the user has been stationary.
|
||||
* This policy will dictate a policy based on a min, max and idle time.
|
||||
* The policy will dictate an interval bounded by min and max, and is half of the idle time.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy {
|
||||
|
||||
private final Duration minInterval;
|
||||
private final Duration maxInterval;
|
||||
private final int minDistance_m;
|
||||
|
||||
// The time the user has been idle at the current location, in milliseconds.
|
||||
private Duration idleTime;
|
||||
|
||||
/**
|
||||
* Creates a policy that will be bounded by the given minInterval_ms and maxInterval_ms.
|
||||
*
|
||||
* @param minInterval the smallest interval this policy will dictate
|
||||
* @param maxInterval the largest interval this policy will dictate
|
||||
* @param minDistance_m the minimum distance
|
||||
*/
|
||||
public AdaptiveLocationListenerPolicy(Duration minInterval, Duration maxInterval, int minDistance_m) {
|
||||
this.minInterval = minInterval;
|
||||
this.maxInterval = maxInterval;
|
||||
this.minDistance_m = minDistance_m;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an interval half of the idle time, but bounded by minInterval and maxInterval.
|
||||
*/
|
||||
public Duration getDesiredPollingInterval() {
|
||||
Duration desiredInterval = idleTime.dividedBy(2);
|
||||
|
||||
// Round to second to avoid setting the interval too often
|
||||
desiredInterval = Duration.ofSeconds(desiredInterval.getSeconds());
|
||||
|
||||
if (minInterval.compareTo(desiredInterval) > 0) {
|
||||
return minInterval;
|
||||
} else if (maxInterval.compareTo(desiredInterval) < 0) {
|
||||
return maxInterval;
|
||||
}
|
||||
return desiredInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinDistance_m() {
|
||||
return minDistance_m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIdleTime(Duration newIdleTime) {
|
||||
idleTime = newIdleTime;
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,8 @@ class GpsStatus {
|
||||
SharedPreferences sharedPreferences = PreferencesUtils.getSharedPreferences(context);
|
||||
thresholdHorizontalAccuracy = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context);
|
||||
|
||||
Duration minRecordingInterval = Duration.ofSeconds(PreferencesUtils.getMinRecordingInterval(sharedPreferences, context));
|
||||
signalLostThreshold = !minRecordingInterval.isNegative() ? SIGNAL_LOST_THRESHOLD.plus(minRecordingInterval) : SIGNAL_LOST_THRESHOLD;
|
||||
Duration minRecordingInterval = PreferencesUtils.getMinRecordingInterval(sharedPreferences, context);
|
||||
signalLostThreshold = SIGNAL_LOST_THRESHOLD.plus(minRecordingInterval);
|
||||
|
||||
gpsStatusHandler = new Handler();
|
||||
}
|
||||
@@ -102,13 +102,8 @@ class GpsStatus {
|
||||
thresholdHorizontalAccuracy = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the lost threshold from outside.
|
||||
*
|
||||
* @param value Minimal recording interval preference value in seconds or an special value: -1, -2, 0.
|
||||
*/
|
||||
public void onMinRecordingIntervalChanged(int value) {
|
||||
signalLostThreshold = value > 0 ? SIGNAL_LOST_THRESHOLD.plus(Duration.ofSeconds(value)) : SIGNAL_LOST_THRESHOLD;
|
||||
public void onMinRecordingIntervalChanged(Duration value) {
|
||||
signalLostThreshold = SIGNAL_LOST_THRESHOLD.plus(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
|
||||
@VisibleForTesting(otherwise = 3)
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public class LocationHandler implements LocationListener, GpsStatus.GpsStatusListener {
|
||||
|
||||
private final String TAG = LocationHandler.class.getSimpleName();
|
||||
@@ -27,8 +27,7 @@ public class LocationHandler implements LocationListener, GpsStatus.GpsStatusLis
|
||||
private LocationManager locationManager;
|
||||
private final TrackPointCreator handlerServer;
|
||||
private GpsStatus gpsStatus;
|
||||
private LocationListenerPolicy locationListenerPolicy;
|
||||
private Duration currentRecordingInterval;
|
||||
private Duration gpsInterval;
|
||||
private Distance thresholdHorizontalAccuracy;
|
||||
private TrackPoint lastTrackPoint;
|
||||
|
||||
@@ -64,32 +63,31 @@ public class LocationHandler implements LocationListener, GpsStatus.GpsStatusLis
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(@NonNull Context context, @NonNull SharedPreferences sharedPreferences, String key) {
|
||||
if (PreferencesUtils.isKey(context, R.string.min_recording_interval_key, key)) {
|
||||
int minRecordingInterval = PreferencesUtils.getMinRecordingInterval(sharedPreferences, context);
|
||||
if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
|
||||
// Choose battery life over moving time accuracy.
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(30), Duration.ofSeconds(5), 5);
|
||||
} else if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
|
||||
// Get all the updates.
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(1), Duration.ofSeconds(30), 0);
|
||||
} else {
|
||||
locationListenerPolicy = new AbsoluteLocationListenerPolicy(Duration.ofSeconds(minRecordingInterval));
|
||||
}
|
||||
boolean registerListener = false;
|
||||
|
||||
registerLocationListener();
|
||||
if (PreferencesUtils.isKey(context, R.string.min_recording_interval_key, key)) {
|
||||
registerListener = true;
|
||||
|
||||
gpsInterval = PreferencesUtils.getMinRecordingInterval(sharedPreferences, context);
|
||||
|
||||
if (gpsStatus != null) {
|
||||
gpsStatus.onMinRecordingIntervalChanged(gpsInterval);
|
||||
}
|
||||
}
|
||||
if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) {
|
||||
thresholdHorizontalAccuracy = PreferencesUtils.getThresholdHorizontalAccuracy(sharedPreferences, context);
|
||||
}
|
||||
if (PreferencesUtils.isKey(context, R.string.min_recording_interval_key, key)) {
|
||||
if (PreferencesUtils.isKey(context, R.string.recording_distance_interval_key, key)) {
|
||||
registerListener = true;
|
||||
|
||||
if (gpsStatus != null) {
|
||||
gpsStatus.onMinRecordingIntervalChanged(PreferencesUtils.getMinRecordingInterval(sharedPreferences, context));
|
||||
Distance gpsMinDistance = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context);
|
||||
gpsStatus.onRecordingDistanceChanged(gpsMinDistance);
|
||||
}
|
||||
}
|
||||
if (PreferencesUtils.isKey(context, R.string.recording_distance_interval_key, key)) {
|
||||
if (gpsStatus != null) {
|
||||
gpsStatus.onRecordingDistanceChanged(PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context));
|
||||
}
|
||||
|
||||
if (registerListener) {
|
||||
registerLocationListener();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,16 +121,6 @@ public class LocationHandler implements LocationListener, GpsStatus.GpsStatusLis
|
||||
return;
|
||||
}
|
||||
|
||||
Duration idleTime = Duration.ofSeconds(0);
|
||||
if (lastTrackPoint != null && trackPoint.getTime().isAfter(lastTrackPoint.getTime())) {
|
||||
idleTime = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
}
|
||||
|
||||
locationListenerPolicy.updateIdleTime(idleTime);
|
||||
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
|
||||
registerLocationListener();
|
||||
}
|
||||
|
||||
lastTrackPoint = trackPoint;
|
||||
handlerServer.onNewTrackPoint(trackPoint, thresholdHorizontalAccuracy);
|
||||
}
|
||||
@@ -161,9 +149,7 @@ public class LocationHandler implements LocationListener, GpsStatus.GpsStatusLis
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Duration interval = locationListenerPolicy.getDesiredPollingInterval();
|
||||
currentRecordingInterval = interval;
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval.toMillis(), locationListenerPolicy.getMinDistance_m(), this);
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval.toMillis(), 0, this);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
|
||||
}
|
||||
|
||||
@@ -1,46 +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.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* This is an interface for classes that will manage the location listener policy.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
interface LocationListenerPolicy {
|
||||
|
||||
/**
|
||||
* Returns the polling interval this policy would like at this moment.
|
||||
*
|
||||
* @return the polling interval
|
||||
*/
|
||||
Duration getDesiredPollingInterval();
|
||||
|
||||
/**
|
||||
* Returns the minimum distance between updates.
|
||||
*/
|
||||
int getMinDistance_m();
|
||||
|
||||
/**
|
||||
* Notifies the amount of time the user has been idle at his current location.
|
||||
*
|
||||
* @param idleTime the time that the user has been idle at his current location
|
||||
*/
|
||||
void updateIdleTime(Duration idleTime);
|
||||
}
|
||||
@@ -14,11 +14,7 @@ final class PreferenceHelper {
|
||||
for (int i = 0; i < entryValues.length; i++) {
|
||||
int value = Integer.parseInt(entryValues[i]);
|
||||
|
||||
if (value == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
|
||||
entries[i] = context.getString(R.string.value_adapt_accuracy);
|
||||
} else if (value == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
|
||||
entries[i] = context.getString(R.string.value_adapt_battery_life);
|
||||
} else if (value == PreferencesUtils.getMinRecordingIntervalDefault(context)) {
|
||||
if (value == PreferencesUtils.getMinRecordingIntervalDefault(context).getSeconds()) {
|
||||
entries[i] = context.getString(R.string.value_smallest_recommended);
|
||||
} else {
|
||||
entries[i] = value < 60 ? context.getString(R.string.value_integer_second, value) : context.getString(R.string.value_integer_minute, value / 60);
|
||||
|
||||
@@ -203,7 +203,7 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity
|
||||
findPreference(getString(R.string.min_recording_interval_key))
|
||||
.setSummaryProvider(
|
||||
preference -> {
|
||||
Duration interval = Duration.ofSeconds(PreferencesUtils.getMinRecordingInterval(sharedPreferences, getContext()));
|
||||
Duration interval = PreferencesUtils.getMinRecordingInterval(sharedPreferences, getContext());
|
||||
return getString(R.string.settings_recording_location_frequency_summary, getString(R.string.value_integer_second, interval.getSeconds()));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -28,6 +28,8 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -241,22 +243,19 @@ public class PreferencesUtils {
|
||||
return Distance.of(getInt(sharedPreferences, context, R.string.max_recording_distance_key, MAX_RECORDING_DISTANCE));
|
||||
}
|
||||
|
||||
//TODO Duration
|
||||
public static int getMinRecordingInterval(SharedPreferences sharedPreferences, Context context) {
|
||||
final int MIN_RECORDING_INTERVAL = Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default));
|
||||
return getInt(sharedPreferences, context, R.string.min_recording_interval_key, MIN_RECORDING_INTERVAL);
|
||||
public static Duration getMinRecordingInterval(SharedPreferences sharedPreferences, Context context) {
|
||||
final Duration MIN_RECORDING_INTERVAL = getMinRecordingIntervalDefault(context);
|
||||
Duration interval = Duration.ofSeconds(getInt(sharedPreferences, context, R.string.min_recording_interval_key, (int) MIN_RECORDING_INTERVAL.getSeconds()));
|
||||
|
||||
if (interval.isNegative()) {
|
||||
// Due to removal of adaptive listener policy; used -1, and -2
|
||||
interval = getMinRecordingIntervalDefault(context);
|
||||
}
|
||||
return 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 Duration getMinRecordingIntervalDefault(Context context) {
|
||||
return Duration.ofSeconds(Integer.parseInt(context.getResources().getString(R.string.min_recording_interval_default)));
|
||||
}
|
||||
|
||||
public static Distance getThresholdHorizontalAccuracy(SharedPreferences sharedPreferences, Context context) {
|
||||
|
||||
Reference in New Issue
Block a user