revert f505ce7c6bde

This commit is contained in:
Jimmy Shih
2012-08-14 10:04:38 -07:00
parent 1a6baf2beb
commit 360b757bf3
7 changed files with 324 additions and 155 deletions
@@ -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);
@@ -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);
@@ -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)
@@ -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;
}
}