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
|
// first point did not have a time, start stats builder without it
|
||||||
tripStatisticsBuilder = new TripStatisticsBuilder(0);
|
tripStatisticsBuilder = new TripStatisticsBuilder(0);
|
||||||
}
|
}
|
||||||
tripStatisticsBuilder.addLocation(location, lastSegmentLocation);
|
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||||
|
|
||||||
// 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, lastLocation);
|
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||||
// 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, lastLocation);
|
tripStatisticsBuilder.addLocation(location, location.getTime());
|
||||||
// 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);
|
||||||
|
|||||||
+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.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;
|
||||||
@@ -103,11 +104,24 @@ 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
|
||||||
@@ -181,6 +195,10 @@ 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)) {
|
||||||
@@ -238,6 +256,7 @@ 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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -279,9 +298,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.
|
||||||
*/
|
*/
|
||||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||||
if (track != null) {
|
if (recordingTrack != null) {
|
||||||
restartTrack(track);
|
restartTrack(recordingTrack);
|
||||||
} 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);
|
||||||
@@ -432,14 +451,11 @@ 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) {
|
||||||
TripStatistics trackTripStatistics = trackTripStatisticsBuilder.getTripStatistics();
|
duration = location.getTime() - trackTripStatisticsBuilder.getTripStatistics().getStartTime();
|
||||||
length = trackTripStatistics.getTotalDistance();
|
|
||||||
duration = location.getTime() - trackTripStatistics.getStartTime();
|
|
||||||
} else {
|
} else {
|
||||||
if (!waypointCreationRequest.isTrackStatistics()) {
|
if (!waypointCreationRequest.isTrackStatistics()) {
|
||||||
return -1L;
|
return -1L;
|
||||||
@@ -448,7 +464,6 @@ 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,
|
||||||
@@ -484,7 +499,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(myTracksProviderUtils.getTrack(recordingTrackId))) {
|
if (!shouldResumeTrack(recordingTrack)) {
|
||||||
Log.i(TAG, "Stop resume track.");
|
Log.i(TAG, "Stop resume track.");
|
||||||
stopRecording();
|
stopRecording();
|
||||||
stopSelfResult(startId);
|
stopSelfResult(startId);
|
||||||
@@ -539,8 +554,12 @@ 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);
|
||||||
@@ -572,8 +591,11 @@ 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);
|
||||||
@@ -583,6 +605,7 @@ 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 {
|
||||||
@@ -592,22 +615,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(
|
trackTripStatisticsBuilder.addLocation(location, location.getTime());
|
||||||
location, lastValidTripLocation, location.getTime(), false, minRecordingDistance);
|
|
||||||
lastValidTripLocation = location;
|
|
||||||
if (location.getTime() > markerStartTime) {
|
if (location.getTime() > markerStartTime) {
|
||||||
markerTripStatisticsBuilder.addLocation(
|
markerTripStatisticsBuilder.addLocation(location, location.getTime());
|
||||||
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);
|
||||||
@@ -624,7 +647,11 @@ 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();
|
||||||
@@ -641,16 +668,19 @@ 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;
|
||||||
@@ -671,27 +701,14 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update track.
|
* Updates a {@link TripStatistics} to a time.
|
||||||
*
|
*
|
||||||
* @param track the track
|
* @param tripStatistics the trip statistics
|
||||||
* @param lastTrackPointId the last track point id
|
* @param time the time
|
||||||
* @param isLastTrackPointNew true if the last track point id is new
|
|
||||||
*/
|
*/
|
||||||
private void updateTrack(Track track, long lastTrackPointId, boolean isLastTrackPointNew) {
|
private void updateTripStatisticsToTime(TripStatistics tripStatistics, long time) {
|
||||||
if (lastTrackPointId >= 0) {
|
tripStatistics.setStopTime(time);
|
||||||
if (track.getStartId() < 0) {
|
tripStatistics.setTotalTime(time - tripStatistics.getStartTime());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -701,13 +718,13 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
private void onLocationChangedAsync(Location location) {
|
private void onLocationChangedAsync(Location location) {
|
||||||
try {
|
try {
|
||||||
if (!isRecording()) {
|
if (location == null) {
|
||||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
Log.w(TAG, "Ignore onLocationChangedAsync. location is null.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LocationUtils.isValidLocation(location)) {
|
if (!isRecording()) {
|
||||||
Log.w(TAG, "Ignore onLocationChangedAsync. Not valid location.");
|
Log.w(TAG, "Ignore onLocationChangedAsync. Not recording.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,59 +733,73 @@ public class TrackRecordingService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
|
recordingTrack = myTracksProviderUtils.getTrack(recordingTrackId);
|
||||||
if (track == null) {
|
if (recordingTrack == null) {
|
||||||
Log.d(TAG, "Ignore onLocationChangedAsync. recodingTrack is null.");
|
Log.d(TAG, "Ignore onLocationChangedAsync. recodingTrack is null.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Location lastLocation = myTracksProviderUtils.getLastTrackLocation(recordingTrackId);
|
locationListenerPolicy.updateIdleTime(trackTripStatisticsBuilder.getIdleTime());
|
||||||
if (!LocationUtils.isValidLocation(lastLocation)) {
|
|
||||||
lastLocation = null;
|
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()) {
|
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();
|
|
||||||
markerTripStatisticsBuilder.addLocation(location, lastLocation, now, hasSensorData, minRecordingDistance);
|
// If stationary for two locations, make sure the first one is recorded
|
||||||
if (trackTripStatisticsBuilder.addLocation(
|
if (distanceToLastLocation == 0 && !hasSensorData) {
|
||||||
location, lastLocation, now, hasSensorData, minRecordingDistance)) {
|
if (isMoving) {
|
||||||
try {
|
isMoving = false;
|
||||||
if (lastLocation != null && location.distanceTo(lastLocation)
|
if (lastLocation != null && !lastLocation.equals(lastRecordedLocation)) {
|
||||||
> maxRecordingDistance) {
|
if (!insertLocation(lastLocation, lastRecordedLocation, recordingTrackId)) {
|
||||||
Log.d(TAG, "Inserting a separator track point.");
|
return;
|
||||||
Location separator = new Location(LocationManager.GPS_PROVIDER);
|
}
|
||||||
separator.setLongitude(0);
|
|
||||||
separator.setLatitude(100);
|
|
||||||
separator.setTime(lastLocation.getTime());
|
|
||||||
myTracksProviderUtils.insertTrackPoint(separator, recordingTrackId);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (hasSensorData) {
|
lastLocation = location;
|
||||||
location = new MyTracksLocation(location, sensorManager.getSensorDataSet());
|
} 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());
|
|
||||||
|
boolean startNewSegment = LocationUtils.isValidLocation(lastRecordedLocation)
|
||||||
updateTrack(track, trackPointId, true);
|
&& distanceToLastRecordedLocation > maxRecordingDistance
|
||||||
} catch (SQLiteException e) {
|
&& recordingTrack.getStartId() >= 0;
|
||||||
/*
|
if (startNewSegment) {
|
||||||
* Insert failed, most likely because of SqlLite error code 5
|
Log.d(TAG, "Inserting a separator track point.");
|
||||||
* (SQLite_BUSY). This is expected to happen extremely rarely (if our
|
Location separator = new Location(LocationManager.GPS_PROVIDER);
|
||||||
* listener gets invoked twice at about the same time).
|
separator.setLongitude(0);
|
||||||
*/
|
separator.setLatitude(100);
|
||||||
Log.w(TAG, "SQLiteException", e);
|
separator.setTime(lastRecordedLocation.getTime());
|
||||||
|
myTracksProviderUtils.insertTrackPoint(separator, recordingTrackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insertLocation(location, lastRecordedLocation, recordingTrackId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
announcementExecutor.update();
|
lastLocation = location;
|
||||||
splitExecutor.update();
|
} else {
|
||||||
|
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);
|
||||||
@@ -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.
|
* Registers the location listener.
|
||||||
*/
|
*/
|
||||||
private void registerLocationListener() {
|
private void registerLocationListener() {
|
||||||
unregisterLocationListener();
|
if (locationManager == null) {
|
||||||
|
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 track statistics as new
|
* Builder for {@link TripStatistics}. For keeping statistics as a track is
|
||||||
* locations are added.
|
* paused/resumed and new locations are added.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
@@ -37,6 +37,18 @@ 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);
|
||||||
|
|
||||||
@@ -51,85 +63,88 @@ 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 {@link TripStatistics} starting at a start time.
|
* Creates a new trip 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();
|
||||||
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) {
|
public TripStatisticsBuilder(TripStatistics other) {
|
||||||
tripStatistics.setStopTime(stopTime);
|
tripStatistics = new TripStatistics(other);
|
||||||
tripStatistics.setTotalTime(stopTime - tripStatistics.getStartTime());
|
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() {
|
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);
|
return new TripStatistics(tripStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a location.
|
* Returns the amount of time the user has been idle or 0 if he is moving.
|
||||||
*
|
|
||||||
* @param location the location
|
|
||||||
* @param lastLocation the last location
|
|
||||||
*/
|
*/
|
||||||
public void addLocation(Location location, Location lastLocation) {
|
public long getIdleTime() {
|
||||||
addLocation(location, lastLocation, location.getTime(), false,
|
if (lastLocation == null || lastMovingLocation == null) {
|
||||||
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
return lastLocation.getTime() - lastMovingLocation.getTime();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,11 +152,62 @@ public class TripStatisticsBuilder {
|
|||||||
* is noisy so the smoothed elevation is better than the raw elevation for
|
* is noisy so the smoothed elevation is better than the raw elevation for
|
||||||
* many tasks.
|
* many tasks.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
public double getSmoothedElevation() {
|
||||||
double getSmoothedElevation() {
|
|
||||||
return elevationBuffer.getAverage();
|
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.
|
* 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 = -1L;
|
private long id = -1;
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private String description = "";
|
private String description = "";
|
||||||
private String category = "";
|
private String category = "";
|
||||||
private long startId = -1L;
|
private long startId = -1;
|
||||||
private long stopId = -1L;
|
private long stopId = -1;
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
+2
-3
@@ -36,7 +36,6 @@ 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);
|
||||||
@@ -49,7 +48,8 @@ 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);
|
||||||
builder.addLocation(location, lastLocation);
|
boolean moving = builder.addLocation(location, time);
|
||||||
|
assertEquals((i != 0), moving);
|
||||||
|
|
||||||
tripStatistics = builder.getTripStatistics();
|
tripStatistics = builder.getTripStatistics();
|
||||||
assertEquals(10000 * i, tripStatistics.getTotalTime());
|
assertEquals(10000 * i, tripStatistics.getTotalTime());
|
||||||
@@ -68,7 +68,6 @@ 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