forked from upstream-mirrors/OpenTracks
revert f505ce7c6bde
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
|
||||
tripStatisticsBuilder = new TripStatisticsBuilder(0);
|
||||
}
|
||||
tripStatisticsBuilder.addLocation(location, lastSegmentLocation);
|
||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||
|
||||
// insert in db
|
||||
insertPoint(location);
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
|
||||
|
||||
// Add to the distances and elevations vectors
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
tripStatisticsBuilder.addLocation(location, lastLocation);
|
||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||
// All points go into the smoothing buffer
|
||||
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||
|
||||
@@ -292,7 +292,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
|
||||
|
||||
// Add to the distances and elevations vectors
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
tripStatisticsBuilder.addLocation(location, lastLocation);
|
||||
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||
// All points go into the smoothing buffer
|
||||
elevationBuffer.setNext(metricUnits ? location.getAltitude()
|
||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||
|
||||
+188
-84
@@ -25,6 +25,7 @@ import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
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.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
||||
@@ -103,11 +104,24 @@ public class TrackRecordingService extends Service {
|
||||
private int minRequiredAccuracy;
|
||||
private int autoResumeTrackTimeout;
|
||||
private long currentRecordingInterval;
|
||||
private Track recordingTrack;
|
||||
|
||||
// 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 markerTripStatisticsBuilder;
|
||||
private WakeLock wakeLock;
|
||||
private Location lastLocation;
|
||||
private boolean isMoving;
|
||||
private SensorManager sensorManager;
|
||||
|
||||
// Timer to periodically invoke checkLocationListener
|
||||
@@ -181,6 +195,10 @@ public class TrackRecordingService extends Service {
|
||||
minRecordingDistance = PreferencesUtils.getInt(context,
|
||||
R.string.min_recording_distance_key,
|
||||
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)
|
||||
.equals(key)) {
|
||||
@@ -238,6 +256,7 @@ public class TrackRecordingService extends Service {
|
||||
if (isRecording()) {
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
unregisterLocationListener();
|
||||
registerLocationListener();
|
||||
}
|
||||
});
|
||||
@@ -279,9 +298,9 @@ public class TrackRecordingService extends Service {
|
||||
* Try to restart the previous recording track in case the service has been
|
||||
* restarted by the system, which can sometimes happen.
|
||||
*/
|
||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||
if (track != null) {
|
||||
restartTrack(track);
|
||||
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||
if (recordingTrack != null) {
|
||||
restartTrack(recordingTrack);
|
||||
} else {
|
||||
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
||||
Log.w(TAG, "recordingTrackId not -1L, but recordingTrack is null. " + recordingTrackId);
|
||||
@@ -432,14 +451,11 @@ public class TrackRecordingService extends Service {
|
||||
isStatistics ? R.string.marker_statistics_icon_url : R.string.marker_waypoint_icon_url);
|
||||
int type = isStatistics ? Waypoint.TYPE_STATISTICS : Waypoint.TYPE_WAYPOINT;
|
||||
|
||||
double length;
|
||||
long duration;
|
||||
Location location = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
||||
if (location != null && trackTripStatisticsBuilder != null
|
||||
&& trackTripStatisticsBuilder.getTripStatistics() != null) {
|
||||
TripStatistics trackTripStatistics = trackTripStatisticsBuilder.getTripStatistics();
|
||||
length = trackTripStatistics.getTotalDistance();
|
||||
duration = location.getTime() - trackTripStatistics.getStartTime();
|
||||
duration = location.getTime() - trackTripStatisticsBuilder.getTripStatistics().getStartTime();
|
||||
} else {
|
||||
if (!waypointCreationRequest.isTrackStatistics()) {
|
||||
return -1L;
|
||||
@@ -448,7 +464,6 @@ public class TrackRecordingService extends Service {
|
||||
location = new Location("");
|
||||
location.setLatitude(100);
|
||||
location.setLongitude(180);
|
||||
length = 0;
|
||||
duration = 0;
|
||||
}
|
||||
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, type,
|
||||
@@ -484,7 +499,7 @@ public class TrackRecordingService extends Service {
|
||||
private void handleStartCommand(Intent intent, int startId) {
|
||||
// Check if the service is called to resume track (from phone reboot)
|
||||
if (intent != null && intent.getBooleanExtra(RESUME_TRACK_EXTRA_NAME, false)) {
|
||||
if (!shouldResumeTrack(myTracksProviderUtils.getTrack(recordingTrackId))) {
|
||||
if (!shouldResumeTrack(recordingTrack)) {
|
||||
Log.i(TAG, "Stop resume track.");
|
||||
stopRecording();
|
||||
stopSelfResult(startId);
|
||||
@@ -539,8 +554,12 @@ public class TrackRecordingService extends Service {
|
||||
return -1L;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
length = 0;
|
||||
lastLengthLocation = null;
|
||||
trackTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
||||
trackTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
||||
markerTripStatisticsBuilder = new TripStatisticsBuilder(now);
|
||||
markerTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
||||
|
||||
Track track = new Track();
|
||||
track.setStartId(-1L);
|
||||
@@ -572,8 +591,11 @@ public class TrackRecordingService extends Service {
|
||||
private void restartTrack(Track track) {
|
||||
Log.d(TAG, "Restarting track: " + track.getId());
|
||||
|
||||
length = 0;
|
||||
lastLengthLocation = null;
|
||||
TripStatistics tripStatistics = track.getTripStatistics();
|
||||
trackTripStatisticsBuilder = new TripStatisticsBuilder(tripStatistics.getStartTime());
|
||||
trackTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
||||
|
||||
long markerStartTime;
|
||||
Waypoint waypoint = myTracksProviderUtils.getLastStatisticsWaypoint(recordingTrackId);
|
||||
@@ -583,6 +605,7 @@ public class TrackRecordingService extends Service {
|
||||
markerStartTime = tripStatistics.getStartTime();
|
||||
}
|
||||
markerTripStatisticsBuilder = new TripStatisticsBuilder(markerStartTime);
|
||||
markerTripStatisticsBuilder.setMinRecordingDistance(minRecordingDistance);
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
@@ -592,22 +615,22 @@ public class TrackRecordingService extends Service {
|
||||
Log.e(TAG, "Cursor is null.");
|
||||
} else {
|
||||
if (cursor.moveToLast()) {
|
||||
Location lastValidTripLocation = null;
|
||||
Location lastValidMarkerLocation = null;
|
||||
do {
|
||||
Location location = myTracksProviderUtils.createLocation(cursor);
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
trackTripStatisticsBuilder.addLocation(
|
||||
location, lastValidTripLocation, location.getTime(), false, minRecordingDistance);
|
||||
lastValidTripLocation = location;
|
||||
trackTripStatisticsBuilder.addLocation(location, location.getTime());
|
||||
if (location.getTime() > markerStartTime) {
|
||||
markerTripStatisticsBuilder.addLocation(
|
||||
location, lastValidMarkerLocation, location.getTime(), false, minRecordingDistance);
|
||||
lastValidMarkerLocation = location;
|
||||
markerTripStatisticsBuilder.addLocation(location, location.getTime());
|
||||
}
|
||||
if (lastLengthLocation != null) {
|
||||
length += location.distanceTo(lastLengthLocation);
|
||||
}
|
||||
lastLengthLocation = location;
|
||||
}
|
||||
} while (cursor.moveToPrevious());
|
||||
}
|
||||
trackTripStatisticsBuilder.pauseAt(tripStatistics.getStopTime());
|
||||
trackTripStatisticsBuilder.resumeAt(System.currentTimeMillis());
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "RuntimeException", e);
|
||||
@@ -624,7 +647,11 @@ public class TrackRecordingService extends Service {
|
||||
*/
|
||||
private void startRecording() {
|
||||
acquireWakeLock();
|
||||
|
||||
lastLocation = null;
|
||||
isMoving = true;
|
||||
sensorManager = SensorManagerFactory.getSystemSensorManager(this);
|
||||
|
||||
showNotification();
|
||||
sendTrackBroadcast(R.string.track_started_broadcast_action, recordingTrackId);
|
||||
announcementExecutor.restore();
|
||||
@@ -641,16 +668,19 @@ public class TrackRecordingService extends Service {
|
||||
}
|
||||
announcementExecutor.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
|
||||
long trackId = recordingTrackId;
|
||||
stopRecording();
|
||||
|
||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||
if (track != null) {
|
||||
updateTrack(track, myTracksProviderUtils.getLastTrackLocationId(recordingTrackId), false);
|
||||
}
|
||||
|
||||
if (sensorManager != null) {
|
||||
SensorManagerFactory.releaseSystemSensorManager();
|
||||
sensorManager = null;
|
||||
@@ -671,27 +701,14 @@ public class TrackRecordingService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update track.
|
||||
* Updates a {@link TripStatistics} to a time.
|
||||
*
|
||||
* @param track the track
|
||||
* @param lastTrackPointId the last track point id
|
||||
* @param isLastTrackPointNew true if the last track point id is new
|
||||
* @param tripStatistics the trip statistics
|
||||
* @param time the time
|
||||
*/
|
||||
private void updateTrack(Track track, long lastTrackPointId, boolean isLastTrackPointNew) {
|
||||
if (lastTrackPointId >= 0) {
|
||||
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);
|
||||
private void updateTripStatisticsToTime(TripStatistics tripStatistics, long time) {
|
||||
tripStatistics.setStopTime(time);
|
||||
tripStatistics.setTotalTime(time - tripStatistics.getStartTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,13 +718,13 @@ public class TrackRecordingService extends Service {
|
||||
*/
|
||||
private void onLocationChangedAsync(Location location) {
|
||||
try {
|
||||
if (!isRecording()) {
|
||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
||||
if (location == null) {
|
||||
Log.w(TAG, "Ignore onLocationChangedAsync. location is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!LocationUtils.isValidLocation(location)) {
|
||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not valid location.");
|
||||
if (!isRecording()) {
|
||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -716,59 +733,73 @@ public class TrackRecordingService extends Service {
|
||||
return;
|
||||
}
|
||||
|
||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||
if (track == null) {
|
||||
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||
if (recordingTrack == null) {
|
||||
Log.d(TAG, "Ignore onLocationChangedAsync. recodingTrack is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
Location lastLocation = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
||||
if (!LocationUtils.isValidLocation(lastLocation)) {
|
||||
lastLocation = null;
|
||||
locationListenerPolicy.updateIdleTime(trackTripStatisticsBuilder.getIdleTime());
|
||||
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
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()) {
|
||||
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()
|
||||
&& sensorManager.getSensorDataSet() != null && sensorManager.isSensorDataSetValid();
|
||||
long now = System.currentTimeMillis();
|
||||
markerTripStatisticsBuilder.addLocation(location, lastLocation, now, hasSensorData, minRecordingDistance);
|
||||
if (trackTripStatisticsBuilder.addLocation(
|
||||
location, lastLocation, now, hasSensorData, minRecordingDistance)) {
|
||||
try {
|
||||
if (lastLocation != null && location.distanceTo(lastLocation)
|
||||
> maxRecordingDistance) {
|
||||
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);
|
||||
|
||||
// If stationary for two locations, make sure the first one is recorded
|
||||
if (distanceToLastLocation == 0 && !hasSensorData) {
|
||||
if (isMoving) {
|
||||
isMoving = false;
|
||||
if (lastLocation != null && !lastLocation.equals(lastRecordedLocation)) {
|
||||
if (!insertLocation(lastLocation, lastRecordedLocation, recordingTrackId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSensorData) {
|
||||
location = new MyTracksLocation(location, sensorManager.getSensorDataSet());
|
||||
}
|
||||
lastLocation = location;
|
||||
} else if (distanceToLastRecordedLocation >= minRecordingDistance || hasSensorData) {
|
||||
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());
|
||||
|
||||
updateTrack(track, trackPointId, true);
|
||||
} 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);
|
||||
}
|
||||
|
||||
boolean startNewSegment = LocationUtils.isValidLocation(lastRecordedLocation)
|
||||
&& distanceToLastRecordedLocation > maxRecordingDistance
|
||||
&& recordingTrack.getStartId() >= 0;
|
||||
if (startNewSegment) {
|
||||
Log.d(TAG, "Inserting a separator track point.");
|
||||
Location separator = new Location(LocationManager.GPS_PROVIDER);
|
||||
separator.setLongitude(0);
|
||||
separator.setLatitude(100);
|
||||
separator.setTime(lastRecordedLocation.getTime());
|
||||
myTracksProviderUtils.insertTrackPoint(separator, recordingTrackId);
|
||||
}
|
||||
|
||||
if (!insertLocation(location, lastRecordedLocation, recordingTrackId)) {
|
||||
return;
|
||||
}
|
||||
announcementExecutor.update();
|
||||
splitExecutor.update();
|
||||
lastLocation = location;
|
||||
} else {
|
||||
Log.d(TAG, "Ignore location. distanceToLastRecordedLocation < minRecordingDistance.");
|
||||
}
|
||||
} catch (Error e) {
|
||||
Log.e(TAG, "Error in onLocationChangedAsync", e);
|
||||
@@ -779,11 +810,84 @@ 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.
|
||||
*/
|
||||
private void registerLocationListener() {
|
||||
unregisterLocationListener();
|
||||
if (locationManager == null) {
|
||||
Log.e(TAG, "locationManager is null.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long interval = locationListenerPolicy.getDesiredPollingInterval();
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval,
|
||||
|
||||
@@ -26,8 +26,8 @@ import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Builder for {@link TripStatistics}. For keeping track statistics as new
|
||||
* locations are added.
|
||||
* Builder for {@link TripStatistics}. For keeping statistics as a track is
|
||||
* paused/resumed and new locations are added.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
@@ -37,6 +37,18 @@ public class TripStatisticsBuilder {
|
||||
// The trip statistics.
|
||||
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.
|
||||
private final DoubleBuffer speedBuffer = new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
|
||||
|
||||
@@ -51,85 +63,88 @@ public class TripStatisticsBuilder {
|
||||
private final DoubleBuffer gradeBuffer = new DoubleBuffer(Constants.GRADE_SMOOTHING_FACTOR);
|
||||
|
||||
/**
|
||||
* Creates a new {@link TripStatistics} starting at a start time.
|
||||
* Creates a new trip starting at a start time.
|
||||
*
|
||||
* @param startTime the start time
|
||||
*/
|
||||
public TripStatisticsBuilder(long startTime) {
|
||||
tripStatistics = new TripStatistics();
|
||||
tripStatistics.setStartTime(startTime);
|
||||
resumeAt(startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the {@link TripStatistics} at a stop time.
|
||||
* Creates a new trip, starting with an existing {@link TripStatistics}.
|
||||
*
|
||||
* @param stopTime the stop time
|
||||
* @param other the existing {@link TripStatistics}
|
||||
*/
|
||||
public void pauseAt(long stopTime) {
|
||||
tripStatistics.setStopTime(stopTime);
|
||||
tripStatistics.setTotalTime(stopTime - tripStatistics.getStartTime());
|
||||
public TripStatisticsBuilder(TripStatistics other) {
|
||||
tripStatistics = new TripStatistics(other);
|
||||
if (tripStatistics.getStartTime() > 0) {
|
||||
resumeAt(tripStatistics.getStartTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link TripStatistics}.
|
||||
* Sets the min recording distance.
|
||||
*
|
||||
* @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() {
|
||||
// Take a snapshot - we don't want anyone messing with our tripStatistics
|
||||
// Take a snapshot - we don't want anyone messing with our internals
|
||||
return new TripStatistics(tripStatistics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a location.
|
||||
*
|
||||
* @param location the location
|
||||
* @param lastLocation the last location
|
||||
* Returns the amount of time the user has been idle or 0 if he is moving.
|
||||
*/
|
||||
public void addLocation(Location location, Location lastLocation) {
|
||||
addLocation(location, lastLocation, location.getTime(), false,
|
||||
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a location. This will update all of the internal variables with this
|
||||
* new location.
|
||||
*
|
||||
* @param location the location
|
||||
* @param lastLocation the last location
|
||||
* @param time the time
|
||||
* @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, Location lastLocation, long time, boolean alwaysAdd,
|
||||
int minRecordingDistance) {
|
||||
pauseAt(time);
|
||||
|
||||
double elevationDifference = updateElevation(location.getAltitude());
|
||||
tripStatistics.updateLatitudeExtremities(location.getLatitude());
|
||||
tripStatistics.updateLongitudeExtremities(location.getLongitude());
|
||||
|
||||
// If lastLocation is null, returns true.
|
||||
if (lastLocation == null) {
|
||||
return true;
|
||||
public long getIdleTime() {
|
||||
if (lastLocation == null || lastMovingLocation == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double distance = lastLocation.distanceTo(location);
|
||||
if (distance < minRecordingDistance && location.getSpeed() < Constants.MAX_NO_MOVEMENT_SPEED) {
|
||||
return alwaysAdd;
|
||||
}
|
||||
|
||||
long movingTime = location.getTime() - lastLocation.getTime();
|
||||
if (movingTime < 0) {
|
||||
Log.e(TAG, "Negative moving time: " + movingTime);
|
||||
return alwaysAdd;
|
||||
}
|
||||
|
||||
tripStatistics.addTotalDistance(distance);
|
||||
tripStatistics.addMovingTime(movingTime);
|
||||
updateSpeed(
|
||||
location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed());
|
||||
updateGrade(distance, elevationDifference);
|
||||
return true;
|
||||
return lastLocation.getTime() - lastMovingLocation.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,11 +152,62 @@ public class TripStatisticsBuilder {
|
||||
* is noisy so the smoothed elevation is better than the raw elevation for
|
||||
* many tasks.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
double getSmoothedElevation() {
|
||||
public double getSmoothedElevation() {
|
||||
return elevationBuffer.getAverage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a location. This will update all of the internal variables with this
|
||||
* new location.
|
||||
*
|
||||
* @param location the location
|
||||
* @param systemTime the system time for calculating totalTime. This should be
|
||||
* the phone's system time (not GPS time)
|
||||
* @return true if the person is moving
|
||||
*/
|
||||
public boolean addLocation(Location location, long systemTime) {
|
||||
if (paused) {
|
||||
Log.w(TAG, "Track is paused. Ignore addLocation.");
|
||||
return false;
|
||||
}
|
||||
|
||||
tripStatistics.setTotalTime(systemTime - tripStatistics.getStartTime());
|
||||
|
||||
double elevationDifference = updateElevation(location.getAltitude());
|
||||
tripStatistics.updateLatitudeExtremities(location.getLatitude());
|
||||
tripStatistics.updateLongitudeExtremities(location.getLongitude());
|
||||
|
||||
// If this is the first location, remember it and return.
|
||||
if (lastLocation == null || lastMovingLocation == null) {
|
||||
lastLocation = location;
|
||||
lastMovingLocation = location;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't do anything more if we didn't move since the last location.
|
||||
double distance = lastLocation.distanceTo(location);
|
||||
if (distance < minRecordingDistance && location.getSpeed() < Constants.MAX_NO_MOVEMENT_SPEED) {
|
||||
lastLocation = location;
|
||||
return false;
|
||||
}
|
||||
|
||||
long timeDifference = location.getTime() - lastLocation.getTime();
|
||||
if (timeDifference < 0) {
|
||||
Log.e(TAG, "Negative time difference: " + timeDifference);
|
||||
lastLocation = location;
|
||||
return false;
|
||||
}
|
||||
|
||||
tripStatistics.addTotalDistance(lastMovingLocation.distanceTo(location));
|
||||
tripStatistics.addMovingTime(timeDifference);
|
||||
updateSpeed(
|
||||
location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed());
|
||||
updateGrade(distance, elevationDifference);
|
||||
lastLocation = location;
|
||||
lastMovingLocation = location;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a speed reading. Assumes the user is moving.
|
||||
*
|
||||
|
||||
@@ -32,12 +32,12 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class Track implements Parcelable {
|
||||
|
||||
private long id = -1L;
|
||||
private long id = -1;
|
||||
private String name = "";
|
||||
private String description = "";
|
||||
private String category = "";
|
||||
private long startId = -1L;
|
||||
private long stopId = -1L;
|
||||
private long startId = -1;
|
||||
private long stopId = -1;
|
||||
|
||||
// The number of location points (present even if the points themselves are
|
||||
// not loaded)
|
||||
|
||||
+2
-3
@@ -36,7 +36,6 @@ public class TripStatisticsBuilderTest extends TestCase {
|
||||
assertEquals(0.0, tripStatistics.getTotalElevationGain());
|
||||
assertEquals(0, tripStatistics.getMovingTime());
|
||||
assertEquals(0.0, tripStatistics.getTotalDistance());
|
||||
Location lastLocation = null;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Location location = new Location("test");
|
||||
location.setAccuracy(1.0f);
|
||||
@@ -49,7 +48,8 @@ public class TripStatisticsBuilderTest extends TestCase {
|
||||
// Each time slice is 10 seconds.
|
||||
long time = 1000 + 10000 * i;
|
||||
location.setTime(time);
|
||||
builder.addLocation(location, lastLocation);
|
||||
boolean moving = builder.addLocation(location, time);
|
||||
assertEquals((i != 0), moving);
|
||||
|
||||
tripStatistics = builder.getTripStatistics();
|
||||
assertEquals(10000 * i, tripStatistics.getTotalTime());
|
||||
@@ -68,7 +68,6 @@ public class TripStatisticsBuilderTest extends TestCase {
|
||||
assertEquals(0.009, tripStatistics.getMaxGrade(), 0.0001);
|
||||
}
|
||||
assertEquals(111.0 * i, tripStatistics.getTotalDistance(), 100);
|
||||
lastLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user