forked from upstream-mirrors/OpenTracks
Refactor location recording logic so that
all location filtering code is done at TripStatisticsBuilder.java.
This commit is contained in:
@@ -380,7 +380,7 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
// first point did not have a time, start stats builder without it
|
// first point did not have a time, start stats builder without it
|
||||||
tripStatisticsBuilder = new TripStatisticsBuilder(0);
|
tripStatisticsBuilder = new TripStatisticsBuilder(0);
|
||||||
}
|
}
|
||||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
tripStatisticsBuilder.addLocation(location, lastSegmentLocation);
|
||||||
|
|
||||||
// insert in db
|
// insert in db
|
||||||
insertPoint(location);
|
insertPoint(location);
|
||||||
|
|||||||
+1
-1
@@ -248,7 +248,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
|
|||||||
|
|
||||||
// Add to the distances and elevations vectors
|
// Add to the distances and elevations vectors
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
if (LocationUtils.isValidLocation(location)) {
|
||||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
tripStatisticsBuilder.addLocation(location, lastLocation);
|
||||||
// All points go into the smoothing buffer
|
// All points go into the smoothing buffer
|
||||||
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
||||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
|
|||||||
|
|
||||||
// Add to the distances and elevations vectors
|
// Add to the distances and elevations vectors
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
if (LocationUtils.isValidLocation(location)) {
|
||||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
tripStatisticsBuilder.addLocation(location, lastLocation);
|
||||||
// All points go into the smoothing buffer
|
// All points go into the smoothing buffer
|
||||||
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
||||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||||
|
|||||||
+84
-188
@@ -25,7 +25,6 @@ import com.google.android.apps.mytracks.content.MyTracksLocation;
|
|||||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
import com.google.android.apps.mytracks.content.Sensor;
|
||||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
||||||
@@ -104,24 +103,11 @@ public class TrackRecordingService extends Service {
|
|||||||
private int minRequiredAccuracy;
|
private int minRequiredAccuracy;
|
||||||
private int autoResumeTrackTimeout;
|
private int autoResumeTrackTimeout;
|
||||||
private long currentRecordingInterval;
|
private long currentRecordingInterval;
|
||||||
private Track recordingTrack;
|
|
||||||
|
|
||||||
// The following variables are set when recording:
|
// The following variables are set when recording:
|
||||||
|
|
||||||
/*
|
|
||||||
* Track length. Calculated from the recorded points to overlay waypoints
|
|
||||||
* precisely on the elevation chart.
|
|
||||||
*/
|
|
||||||
private double length;
|
|
||||||
|
|
||||||
// Used for length calculation
|
|
||||||
private Location lastLengthLocation;
|
|
||||||
|
|
||||||
private TripStatisticsBuilder trackTripStatisticsBuilder;
|
private TripStatisticsBuilder trackTripStatisticsBuilder;
|
||||||
private TripStatisticsBuilder markerTripStatisticsBuilder;
|
private TripStatisticsBuilder markerTripStatisticsBuilder;
|
||||||
private WakeLock wakeLock;
|
private WakeLock wakeLock;
|
||||||
private Location lastLocation;
|
|
||||||
private boolean isMoving;
|
|
||||||
private SensorManager sensorManager;
|
private SensorManager sensorManager;
|
||||||
|
|
||||||
// Timer to periodically invoke checkLocationListener
|
// Timer to periodically invoke checkLocationListener
|
||||||
@@ -195,10 +181,6 @@ public class TrackRecordingService extends Service {
|
|||||||
minRecordingDistance = PreferencesUtils.getInt(context,
|
minRecordingDistance = PreferencesUtils.getInt(context,
|
||||||
R.string.min_recording_distance_key,
|
R.string.min_recording_distance_key,
|
||||||
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
|
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
|
||||||
if (trackTripStatisticsBuilder != null && markerTripStatisticsBuilder != null) {
|
|
||||||
trackTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
markerTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (key == null || PreferencesUtils.getKey(context, R.string.max_recording_distance_key)
|
if (key == null || PreferencesUtils.getKey(context, R.string.max_recording_distance_key)
|
||||||
.equals(key)) {
|
.equals(key)) {
|
||||||
@@ -256,7 +238,6 @@ public class TrackRecordingService extends Service {
|
|||||||
if (isRecording()) {
|
if (isRecording()) {
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
unregisterLocationListener();
|
|
||||||
registerLocationListener();
|
registerLocationListener();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -298,9 +279,9 @@ public class TrackRecordingService extends Service {
|
|||||||
* Try to restart the previous recording track in case the service has been
|
* Try to restart the previous recording track in case the service has been
|
||||||
* restarted by the system, which can sometimes happen.
|
* restarted by the system, which can sometimes happen.
|
||||||
*/
|
*/
|
||||||
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||||
if (recordingTrack != null) {
|
if (track != null) {
|
||||||
restartTrack(recordingTrack);
|
restartTrack(track);
|
||||||
} else {
|
} else {
|
||||||
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
||||||
Log.w(TAG, "recordingTrackId not -1L, but recordingTrack is null. " + recordingTrackId);
|
Log.w(TAG, "recordingTrackId not -1L, but recordingTrack is null. " + recordingTrackId);
|
||||||
@@ -451,11 +432,14 @@ public class TrackRecordingService extends Service {
|
|||||||
isStatistics ? R.string.marker_statistics_icon_url : R.string.marker_waypoint_icon_url);
|
isStatistics ? R.string.marker_statistics_icon_url : R.string.marker_waypoint_icon_url);
|
||||||
int type = isStatistics ? Waypoint.TYPE_STATISTICS : Waypoint.TYPE_WAYPOINT;
|
int type = isStatistics ? Waypoint.TYPE_STATISTICS : Waypoint.TYPE_WAYPOINT;
|
||||||
|
|
||||||
|
double length;
|
||||||
long duration;
|
long duration;
|
||||||
Location location = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
Location location = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
||||||
if (location != null && trackTripStatisticsBuilder != null
|
if (location != null && trackTripStatisticsBuilder != null
|
||||||
&& trackTripStatisticsBuilder.getTripStatistics() != null) {
|
&& trackTripStatisticsBuilder.getTripStatistics() != null) {
|
||||||
duration = location.getTime() - trackTripStatisticsBuilder.getTripStatistics().getStartTime();
|
TripStatistics trackTripStatistics = trackTripStatisticsBuilder.getTripStatistics();
|
||||||
|
length = trackTripStatistics.getTotalDistance();
|
||||||
|
duration = location.getTime() - trackTripStatistics.getStartTime();
|
||||||
} else {
|
} else {
|
||||||
if (!waypointCreationRequest.isTrackStatistics()) {
|
if (!waypointCreationRequest.isTrackStatistics()) {
|
||||||
return -1L;
|
return -1L;
|
||||||
@@ -464,6 +448,7 @@ public class TrackRecordingService extends Service {
|
|||||||
location = new Location("");
|
location = new Location("");
|
||||||
location.setLatitude(100);
|
location.setLatitude(100);
|
||||||
location.setLongitude(180);
|
location.setLongitude(180);
|
||||||
|
length = 0;
|
||||||
duration = 0;
|
duration = 0;
|
||||||
}
|
}
|
||||||
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, type,
|
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, type,
|
||||||
@@ -499,7 +484,7 @@ public class TrackRecordingService extends Service {
|
|||||||
private void handleStartCommand(Intent intent, int startId) {
|
private void handleStartCommand(Intent intent, int startId) {
|
||||||
// Check if the service is called to resume track (from phone reboot)
|
// Check if the service is called to resume track (from phone reboot)
|
||||||
if (intent != null && intent.getBooleanExtra(RESUME_TRACK_EXTRA_NAME, false)) {
|
if (intent != null && intent.getBooleanExtra(RESUME_TRACK_EXTRA_NAME, false)) {
|
||||||
if (!shouldResumeTrack(recordingTrack)) {
|
if (!shouldResumeTrack(myTracksProviderUtils.getTrack(recordingTrackId))) {
|
||||||
Log.i(TAG, "Stop resume track.");
|
Log.i(TAG, "Stop resume track.");
|
||||||
stopRecording();
|
stopRecording();
|
||||||
stopSelfResult(startId);
|
stopSelfResult(startId);
|
||||||
@@ -554,12 +539,8 @@ public class TrackRecordingService extends Service {
|
|||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
length = 0;
|
|
||||||
lastLengthLocation = null;
|
|
||||||
trackTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
trackTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
||||||
trackTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
markerTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
markerTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
||||||
markerTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
|
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
track.setStartId(-1L);
|
track.setStartId(-1L);
|
||||||
@@ -591,11 +572,8 @@ public class TrackRecordingService extends Service {
|
|||||||
private void restartTrack(Track track) {
|
private void restartTrack(Track track) {
|
||||||
Log.d(TAG, "Restarting track: " + track.getId());
|
Log.d(TAG, "Restarting track: " + track.getId());
|
||||||
|
|
||||||
length = 0;
|
|
||||||
lastLengthLocation = null;
|
|
||||||
TripStatistics tripStatistics = track.getTripStatistics();
|
TripStatistics tripStatistics = track.getTripStatistics();
|
||||||
trackTripStatisticsBuilder = new TripStatisticsBuilder(tripStatistics.getStartTime());
|
trackTripStatisticsBuilder = new TripStatisticsBuilder(tripStatistics.getStartTime());
|
||||||
trackTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
|
|
||||||
long markerStartTime;
|
long markerStartTime;
|
||||||
Waypoint waypoint = myTracksProviderUtils.getLastStatisticsWaypoint(recordingTrackId);
|
Waypoint waypoint = myTracksProviderUtils.getLastStatisticsWaypoint(recordingTrackId);
|
||||||
@@ -605,7 +583,6 @@ public class TrackRecordingService extends Service {
|
|||||||
markerStartTime = tripStatistics.getStartTime();
|
markerStartTime = tripStatistics.getStartTime();
|
||||||
}
|
}
|
||||||
markerTripStatisticsBuilder = new TripStatisticsBuilder(markerStartTime);
|
markerTripStatisticsBuilder = new TripStatisticsBuilder(markerStartTime);
|
||||||
markerTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
|
||||||
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
@@ -615,22 +592,22 @@ public class TrackRecordingService extends Service {
|
|||||||
Log.e(TAG, "Cursor is null.");
|
Log.e(TAG, "Cursor is null.");
|
||||||
} else {
|
} else {
|
||||||
if (cursor.moveToLast()) {
|
if (cursor.moveToLast()) {
|
||||||
|
Location lastValidTripLocation = null;
|
||||||
|
Location lastValidMarkerLocation = null;
|
||||||
do {
|
do {
|
||||||
Location location = myTracksProviderUtils.createLocation(cursor);
|
Location location = myTracksProviderUtils.createLocation(cursor);
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
if (LocationUtils.isValidLocation(location)) {
|
||||||
trackTripStatisticsBuilder.addLocation(location, location.getTime());
|
trackTripStatisticsBuilder.addLocation(
|
||||||
|
location, lastValidTripLocation, location.getTime(), false, minRecordingDistance);
|
||||||
|
lastValidTripLocation = location;
|
||||||
if (location.getTime() > markerStartTime) {
|
if (location.getTime() > markerStartTime) {
|
||||||
markerTripStatisticsBuilder.addLocation(location, location.getTime());
|
markerTripStatisticsBuilder.addLocation(
|
||||||
|
location, lastValidMarkerLocation, location.getTime(), false, minRecordingDistance);
|
||||||
|
lastValidMarkerLocation = location;
|
||||||
}
|
}
|
||||||
if (lastLengthLocation != null) {
|
|
||||||
length += location.distanceTo(lastLengthLocation);
|
|
||||||
}
|
|
||||||
lastLengthLocation = location;
|
|
||||||
}
|
}
|
||||||
} while (cursor.moveToPrevious());
|
} while (cursor.moveToPrevious());
|
||||||
}
|
}
|
||||||
trackTripStatisticsBuilder.pauseAt(tripStatistics.getStopTime());
|
|
||||||
trackTripStatisticsBuilder.resumeAt(System.currentTimeMillis());
|
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(TAG, "RuntimeException", e);
|
Log.e(TAG, "RuntimeException", e);
|
||||||
@@ -647,11 +624,7 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
private void startRecording() {
|
private void startRecording() {
|
||||||
acquireWakeLock();
|
acquireWakeLock();
|
||||||
|
|
||||||
lastLocation = null;
|
|
||||||
isMoving = true;
|
|
||||||
sensorManager = SensorManagerFactory.getSystemSensorManager(this);
|
sensorManager = SensorManagerFactory.getSystemSensorManager(this);
|
||||||
|
|
||||||
showNotification();
|
showNotification();
|
||||||
sendTrackBroadcast(R.string.track_started_broadcast_action, recordingTrackId);
|
sendTrackBroadcast(R.string.track_started_broadcast_action, recordingTrackId);
|
||||||
announcementExecutor.restore();
|
announcementExecutor.restore();
|
||||||
@@ -668,19 +641,16 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
announcementExecutor.shutdown();
|
announcementExecutor.shutdown();
|
||||||
splitExecutor.shutdown();
|
splitExecutor.shutdown();
|
||||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
|
||||||
if (track != null) {
|
|
||||||
long lastLocationId = myTracksProviderUtils.getLastTrackLocationId(recordingTrackId);
|
|
||||||
if (lastLocationId >= 0 && track.getStopId() >= 0) {
|
|
||||||
track.setStopId(lastLocationId);
|
|
||||||
}
|
|
||||||
updateTripStatisticsToTime(track.getTripStatistics(), System.currentTimeMillis());
|
|
||||||
myTracksProviderUtils.updateTrack(track);
|
|
||||||
}
|
|
||||||
// Need to remember the trackId before calling stopRecording
|
// Need to remember the trackId before calling stopRecording
|
||||||
long trackId = recordingTrackId;
|
long trackId = recordingTrackId;
|
||||||
stopRecording();
|
stopRecording();
|
||||||
|
|
||||||
|
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||||
|
if (track != null) {
|
||||||
|
updateTrack(track, myTracksProviderUtils.getLastTrackLocationId(recordingTrackId), false);
|
||||||
|
}
|
||||||
|
|
||||||
if (sensorManager != null) {
|
if (sensorManager != null) {
|
||||||
SensorManagerFactory.releaseSystemSensorManager();
|
SensorManagerFactory.releaseSystemSensorManager();
|
||||||
sensorManager = null;
|
sensorManager = null;
|
||||||
@@ -701,14 +671,27 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a {@link TripStatistics} to a time.
|
* Update track.
|
||||||
*
|
*
|
||||||
* @param tripStatistics the trip statistics
|
* @param track the track
|
||||||
* @param time the time
|
* @param lastTrackPointId the last track point id
|
||||||
|
* @param isLastTrackPointNew true if the last track point id is new
|
||||||
*/
|
*/
|
||||||
private void updateTripStatisticsToTime(TripStatistics tripStatistics, long time) {
|
private void updateTrack(Track track, long lastTrackPointId, boolean isLastTrackPointNew) {
|
||||||
tripStatistics.setStopTime(time);
|
if (lastTrackPointId >= 0) {
|
||||||
tripStatistics.setTotalTime(time - tripStatistics.getStartTime());
|
if (track.getStartId() < 0) {
|
||||||
|
track.setStartId(lastTrackPointId);
|
||||||
|
}
|
||||||
|
track.setStopId(lastTrackPointId);
|
||||||
|
if (isLastTrackPointNew) {
|
||||||
|
track.setNumberOfPoints(track.getNumberOfPoints() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isLastTrackPointNew) {
|
||||||
|
trackTripStatisticsBuilder.pauseAt(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
track.setTripStatistics(trackTripStatisticsBuilder.getTripStatistics());
|
||||||
|
myTracksProviderUtils.updateTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -718,13 +701,13 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
private void onLocationChangedAsync(Location location) {
|
private void onLocationChangedAsync(Location location) {
|
||||||
try {
|
try {
|
||||||
if (location == null) {
|
if (!isRecording()) {
|
||||||
Log.w(TAG, "Ignore onLocationChangedAsync. location is null.");
|
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRecording()) {
|
if (!LocationUtils.isValidLocation(location)) {
|
||||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
Log.w(TAG, "Ignore onLocationChangedAsync. Not valid location.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,73 +716,59 @@ public class TrackRecordingService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||||
if (recordingTrack == null) {
|
if (track == null) {
|
||||||
Log.d(TAG, "Ignore onLocationChangedAsync. recodingTrack is null.");
|
Log.d(TAG, "Ignore onLocationChangedAsync. recodingTrack is null.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
locationListenerPolicy.updateIdleTime(trackTripStatisticsBuilder.getIdleTime());
|
Location lastLocation = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
||||||
|
if (!LocationUtils.isValidLocation(lastLocation)) {
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
lastLocation = null;
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
trackTripStatisticsBuilder.addLocation(location, now);
|
|
||||||
markerTripStatisticsBuilder.addLocation(location, now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update location listener policy
|
||||||
|
locationListenerPolicy.updateIdleTime(
|
||||||
|
lastLocation != null ? location.getTime() - lastLocation.getTime() : 0L);
|
||||||
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
|
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
|
||||||
registerLocationListener();
|
registerLocationListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
Location lastRecordedLocation = myTracksProviderUtils.getLastLocation();
|
|
||||||
double distanceToLastRecordedLocation = lastRecordedLocation != null ? location.distanceTo(
|
|
||||||
lastRecordedLocation)
|
|
||||||
: Double.POSITIVE_INFINITY;
|
|
||||||
double distanceToLastLocation = lastLocation != null ? location.distanceTo(lastLocation)
|
|
||||||
: Double.POSITIVE_INFINITY;
|
|
||||||
boolean hasSensorData = sensorManager != null && sensorManager.isEnabled()
|
boolean hasSensorData = sensorManager != null && sensorManager.isEnabled()
|
||||||
&& sensorManager.getSensorDataSet() != null && sensorManager.isSensorDataSetValid();
|
&& sensorManager.getSensorDataSet() != null && sensorManager.isSensorDataSetValid();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
// If stationary for two locations, make sure the first one is recorded
|
markerTripStatisticsBuilder.addLocation(location, lastLocation, now, hasSensorData, minRecordingDistance);
|
||||||
if (distanceToLastLocation == 0 && !hasSensorData) {
|
if (trackTripStatisticsBuilder.addLocation(
|
||||||
if (isMoving) {
|
location, lastLocation, now, hasSensorData, minRecordingDistance)) {
|
||||||
isMoving = false;
|
try {
|
||||||
if (lastLocation != null && !lastLocation.equals(lastRecordedLocation)) {
|
if (lastLocation != null && location.distanceTo(lastLocation)
|
||||||
if (!insertLocation(lastLocation, lastRecordedLocation, recordingTrackId)) {
|
> maxRecordingDistance) {
|
||||||
return;
|
Log.d(TAG, "Inserting a separator track point.");
|
||||||
}
|
Location separator = new Location(LocationManager.GPS_PROVIDER);
|
||||||
|
separator.setLongitude(0);
|
||||||
|
separator.setLatitude(100);
|
||||||
|
separator.setTime(lastLocation.getTime());
|
||||||
|
myTracksProviderUtils.insertTrackPoint(separator, recordingTrackId);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
lastLocation = location;
|
if (hasSensorData) {
|
||||||
} else if (distanceToLastRecordedLocation >= minRecordingDistance || hasSensorData) {
|
location = new MyTracksLocation(location, sensorManager.getSensorDataSet());
|
||||||
if (!isMoving) {
|
|
||||||
isMoving = true;
|
|
||||||
// Make sure the lastLocation is added.
|
|
||||||
if (lastLocation != null && !lastLocation.equals(lastRecordedLocation)) {
|
|
||||||
if (!insertLocation(lastLocation, lastRecordedLocation, recordingTrackId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
Uri uri = myTracksProviderUtils.insertTrackPoint(location, recordingTrackId);
|
||||||
|
int trackPointId = Integer.parseInt(uri.getLastPathSegment());
|
||||||
boolean startNewSegment = LocationUtils.isValidLocation(lastRecordedLocation)
|
|
||||||
&& distanceToLastRecordedLocation > maxRecordingDistance
|
updateTrack(track, trackPointId, true);
|
||||||
&& recordingTrack.getStartId() >= 0;
|
} catch (SQLiteException e) {
|
||||||
if (startNewSegment) {
|
/*
|
||||||
Log.d(TAG, "Inserting a separator track point.");
|
* Insert failed, most likely because of SqlLite error code 5
|
||||||
Location separator = new Location(LocationManager.GPS_PROVIDER);
|
* (SQLite_BUSY). This is expected to happen extremely rarely (if our
|
||||||
separator.setLongitude(0);
|
* listener gets invoked twice at about the same time).
|
||||||
separator.setLatitude(100);
|
*/
|
||||||
separator.setTime(lastRecordedLocation.getTime());
|
Log.w(TAG, "SQLiteException", e);
|
||||||
myTracksProviderUtils.insertTrackPoint(separator, recordingTrackId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!insertLocation(location, lastRecordedLocation, recordingTrackId)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastLocation = location;
|
announcementExecutor.update();
|
||||||
} else {
|
splitExecutor.update();
|
||||||
Log.d(TAG, "Ignore location. distanceToLastRecordedLocation < minRecordingDistance.");
|
|
||||||
}
|
}
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
Log.e(TAG, "Error in onLocationChangedAsync", e);
|
Log.e(TAG, "Error in onLocationChangedAsync", e);
|
||||||
@@ -810,84 +779,11 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a new location in the track points db and updates the corresponding
|
|
||||||
* track in the track db.
|
|
||||||
*
|
|
||||||
* @param location the location to be inserted
|
|
||||||
* @param lastRecordedLocation the last recorded location before this one (or
|
|
||||||
* null if none)
|
|
||||||
* @param trackId the id of the track
|
|
||||||
* @return true if successful. False if SQLite3 threw an exception.
|
|
||||||
*/
|
|
||||||
private boolean insertLocation(Location location, Location lastRecordedLocation, long trackId) {
|
|
||||||
|
|
||||||
// Keep track of length along recorded track
|
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
|
||||||
if (lastLengthLocation != null) {
|
|
||||||
length += location.distanceTo(lastLengthLocation);
|
|
||||||
}
|
|
||||||
lastLengthLocation = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Location locationToInsert = location;
|
|
||||||
if (sensorManager != null && sensorManager.isEnabled()) {
|
|
||||||
SensorDataSet sensorDataSet = sensorManager.getSensorDataSet();
|
|
||||||
if (sensorDataSet != null && sensorManager.isSensorDataSetValid()) {
|
|
||||||
locationToInsert = new MyTracksLocation(location, sensorDataSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Uri uri = myTracksProviderUtils.insertTrackPoint(locationToInsert, trackId);
|
|
||||||
int pointId = Integer.parseInt(uri.getLastPathSegment());
|
|
||||||
|
|
||||||
// Update the current track
|
|
||||||
if (lastRecordedLocation != null && lastRecordedLocation.getLatitude() <= 90) {
|
|
||||||
if (recordingTrack.getStartId() < 0) {
|
|
||||||
recordingTrack.setStartId(pointId);
|
|
||||||
}
|
|
||||||
recordingTrack.setStopId(pointId);
|
|
||||||
recordingTrack.setNumberOfPoints(recordingTrack.getNumberOfPoints() + 1);
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
TripStatistics tripStatistics = trackTripStatisticsBuilder.getTripStatistics();
|
|
||||||
updateTripStatisticsToTime(tripStatistics, now);
|
|
||||||
recordingTrack.setTripStatistics(tripStatistics);
|
|
||||||
|
|
||||||
myTracksProviderUtils.updateTrack(recordingTrack);
|
|
||||||
|
|
||||||
// Update the first waypoint
|
|
||||||
Waypoint waypoint = myTracksProviderUtils.getFirstWaypoint(recordingTrackId);
|
|
||||||
if (waypoint != null) {
|
|
||||||
TripStatistics stats = trackTripStatisticsBuilder.getTripStatistics();
|
|
||||||
waypoint.setLength(length);
|
|
||||||
waypoint.setDuration(now - stats.getStartTime());
|
|
||||||
waypoint.setTripStatistics(stats);
|
|
||||||
myTracksProviderUtils.updateWaypoint(waypoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
/*
|
|
||||||
* Insert failed, most likely because of SqlLite error code 5
|
|
||||||
* (SQLite_BUSY). This is expected to happen extremely rarely (if our
|
|
||||||
* listener gets invoked twice at about the same time).
|
|
||||||
*/
|
|
||||||
Log.w(TAG, "SQLiteException", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
announcementExecutor.update();
|
|
||||||
splitExecutor.update();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the location listener.
|
* Registers the location listener.
|
||||||
*/
|
*/
|
||||||
private void registerLocationListener() {
|
private void registerLocationListener() {
|
||||||
if (locationManager == null) {
|
unregisterLocationListener();
|
||||||
Log.e(TAG, "locationManager is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
long interval = locationListenerPolicy.getDesiredPollingInterval();
|
long interval = locationListenerPolicy.getDesiredPollingInterval();
|
||||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval,
|
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval,
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ import android.location.Location;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for {@link TripStatistics}. For keeping statistics as a track is
|
* Builder for {@link TripStatistics}. For keeping track statistics as new
|
||||||
* paused/resumed and new locations are added.
|
* locations are added.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
@@ -37,18 +37,6 @@ public class TripStatisticsBuilder {
|
|||||||
// The trip statistics.
|
// The trip statistics.
|
||||||
private final TripStatistics tripStatistics;
|
private final TripStatistics tripStatistics;
|
||||||
|
|
||||||
// The minimum recording distance.
|
|
||||||
private int minRecordingDistance = PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT;
|
|
||||||
|
|
||||||
// True if the trip is paused. All trips start as paused.
|
|
||||||
private boolean paused = true;
|
|
||||||
|
|
||||||
// The last location as reported by GPS.
|
|
||||||
private Location lastLocation;
|
|
||||||
|
|
||||||
// The last moving location that contributed to the moving statistics.
|
|
||||||
private Location lastMovingLocation;
|
|
||||||
|
|
||||||
// A buffer of the recent speed readings (m/s) for calculating max speed.
|
// A buffer of the recent speed readings (m/s) for calculating max speed.
|
||||||
private final DoubleBuffer speedBuffer = new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
|
private final DoubleBuffer speedBuffer = new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
|
||||||
|
|
||||||
@@ -63,97 +51,42 @@ public class TripStatisticsBuilder {
|
|||||||
private final DoubleBuffer gradeBuffer = new DoubleBuffer(Constants.GRADE_SMOOTHING_FACTOR);
|
private final DoubleBuffer gradeBuffer = new DoubleBuffer(Constants.GRADE_SMOOTHING_FACTOR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new trip starting at a start time.
|
* Creates a new {@link TripStatistics} starting at a start time.
|
||||||
*
|
*
|
||||||
* @param startTime the start time
|
* @param startTime the start time
|
||||||
*/
|
*/
|
||||||
public TripStatisticsBuilder(long startTime) {
|
public TripStatisticsBuilder(long startTime) {
|
||||||
tripStatistics = new TripStatistics();
|
tripStatistics = new TripStatistics();
|
||||||
resumeAt(startTime);
|
tripStatistics.setStartTime(startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new trip, starting with an existing {@link TripStatistics}.
|
* Pauses the {@link TripStatistics} at a stop time.
|
||||||
*
|
*
|
||||||
* @param other the existing {@link TripStatistics}
|
* @param stopTime the stop time
|
||||||
*/
|
*/
|
||||||
public TripStatisticsBuilder(TripStatistics other) {
|
public void pauseAt(long stopTime) {
|
||||||
tripStatistics = new TripStatistics(other);
|
tripStatistics.setStopTime(stopTime);
|
||||||
if (tripStatistics.getStartTime() > 0) {
|
tripStatistics.setTotalTime(stopTime - tripStatistics.getStartTime());
|
||||||
resumeAt(tripStatistics.getStartTime());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the min recording distance.
|
* Gets the {@link TripStatistics}.
|
||||||
*
|
|
||||||
* @param minRecordingDistance the min recording distance
|
|
||||||
*/
|
|
||||||
public void setMinRecordingDistance(int minRecordingDistance) {
|
|
||||||
this.minRecordingDistance = minRecordingDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resumes the current track at a given time.
|
|
||||||
*
|
|
||||||
* @param time the time
|
|
||||||
*/
|
|
||||||
public void resumeAt(long time) {
|
|
||||||
if (!paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tripStatistics.setStartTime(time);
|
|
||||||
tripStatistics.setStopTime(-1L);
|
|
||||||
paused = false;
|
|
||||||
lastLocation = null;
|
|
||||||
lastMovingLocation = null;
|
|
||||||
speedBuffer.reset();
|
|
||||||
elevationBuffer.reset();
|
|
||||||
distanceBuffer.reset();
|
|
||||||
gradeBuffer.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pauses the track at a given time.
|
|
||||||
*
|
|
||||||
* @param time the time to pause at
|
|
||||||
*/
|
|
||||||
public void pauseAt(long time) {
|
|
||||||
if (paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tripStatistics.setStopTime(time);
|
|
||||||
// TODO: total time needs to take into account pauses
|
|
||||||
tripStatistics.setTotalTime(time - tripStatistics.getStartTime());
|
|
||||||
paused = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the trip statistics.
|
|
||||||
*/
|
*/
|
||||||
public TripStatistics getTripStatistics() {
|
public TripStatistics getTripStatistics() {
|
||||||
// Take a snapshot - we don't want anyone messing with our internals
|
// Take a snapshot - we don't want anyone messing with our tripStatistics
|
||||||
return new TripStatistics(tripStatistics);
|
return new TripStatistics(tripStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the amount of time the user has been idle or 0 if he is moving.
|
* Adds a location.
|
||||||
|
*
|
||||||
|
* @param location the location
|
||||||
|
* @param lastLocation the last location
|
||||||
*/
|
*/
|
||||||
public long getIdleTime() {
|
public void addLocation(Location location, Location lastLocation) {
|
||||||
if (lastLocation == null || lastMovingLocation == null) {
|
addLocation(location, lastLocation, location.getTime(), false,
|
||||||
return 0;
|
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
|
||||||
}
|
|
||||||
return lastLocation.getTime() - lastMovingLocation.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the smoothed elevation over several readings. The elevation readings
|
|
||||||
* is noisy so the smoothed elevation is better than the raw elevation for
|
|
||||||
* many tasks.
|
|
||||||
*/
|
|
||||||
public double getSmoothedElevation() {
|
|
||||||
return elevationBuffer.getAverage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,53 +94,54 @@ public class TripStatisticsBuilder {
|
|||||||
* new location.
|
* new location.
|
||||||
*
|
*
|
||||||
* @param location the location
|
* @param location the location
|
||||||
* @param systemTime the system time for calculating totalTime. This should be
|
* @param lastLocation the last location
|
||||||
* the phone's system time (not GPS time)
|
* @param time the time
|
||||||
* @return true if the person is moving
|
* @param alwaysAdd true to always return true
|
||||||
|
* @param minRecordingDistance the min recording distance
|
||||||
|
* @return true if the location should be added
|
||||||
*/
|
*/
|
||||||
public boolean addLocation(Location location, long systemTime) {
|
public boolean addLocation(Location location, Location lastLocation, long time, boolean alwaysAdd,
|
||||||
if (paused) {
|
int minRecordingDistance) {
|
||||||
Log.w(TAG, "Track is paused. Ignore addLocation.");
|
pauseAt(time);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tripStatistics.setTotalTime(systemTime - tripStatistics.getStartTime());
|
|
||||||
|
|
||||||
double elevationDifference = updateElevation(location.getAltitude());
|
double elevationDifference = updateElevation(location.getAltitude());
|
||||||
tripStatistics.updateLatitudeExtremities(location.getLatitude());
|
tripStatistics.updateLatitudeExtremities(location.getLatitude());
|
||||||
tripStatistics.updateLongitudeExtremities(location.getLongitude());
|
tripStatistics.updateLongitudeExtremities(location.getLongitude());
|
||||||
|
|
||||||
// If this is the first location, remember it and return.
|
// If lastLocation is null, returns true.
|
||||||
if (lastLocation == null || lastMovingLocation == null) {
|
if (lastLocation == null) {
|
||||||
lastLocation = location;
|
return true;
|
||||||
lastMovingLocation = location;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't do anything more if we didn't move since the last location.
|
|
||||||
double distance = lastLocation.distanceTo(location);
|
double distance = lastLocation.distanceTo(location);
|
||||||
if (distance < minRecordingDistance && location.getSpeed() < Constants.MAX_NO_MOVEMENT_SPEED) {
|
if (distance < minRecordingDistance && location.getSpeed() < Constants.MAX_NO_MOVEMENT_SPEED) {
|
||||||
lastLocation = location;
|
return alwaysAdd;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long timeDifference = location.getTime() - lastLocation.getTime();
|
long movingTime = location.getTime() - lastLocation.getTime();
|
||||||
if (timeDifference < 0) {
|
if (movingTime < 0) {
|
||||||
Log.e(TAG, "Negative time difference: " + timeDifference);
|
Log.e(TAG, "Negative moving time: " + movingTime);
|
||||||
lastLocation = location;
|
return alwaysAdd;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tripStatistics.addTotalDistance(lastMovingLocation.distanceTo(location));
|
tripStatistics.addTotalDistance(distance);
|
||||||
tripStatistics.addMovingTime(timeDifference);
|
tripStatistics.addMovingTime(movingTime);
|
||||||
updateSpeed(
|
updateSpeed(
|
||||||
location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed());
|
location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed());
|
||||||
updateGrade(distance, elevationDifference);
|
updateGrade(distance, elevationDifference);
|
||||||
lastLocation = location;
|
|
||||||
lastMovingLocation = location;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the smoothed elevation over several readings. The elevation readings
|
||||||
|
* is noisy so the smoothed elevation is better than the raw elevation for
|
||||||
|
* many tasks.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
double getSmoothedElevation() {
|
||||||
|
return elevationBuffer.getAverage();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a speed reading. Assumes the user is moving.
|
* Updates a speed reading. Assumes the user is moving.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ import java.util.ArrayList;
|
|||||||
*/
|
*/
|
||||||
public class Track implements Parcelable {
|
public class Track implements Parcelable {
|
||||||
|
|
||||||
private long id = -1;
|
private long id = -1L;
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private String description = "";
|
private String description = "";
|
||||||
private String category = "";
|
private String category = "";
|
||||||
private long startId = -1;
|
private long startId = -1L;
|
||||||
private long stopId = -1;
|
private long stopId = -1L;
|
||||||
|
|
||||||
// The number of location points (present even if the points themselves are
|
// The number of location points (present even if the points themselves are
|
||||||
// not loaded)
|
// not loaded)
|
||||||
|
|||||||
+3
-2
@@ -36,6 +36,7 @@ public class TripStatisticsBuilderTest extends TestCase {
|
|||||||
assertEquals(0.0, tripStatistics.getTotalElevationGain());
|
assertEquals(0.0, tripStatistics.getTotalElevationGain());
|
||||||
assertEquals(0, tripStatistics.getMovingTime());
|
assertEquals(0, tripStatistics.getMovingTime());
|
||||||
assertEquals(0.0, tripStatistics.getTotalDistance());
|
assertEquals(0.0, tripStatistics.getTotalDistance());
|
||||||
|
Location lastLocation = null;
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
Location location = new Location("test");
|
Location location = new Location("test");
|
||||||
location.setAccuracy(1.0f);
|
location.setAccuracy(1.0f);
|
||||||
@@ -48,8 +49,7 @@ public class TripStatisticsBuilderTest extends TestCase {
|
|||||||
// Each time slice is 10 seconds.
|
// Each time slice is 10 seconds.
|
||||||
long time = 1000 + 10000 * i;
|
long time = 1000 + 10000 * i;
|
||||||
location.setTime(time);
|
location.setTime(time);
|
||||||
boolean moving = builder.addLocation(location, time);
|
builder.addLocation(location, lastLocation);
|
||||||
assertEquals((i != 0), moving);
|
|
||||||
|
|
||||||
tripStatistics = builder.getTripStatistics();
|
tripStatistics = builder.getTripStatistics();
|
||||||
assertEquals(10000 * i, tripStatistics.getTotalTime());
|
assertEquals(10000 * i, tripStatistics.getTotalTime());
|
||||||
@@ -68,6 +68,7 @@ public class TripStatisticsBuilderTest extends TestCase {
|
|||||||
assertEquals(0.009, tripStatistics.getMaxGrade(), 0.0001);
|
assertEquals(0.009, tripStatistics.getMaxGrade(), 0.0001);
|
||||||
}
|
}
|
||||||
assertEquals(111.0 * i, tripStatistics.getTotalDistance(), 100);
|
assertEquals(111.0 * i, tripStatistics.getTotalDistance(), 100);
|
||||||
|
lastLocation = location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user