Cleanup: mainly code formatting and made LocationIterator implement autoclosable.

This commit is contained in:
Dennis Guse
2019-09-07 12:23:56 +02:00
parent 025dee6821
commit 87d92d25f9
104 changed files with 1076 additions and 1526 deletions
@@ -17,8 +17,7 @@
package de.dennisguse.opentracks.services;
/**
* This is a simple location listener policy that will always dictate the same
* polling interval.
* This is a simple location listener policy that will always dictate the same polling interval.
*
* @author Sandor Dornbush
*/
@@ -41,7 +40,7 @@ public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
}
@Override
public int getMinDistance() {
public int getMinDistance_m() {
return 0;
}
@@ -17,53 +17,48 @@
package de.dennisguse.opentracks.services;
/**
* 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.
* 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 long minInterval;
private final long maxInterval;
private final int minDistance;
private final long minInterval_ms;
private final long maxInterval_ms;
private final int minDistance_m;
// The time the user has been idle at the current location, in milliseconds.
private long idleTime;
/**
* Creates a policy that will be bounded by the given minInterval and
* maxInterval.
* Creates a policy that will be bounded by the given minInterval_ms and maxInterval_ms.
*
* @param minInterval the smallest interval this policy will dictate, in
* milliseconds
* @param maxInterval the largest interval this policy will dictate, in
* milliseconds
* @param minDistance the minimum distance in meters
* @param minInterval_ms the smallest interval this policy will dictate
* @param maxInterval_ms the largest interval this policy will dictate
* @param minDistance_m the minimum distance
*/
public AdaptiveLocationListenerPolicy(long minInterval, long maxInterval, int minDistance) {
this.minInterval = minInterval;
this.maxInterval = maxInterval;
this.minDistance = minDistance;
public AdaptiveLocationListenerPolicy(long minInterval_ms, long maxInterval_ms, int minDistance_m) {
this.minInterval_ms = minInterval_ms;
this.maxInterval_ms = maxInterval_ms;
this.minDistance_m = minDistance_m;
}
/*
* Returns an interval half of the idle time, but bounded by minInteval and
* maxInterval.
* Returns an interval half of the idle time, but bounded by minInterval_ms and maxInterval_ms.
*/
@Override
public long getDesiredPollingInterval() {
long desiredInterval = idleTime / 2;
long desiredInterval_ms = idleTime / 2;
// Round to second to avoid setting the interval too often
desiredInterval = (desiredInterval / 1000) * 1000;
return Math.max(Math.min(maxInterval, desiredInterval), minInterval);
desiredInterval_ms = (desiredInterval_ms / 1000) * 1000;
return Math.max(Math.min(maxInterval_ms, desiredInterval_ms), minInterval_ms);
}
@Override
public int getMinDistance() {
return minDistance;
public int getMinDistance_m() {
return minDistance_m;
}
@Override
@@ -30,12 +30,10 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.widgets.TrackWidgetProvider;
/**
* A service to control starting and stopping of a recording. This service,
* through the AndroidManifest.xml, is configured to only allow components of
* the same application to invoke it. Thus this service can be used my the
* app widget, {@link TrackWidgetProvider}, but not by other applications. This
* application delegates starting and stopping a recording to
* {@link TrackRecordingService} using RPC calls.
* A service to control starting and stopping of a recording.
* This service, through the AndroidManifest.xml, is configured to only allow components of the same application to invoke it.
* Thus this service can be used by the app widget, {@link TrackWidgetProvider}, but not by other applications.
* This application delegates starting and stopping a recording to {@link TrackRecordingService} using RPC calls.
*
* @author Jimmy Shih
*/
@@ -60,9 +58,8 @@ public class ControlRecordingService extends IntentService implements ServiceCon
}
@VisibleForTesting
@Nullable
@Override
public IBinder onBind(Intent intent) {
public IBinder onBind(@Nullable Intent intent) {
return new LocalBinder();
}
@@ -104,8 +101,7 @@ public class ControlRecordingService extends IntentService implements ServiceCon
}
/**
* Notifies all threads that connection to {@link TrackRecordingService} is
* available.
* Notifies all threads that connection to {@link TrackRecordingService} is available.
*/
private synchronized void notifyConnected() {
connected = true;
@@ -120,7 +116,6 @@ public class ControlRecordingService extends IntentService implements ServiceCon
try {
wait();
} catch (InterruptedException e) {
// can safely ignore
}
}
@@ -133,7 +128,7 @@ public class ControlRecordingService extends IntentService implements ServiceCon
}
@VisibleForTesting
public class LocalBinder extends Binder {
class LocalBinder extends Binder {
ControlRecordingService getService() {
return ControlRecordingService.this;
}
@@ -17,9 +17,10 @@ package de.dennisguse.opentracks.services;
import android.location.Location;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.content.WaypointCreationRequest;
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.content.sensor.SensorState;
/**
* App's service.
@@ -97,6 +98,7 @@ public interface ITrackRecordingService {
*
* @param location the track point to be inserted
*/
@VisibleForTesting
void insertTrackPoint(Location location);
/**
@@ -105,11 +107,4 @@ public interface ITrackRecordingService {
* @return SensorDataSet object.
*/
SensorDataSet getSensorData();
/**
* Gets the current sensor manager state.
* <p>
* return a Sensor.SensorState enum value.
*/
SensorState getSensorState();
}
@@ -17,9 +17,7 @@
package de.dennisguse.opentracks.services;
/**
* This is an interface for classes that will manage the location listener
* policy. Different policy options are: {@link AbsoluteLocationListenerPolicy}
* and {@link AdaptiveLocationListenerPolicy}.
* This is an interface for classes that will manage the location listener policy.
*
* @author Sandor Dornbush
*/
@@ -35,13 +33,12 @@ public interface LocationListenerPolicy {
/**
* Returns the minimum distance between updates.
*/
int getMinDistance();
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
* @param idleTime the time that the user has been idle at his current location
*/
void updateIdleTime(long idleTime);
}
@@ -57,7 +57,6 @@ import de.dennisguse.opentracks.content.Waypoint;
import de.dennisguse.opentracks.content.Waypoint.WaypointType;
import de.dennisguse.opentracks.content.WaypointCreationRequest;
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.content.sensor.SensorState;
import de.dennisguse.opentracks.services.sensors.RemoteSensorManager;
import de.dennisguse.opentracks.services.sensors.RemoteSensorManagerFactory;
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
@@ -947,7 +946,7 @@ public class TrackRecordingService extends Service {
}
try {
long interval = locationListenerPolicy.getDesiredPollingInterval();
locationManagerConnector.requestLocationUpdates(interval, locationListenerPolicy.getMinDistance(), locationListener);
locationManagerConnector.requestLocationUpdates(interval, locationListenerPolicy.getMinDistance_m(), locationListener);
currentRecordingInterval = interval;
} catch (RuntimeException e) {
Log.e(TAG, "Could not register location listener.", e);
@@ -1116,15 +1115,6 @@ public class TrackRecordingService extends Service {
return trackRecordingService.remoteSensorManager.getSensorDataSet();
}
@Override
public SensorState getSensorState() {
if (trackRecordingService.remoteSensorManager == null) {
Log.d(TAG, "remoteSensorManager is null.");
return SensorState.NONE;
}
return trackRecordingService.remoteSensorManager.getSensorState();
}
/**
* Detaches from the track recording service. Clears the reference to the
* outer class to minimize the leak.
@@ -25,12 +25,13 @@ import android.os.IBinder.DeathRecipient;
import android.os.RemoteException;
import android.util.Log;
import de.dennisguse.opentracks.util.TrackRecordingServiceConnectionUtils;
import de.dennisguse.opentracks.BuildConfig;
import de.dennisguse.opentracks.util.TrackRecordingServiceConnectionUtils;
/**
* Wrapper for the track recording service. This handles service
* start/bind/unbind/stop. The service must be started before it can be bound.
* Wrapper for the track recording service.
* This handles service start/bind/unbind/stop.
* The service must be started before it can be bound.
* Returns the service if it is started and bound.
*
* @author Rodrigo Damazio
@@ -38,8 +39,10 @@ import de.dennisguse.opentracks.BuildConfig;
public class TrackRecordingServiceConnection {
private static final String TAG = TrackRecordingServiceConnection.class.getSimpleName();
private final Context context;
private final Runnable callback;
private ITrackRecordingService trackRecordingService;
private final DeathRecipient deathRecipient = new DeathRecipient() {
@Override
@@ -48,6 +51,7 @@ public class TrackRecordingServiceConnection {
setTrackRecordingService(null);
}
};
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
@@ -130,8 +134,7 @@ public class TrackRecordingServiceConnection {
return;
}
if (!startIfNeeded
&& !TrackRecordingServiceConnectionUtils.isRecordingServiceRunning(context)) {
if (!startIfNeeded && !TrackRecordingServiceConnectionUtils.isRecordingServiceRunning(context)) {
Log.d(TAG, "Service is not started. Not binding it.");
return;
}
@@ -30,11 +30,11 @@ import android.util.Log;
import androidx.annotation.NonNull;
import java.util.UUID;
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.content.sensor.SensorState;
import java.util.UUID;
/**
* Manages connection to Bluetooth LE heart rate monitor.
* TODO: shutdown connection.
@@ -42,16 +42,20 @@ import java.util.UUID;
public class BluetoothConnectionManager {
// Message types sent to handler
public static final int MESSAGE_DEVICE_NAME = 1;
public static final int MESSAGE_READ = 2;
public static final String KEY_DEVICE_NAME = "device_name";
static final int MESSAGE_DEVICE_NAME = 1;
static final int MESSAGE_READ = 2;
static final String KEY_DEVICE_NAME = "device_name";
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 CLIENT_CHARACTERISTIC_CONFIG_UUID = new UUID(0x290200001000L, 0x800000805f9b34fbL);
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
private final Context context;
private final Handler handler;
private SensorState sensorState;
private BluetoothGattCallback connectCallback = new BluetoothGattCallback() {
@@ -100,7 +104,7 @@ public class BluetoothConnectionManager {
*
* @param handler a handler for sending messages back to the UI activity
*/
public BluetoothConnectionManager(Context context, Handler handler) {
BluetoothConnectionManager(Context context, Handler handler) {
this.context = context;
this.handler = handler;
this.sensorState = SensorState.NONE;
@@ -109,7 +113,7 @@ public class BluetoothConnectionManager {
/**
* Gets the sensor state.
*/
public synchronized SensorState getSensorState() {
synchronized SensorState getSensorState() {
return sensorState;
}
@@ -2,12 +2,12 @@ package de.dennisguse.opentracks.services.sensors;
import android.bluetooth.BluetoothGattCharacteristic;
public final class BluetoothLEUtils {
final class BluetoothLEUtils {
private BluetoothLEUtils() {
}
public static int parseHeartRate(BluetoothGattCharacteristic characteristic) {
static int parseHeartRate(BluetoothGattCharacteristic characteristic) {
//DOCUMENTATION https://www.bluetooth.com/specifications/gatt/characteristics/
byte[] raw = characteristic.getValue();
int index = ((raw[0] & 0x1) == 1) ? 2 : 1;
@@ -34,7 +34,6 @@ import de.dennisguse.opentracks.util.UnitConversions;
/**
* Bluetooth sensor manager.
* <p>
* TODO: Handle a BluetoothGatt.STATE_DISCONNECTED
*
* @author Sandor Dornbush
@@ -42,10 +41,15 @@ import de.dennisguse.opentracks.util.UnitConversions;
public class BluetoothRemoteSensorManager extends RemoteSensorManager {
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
private static final BluetoothAdapter bluetoothAdapter = getDefaultBluetoothAdapter();
private final Context context;
private final BluetoothConnectionManager bluetoothConnectionManager;
private SensorDataSet sensorDataSet = null;
// Handler that gets information back from the bluetoothConnectionManager
private final Handler messageHandler = new Handler(Looper.getMainLooper()) {
@Override
@@ -71,7 +75,7 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager {
/**
* @param context the context
*/
public BluetoothRemoteSensorManager(Context context) {
BluetoothRemoteSensorManager(Context context) {
this.context = context;
bluetoothConnectionManager = new BluetoothConnectionManager(context, messageHandler);
}
@@ -109,7 +113,6 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager {
if (adapters.get(0) == null) {
Log.w(TAG, "No bluetooth adapter found.");
return null;
}
return adapters.get(0);
}
@@ -125,6 +128,7 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager {
Log.w(TAG, "Bluetooth not enabled.");
return;
}
String address = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
if (PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(address)) {
Log.w(TAG, "No bluetooth address.");
@@ -78,13 +78,10 @@ public abstract class RemoteSensorManager {
setUpChannel();
}
break;
case NONE:
case DISCONNECTED:
setUpChannel();
break;
default:
// CONNECTED or SENDING
break;
default: // NONE, CONNECTED or SENDING
}
}
};
@@ -26,6 +26,8 @@ import android.content.Context;
public class RemoteSensorManagerFactory {
private static RemoteSensorManager remoteSensorManagerSystem = null;
//TODO Check if still needed? Is there a missing features?
private static RemoteSensorManager remoteSensorManagerTemporary = null;
private RemoteSensorManagerFactory() {
@@ -70,7 +72,7 @@ public class RemoteSensorManagerFactory {
/**
* Releases the temp sensor manager.
*/
public static void releaseSensorManagerTemporary() {
private static void releaseSensorManagerTemporary() {
if (remoteSensorManagerTemporary != null) {
remoteSensorManagerTemporary.stopSensor();
}
@@ -27,14 +27,14 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import java.util.Locale;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.stats.TripStatistics;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.util.UnitConversions;
import de.dennisguse.opentracks.R;
import java.util.Locale;
/**
* This class will periodically announce the user's trip statistics.
@@ -50,7 +50,9 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
static final float TTS_SPEECH_RATE = 0.9f;
private static final String TAG = AnnouncementPeriodicTask.class.getSimpleName();
private final Context context;
private final AudioManager audioManager;
private final UtteranceProgressListener utteranceListener = new UtteranceProgressListener() {
@Override
@@ -69,13 +71,16 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
public void onError(String utteranceId) {
}
};
private TextToSpeech tts;
// Response from TTS after its initialization
private int initStatus = TextToSpeech.ERROR;
// True if TTS engine is ready
private boolean ready = false;
private boolean ttsReady = false;
// True if speech is allowed
private boolean speechAllowed;
/**
* Listener which updates {@link #speechAllowed} when the phone state changes.
*/
@@ -90,7 +95,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
}
};
public AnnouncementPeriodicTask(Context context) {
AnnouncementPeriodicTask(Context context) {
this.context = context;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@@ -131,13 +136,13 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
}
synchronized (this) {
if (!ready) {
ready = initStatus == TextToSpeech.SUCCESS;
if (ready) {
if (!ttsReady) {
ttsReady = initStatus == TextToSpeech.SUCCESS;
if (ttsReady) {
onTtsReady();
}
}
if (!ready) {
if (!ttsReady) {
Log.i(TAG, "TTS not ready.");
return;
}
@@ -170,9 +175,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
Log.w(TAG, "Default locale not available, use English.");
locale = Locale.ENGLISH;
/*
* TODO: instead of using english, load the language if missing and show a
* toast if not supported. Not able to change the resource strings to
* English.
* TODO: instead of using english, load the language if missing and show a toast if not supported.
* Not able to change the resource strings to English.
*/
}
tts.setLanguage(locale);
@@ -189,8 +193,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
* @param announcement the announcement
*/
private void speakAnnouncement(String announcement) {
int result = audioManager.requestAudioFocus(
null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
int result = audioManager.requestAudioFocus(null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "Failed to request audio focus.");
}
@@ -223,7 +226,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
boolean reportSpeed = PreferencesUtils.isReportSpeed(context);
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
double speed = tripStatistics.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH;
double distancePerTime = tripStatistics.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH;
if (distance == 0) {
return context.getString(R.string.voice_total_distance_zero);
@@ -231,26 +234,22 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
if (!metricUnits) {
distance *= UnitConversions.KM_TO_MI;
speed *= UnitConversions.KM_TO_MI;
distancePerTime *= UnitConversions.KM_TO_MI;
}
String rate;
if (reportSpeed) {
int speedId = metricUnits ? R.plurals.voiceSpeedKilometersPerHour
: R.plurals.voiceSpeedMilesPerHour;
rate = context.getResources().getQuantityString(speedId, getQuantityCount(speed), speed);
int speedId = metricUnits ? R.plurals.voiceSpeedKilometersPerHour : R.plurals.voiceSpeedMilesPerHour;
rate = context.getResources().getQuantityString(speedId, getQuantityCount(distancePerTime), distancePerTime);
} else {
speed = speed == 0 ? 0.0 : 1 / speed;
double timePerDistance = distancePerTime == 0 ? 0.0 : 1 / distancePerTime;
int paceId = metricUnits ? R.string.voice_pace_per_kilometer : R.string.voice_pace_per_mile;
long time = Math.round(
speed * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS);
long time = Math.round(timePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS);
rate = context.getString(paceId, getAnnounceTime(time));
}
int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers
: R.plurals.voiceTotalDistanceMiles;
String totalDistance = context.getResources()
.getQuantityString(totalDistanceId, getQuantityCount(distance), distance);
int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers : R.plurals.voiceTotalDistanceMiles;
String totalDistance = context.getResources().getQuantityString(totalDistanceId, getQuantityCount(distance), distance);
return context.getString(R.string.voice_template, totalDistance,
getAnnounceTime(tripStatistics.getMovingTime()), rate);
@@ -264,8 +263,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
*/
@VisibleForTesting
protected void listenToPhoneState(PhoneStateListener listener, int events) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephony != null) {
telephony.listen(listener, events);
}
@@ -297,15 +295,13 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
}
/**
* Gets the plural count to be used by getQuantityString. getQuantityString
* only supports integer quantities, not a double quantity like "2.2".
* Gets the plural count to be used by getQuantityString.
* getQuantityString only supports integer quantities, not a double quantity like "2.2".
* <p>
* As a temporary workaround, we convert a double quantity to an integer
* quantity. If the double quantity is exactly 0, 1, or 2, then we can return
* these integer quantities. Otherwise, we cast the double quantity to an
* integer quantity. However, we need to make sure that if the casted value is
* 0, 1, or 2, we don't return those, instead, return the next biggest integer
* 3.
* As a temporary workaround, we convert a double quantity to an integer quantity.
* If the double quantity is exactly 0, 1, or 2, then we can return these integer quantities.
* Otherwise, we cast the double quantity to an integer quantity.
* However, we need to make sure that if the casted value is 0, 1, or 2, we don't return those, instead, return the next biggest integer 3.
*
* @param d the double value
*/
@@ -317,6 +313,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
} else if (d == 2) {
return 2;
} else {
//TODO This seems weird; why not use Math.round(d) or Math.ceil()?
int count = (int) d;
return count < 3 ? 3 : count;
}
@@ -24,6 +24,7 @@ import de.dennisguse.opentracks.services.TrackRecordingService;
* @author Sandor Dornbush
*/
public interface PeriodicTask {
/**
* Sets up this task for subsequent calls to the run method.
*/
@@ -36,9 +36,10 @@ public class PeriodicTaskExecutor {
private final PeriodicTaskFactory periodicTaskFactory;
/**
* The task frequency. A positive value is a time frequency (minutes). A
* negative value is a distance frequency (km or mi). A zero value is to turn
* off periodic task.
* The task frequency.
* A positive value is a time frequency (minutes).
* A negative value is a distance frequency (km or mi).
* A zero value is to turn off periodic task.
*/
private int taskFrequency = PreferencesUtils.FREQUENCY_OFF;
@@ -52,8 +53,7 @@ public class PeriodicTaskExecutor {
// The next distance for the distance periodic task
private double nextTaskDistance = Double.MAX_VALUE;
public PeriodicTaskExecutor(
TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
public PeriodicTaskExecutor(TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
this.trackRecordingService = trackRecordingService;
this.periodicTaskFactory = periodicTaskFactory;
}
@@ -67,11 +67,9 @@ public class PeriodicTaskExecutor {
return;
}
if (!isTimeFrequency()) {
if (timerTaskExecutor != null) {
timerTaskExecutor.shutdown();
timerTaskExecutor = null;
}
if (!isTimeFrequency() && timerTaskExecutor != null) {
timerTaskExecutor.shutdown();
timerTaskExecutor = null;
}
if (taskFrequency == PreferencesUtils.FREQUENCY_OFF) {
Log.d(TAG, "Task frequency is off.");
@@ -119,12 +117,13 @@ public class PeriodicTaskExecutor {
if (!isDistanceFrequency() || periodicTask == null) {
return;
}
TripStatistics tripStatistics = trackRecordingService.getTripStatistics();
if (tripStatistics == null) {
return;
}
double distance = tripStatistics.getTotalDistance()
* UnitConversions.M_TO_KM;
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
if (!metricUnits) {
distance *= UnitConversions.KM_TO_MI;
}
@@ -159,8 +158,7 @@ public class PeriodicTaskExecutor {
* Calculates the next distance for the distance periodic task.
*/
private void calculateNextTaskDistance() {
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()
|| periodicTask == null) {
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused() || periodicTask == null) {
return;
}
@@ -175,11 +173,11 @@ public class PeriodicTaskExecutor {
return;
}
double distance = tripStatistics.getTotalDistance()
* UnitConversions.M_TO_KM;
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
if (!metricUnits) {
distance *= UnitConversions.KM_TO_MI;
}
// The index will be negative since the frequency is negative.
int index = (int) (distance / taskFrequency);
index -= 1;
@@ -16,19 +16,19 @@
package de.dennisguse.opentracks.services.tasks;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.stats.TripStatistics;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.stats.TripStatistics;
/**
* This class will periodically perform a task.
*
* @author Sandor Dornbush
*/
public class TimerTaskExecutor {
class TimerTaskExecutor {
private final PeriodicTask periodicTask;
private final TrackRecordingService trackRecordingService;
@@ -42,12 +42,12 @@ public class TimerTaskExecutor {
}
/**
* Schedules the periodic task at an interval.
* Schedules the periodic task in milliseconds.
*
* @param interval the interval in milliseconds
* @param interval_ms the interval_ms
*/
public void scheduleTask(long interval) {
if (interval <= 0) {
void scheduleTask(long interval_ms) {
if (interval_ms <= 0) {
return;
}
@@ -69,14 +69,11 @@ public class TimerTaskExecutor {
}
};
timer = new Timer(TimerTaskExecutor.class.getSimpleName());
long next = System.currentTimeMillis() + interval - (tripStatistics.getTotalTime() % interval);
timer.scheduleAtFixedRate(timerTask, new Date(next), interval);
long next = System.currentTimeMillis() + interval_ms - (tripStatistics.getTotalTime() % interval_ms);
timer.scheduleAtFixedRate(timerTask, new Date(next), interval_ms);
}
/**
* Shuts down.
*/
public void shutdown() {
void shutdown() {
if (timerTask != null) {
timerTask.cancel();
timerTask = null;