Make GPX importer more robust.

Handle the case where the first track point does not have a time
without segfaulting. (issue #316, #192)

Don't throw an exception on a negative time change. It isn't the end
of the world, just put a warning in the log and move on (without
updating the speed, since we really don't have a clue now). (issue #186)

Reset the element content even when we aren't in a track element.  GPX
can have elements outside of the <trk>.  This was causing problems
such as content in a <metadata> element before the <trk> being
included in the track name.

There could still be weirdness in the stats if some of the points have
a time element while others don't.  Hard to say what the best course
of action is in that case though, and may involve changes to the
TripStatisticsBuilder.
This commit is contained in:
Jared Casper
2011-02-13 21:33:31 -08:00
parent 5b0dbd5d30
commit ac1a762fa8
@@ -229,7 +229,10 @@ public class GpxImporter extends DefaultHandler {
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if (!isInTrackElement) { return; }
if (!isInTrackElement) {
content = null;
return;
}
// process these elements only as sub-elements of track
if (localName.equals(TAG_TRACK_POINT)) {
@@ -360,6 +363,10 @@ public class GpxImporter extends DefaultHandler {
*/
private void onTrackPointElementEnd() throws SAXException {
if (MyTracksUtils.isValidLocation(location)) {
if (statsBuilder == null) {
// first point did not have a time, start stats builder without it
statsBuilder = new TripStatisticsBuilder(0);
}
statsBuilder.addLocation(location, location.getTime());
// insert in db
@@ -455,18 +462,18 @@ public class GpxImporter extends DefaultHandler {
// check for negative time change
if (timeDifference < 0) {
String msg = createErrorMessage("Found negative time change.");
throw new SAXException(msg);
}
Log.w(MyTracksConstants.TAG, "Found negative time change.");
} else {
// We don't have a speed and bearing in GPX, make something up from
// the last two points.
// TODO GPS points tend to have some inherent imprecision,
// speed and bearing will likely be off, so the statistics for things like
// max speed will also be off.
float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference;
location.setSpeed(speed);
location.setBearing(lastSegmentLocation.bearingTo(location));
// We don't have a speed and bearing in GPX, make something up from
// the last two points.
// TODO GPS points tend to have some inherent imprecision,
// speed and bearing will likely be off, so the statistics for things like
// max speed will also be off.
float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference;
location.setSpeed(speed);
location.setBearing(lastSegmentLocation.bearingTo(location));
}
}
// Fill in the time