Issue 45: Add ImportAllTracks to import GPX files from /sdcard/MyTracks/gpx

ImportAllTracks is essentially just a modification of ExportAllTracks that
uses the existing GpxImporter to import all GPX files found in
/sdcard/MyTracks/gpx. So that the import functionality can always be accessed,
the MyTracks Activity's MenuManager is altered so that the Tracks button shows
regardless of whether there are any tracks in the database (ImportAllTracks is
launched by a button in the lower right of the MyTracksList activity).

A Toast message shows if no GPX files are found; this serves as a hint to
users on where to put GPX files for import so that this addition should be
discoverable and useable without documentation.

Im
This commit is contained in:
David Piggott
2011-02-13 22:15:48 +00:00
commit 59a05262a1
366 changed files with 47907 additions and 0 deletions
@@ -0,0 +1,116 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.stats;
/**
* A helper class that tracks a minimum and a maximum of a variable.
*
* @author Sandor Dornbush
*/
public class ExtremityMonitor {
/**
* The smallest value seen so far.
*/
private double min;
/**
* The largest value seen so far.
*/
private double max;
public ExtremityMonitor() {
reset();
}
/**
* Updates the min and the max with the new value.
*
* @param value the new value for the monitor
* @return true if an extremity was found
*/
public boolean update(double value) {
boolean changed = false;
if (value < min) {
min = value;
changed = true;
}
if (value > max) {
max = value;
changed = true;
}
return changed;
}
/**
* Gets the minimum value seen.
*
* @return The minimum value passed into the update() function
*/
public double getMin() {
return min;
}
/**
* Gets the maximum value seen.
*
* @return The maximum value passed into the update() function
*/
public double getMax() {
return max;
}
/**
* Resets this object to it's initial state where the min and max are unknown.
*/
public void reset() {
min = Double.POSITIVE_INFINITY;
max = Double.NEGATIVE_INFINITY;
}
/**
* Sets the minimum and maximum values.
*/
public void set(double min, double max) {
this.min = min;
this.max = max;
}
/**
* Sets the minimum value.
*/
public void setMin(double min) {
this.min = min;
}
/**
* Sets the maximum value.
*/
public void setMax(double max) {
this.max = max;
}
public boolean hasData() {
return min != Double.POSITIVE_INFINITY
&& max != Double.NEGATIVE_INFINITY;
}
@Override
public String toString() {
return "Min: " + min + " Max: " + max;
}
}
@@ -0,0 +1,2 @@
package com.google.android.apps.mytracks.stats;
parcelable TripStatistics;
@@ -0,0 +1,572 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.stats;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Statistical data about a trip.
* The data in this class should be filled out by {@link TripStatisticsBuilder}.
*
* TODO: hashCode and equals
*
* @author Rodrigo Damazio
*/
public class TripStatistics implements Parcelable {
/**
* The start time for the trip. This is system time which might not match gps
* time.
*/
private long startTime = -1;
/**
* The stop time for the trip. This is the system time which might not match
* gps time.
*/
private long stopTime = -1;
/**
* The total time that we believe the user was traveling in milliseconds.
*/
private long movingTime;
/**
* The total time of the trip in milliseconds.
* This is only updated when new points are received, so it may be stale.
*/
private long totalTime;
/**
* The total distance in meters that the user traveled on this trip.
*/
private double totalDistance;
/**
* The total elevation gained on this trip in meters.
*/
private double totalElevationGain;
/**
* The maximum speed in meters/second reported that we believe to be a valid
* speed.
*/
private double maxSpeed;
/**
* The min and max latitude values seen in this trip.
*/
private final ExtremityMonitor latitudeExtremities = new ExtremityMonitor();
/**
* The min and max longitude values seen in this trip.
*/
private final ExtremityMonitor longitudeExtremities = new ExtremityMonitor();
/**
* The min and max elevation seen on this trip in meters.
*/
private final ExtremityMonitor elevationExtremities = new ExtremityMonitor();
/**
* The minimum and maximum grade calculations on this trip.
*/
private final ExtremityMonitor gradeExtremities = new ExtremityMonitor();
/**
* Default constructor.
*/
public TripStatistics() {
}
/**
* Copy constructor.
*
* @param other another statistics data object to copy from
*/
public TripStatistics(TripStatistics other) {
this.maxSpeed = other.maxSpeed;
this.movingTime = other.movingTime;
this.startTime = other.startTime;
this.stopTime = other.stopTime;
this.totalDistance = other.totalDistance;
this.totalElevationGain = other.totalElevationGain;
this.totalTime = other.totalTime;
this.latitudeExtremities.set(other.latitudeExtremities.getMin(),
other.latitudeExtremities.getMax());
this.longitudeExtremities.set(other.longitudeExtremities.getMin(),
other.longitudeExtremities.getMax());
this.elevationExtremities.set(other.elevationExtremities.getMin(),
other.elevationExtremities.getMax());
this.gradeExtremities.set(other.gradeExtremities.getMin(),
other.gradeExtremities.getMax());
}
/**
* Combines these statistics with those from another object.
* This assumes that the time periods covered by each do not intersect.
*
* @param other the other waypoint
*/
public void merge(TripStatistics other) {
startTime = Math.min(startTime, other.startTime);
stopTime = Math.max(stopTime, other.stopTime);
totalTime += other.totalTime;
movingTime += other.movingTime;
totalDistance += other.totalDistance;
totalElevationGain += other.totalElevationGain;
maxSpeed = Math.max(maxSpeed, other.maxSpeed);
latitudeExtremities.update(other.latitudeExtremities.getMax());
latitudeExtremities.update(other.latitudeExtremities.getMin());
longitudeExtremities.update(other.longitudeExtremities.getMax());
longitudeExtremities.update(other.longitudeExtremities.getMin());
elevationExtremities.update(other.elevationExtremities.getMax());
elevationExtremities.update(other.elevationExtremities.getMin());
gradeExtremities.update(other.gradeExtremities.getMax());
gradeExtremities.update(other.gradeExtremities.getMin());
}
/**
* Gets the time that this track started.
*
* @return The number of milliseconds since epoch to the time when this track
* started
*/
public long getStartTime() {
return startTime;
}
/**
* Gets the time that this track stopped.
*
* @return The number of milliseconds since epoch to the time when this track
* stopped
*/
public long getStopTime() {
return stopTime;
}
/**
* Gets the total time that this track has been active.
* This statistic is only updated when a new point is added to the statistics,
* so it may be off. If you need to calculate the proper total time, use
* {@link #getStartTime} with the current time.
*
* @return The total number of milliseconds the track was active
*/
public long getTotalTime() {
return totalTime;
}
/**
* Gets the total distance the user traveled.
*
* @return The total distance traveled in meters
*/
public double getTotalDistance() {
return totalDistance;
}
/**
* Gets the the average speed the user traveled.
* This calculation only takes into account the displacement until the last
* point that was accounted for in statistics.
*
* @return The average speed in m/s
*/
public double getAverageSpeed() {
return totalDistance / ((double) totalTime / 1000);
}
/**
* Gets the the average speed the user traveled when they were actively
* moving.
*
* @return The average moving speed in m/s
*/
public double getAverageMovingSpeed() {
return totalDistance / ((double) movingTime / 1000);
}
/**
* Gets the the maximum speed for this track.
*
* @return The maximum speed in m/s
*/
public double getMaxSpeed() {
return maxSpeed;
}
/**
* Gets the moving time.
*
* @return The total number of milliseconds the user was moving
*/
public long getMovingTime() {
return movingTime;
}
/**
* Gets the total elevation gain for this trip. This is calculated as the sum
* of all positive differences in the smoothed elevation.
*
* @return The elevation gain in meters for this trip
*/
public double getTotalElevationGain() {
return totalElevationGain;
}
/**
* Returns the leftmost position (lowest longitude) of the track, in signed
* decimal degrees.
*/
public int getLeft() {
return (int) (longitudeExtremities.getMin() * 1E6);
}
/**
* Returns the rightmost position (highest longitude) of the track, in signed
* decimal degrees.
*/
public int getRight() {
return (int) (longitudeExtremities.getMax() * 1E6);
}
/**
* Returns the bottommost position (lowest latitude) of the track, in meters.
*/
public int getBottom() {
return (int) (latitudeExtremities.getMin() * 1E6);
}
/**
* Returns the topmost position (highest latitude) of the track, in meters.
*/
public int getTop() {
return (int) (latitudeExtremities.getMax() * 1E6);
}
/**
* Gets the minimum elevation seen on this trip. This is calculated from the
* smoothed elevation so this can actually be more than the current elevation.
*
* @return The smallest elevation reading for this trip in meters
*/
public double getMinElevation() {
return elevationExtremities.getMin();
}
/**
* Gets the maximum elevation seen on this trip. This is calculated from the
* smoothed elevation so this can actually be less than the current elevation.
*
* @return The largest elevation reading for this trip in meters
*/
public double getMaxElevation() {
return elevationExtremities.getMax();
}
/**
* Gets the maximum grade for this trip.
*
* @return The maximum grade for this trip as a fraction
*/
public double getMaxGrade() {
return gradeExtremities.getMax();
}
/**
* Gets the minimum grade for this trip.
*
* @return The minimum grade for this trip as a fraction
*/
public double getMinGrade() {
return gradeExtremities.getMin();
}
// Setters - to be used when restoring state or loading from the DB
/**
* Sets the start time for this trip.
*
* @param startTime the start time, in milliseconds since the epoch
*/
public void setStartTime(long startTime) {
this.startTime = startTime;
}
/**
* Sets the stop time for this trip.
*
* @param stopTime the stop time, in milliseconds since the epoch
*/
public void setStopTime(long stopTime) {
this.stopTime = stopTime;
}
/**
* Sets the total moving time.
*
* @param movingTime the moving time in milliseconds
*/
public void setMovingTime(long movingTime) {
this.movingTime = movingTime;
}
/**
* Sets the total trip time.
*
* @param totalTime the total trip time in milliseconds
*/
public void setTotalTime(long totalTime) {
this.totalTime = totalTime;
}
/**
* Sets the total trip distance.
*
* @param totalDistance the trip distance in meters
*/
public void setTotalDistance(double totalDistance) {
this.totalDistance = totalDistance;
}
/**
* Sets the total elevation variation during the trip.
*
* @param totalElevationGain the elevation variation in meters
*/
public void setTotalElevationGain(double totalElevationGain) {
this.totalElevationGain = totalElevationGain;
}
/**
* Sets the maximum speed reached during the trip.
*
* @param maxSpeed the maximum speed in meters per second
*/
public void setMaxSpeed(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
/**
* Sets the minimum elevation reached during the trip.
*
* @param elevation the minimum elevation in meters
*/
public void setMinElevation(double elevation) {
elevationExtremities.setMin(elevation);
}
/**
* Sets the maximum elevation reached during the trip.
*
* @param elevation the maximum elevation in meters
*/
public void setMaxElevation(double elevation) {
elevationExtremities.setMax(elevation);
}
/**
* Sets the minimum grade obtained during the trip.
*
* @param grade the grade as a fraction (-1.0 would mean vertical downwards)
*/
public void setMinGrade(double grade) {
gradeExtremities.setMin(grade);
}
/**
* Sets the maximum grade obtained during the trip).
*
* @param grade the grade as a fraction (1.0 would mean vertical upwards)
*/
public void setMaxGrade(double grade) {
gradeExtremities.setMax(grade);
}
/**
* Sets the bounding box for this trip.
* The unit for all parameters is signed decimal degrees (degrees * 1E6).
*
* @param leftE6 the westmost longitude reached
* @param topE6 the northmost latitude reached
* @param rightE6 the eastmost longitude reached
* @param bottomE6 the southmost latitude reached
*/
public void setBounds(int leftE6, int topE6, int rightE6, int bottomE6) {
latitudeExtremities.set(bottomE6 / 1E6, topE6 / 1E6);
longitudeExtremities.set(leftE6 / 1E6, rightE6 / 1E6);
}
// Data manipulation methods
/**
* Adds to the current total distance.
*
* @param distance the distance to add in meters
*/
void addTotalDistance(double distance) {
totalDistance += distance;
}
/**
* Adds to the total elevation variation.
*
* @param gain the elevation variation in meters
*/
void addTotalElevationGain(double gain) {
totalElevationGain += gain;
}
/**
* Adds to the total moving time of the trip.
*
* @param time the time in milliseconds
*/
void addMovingTime(long time) {
movingTime += time;
}
/**
* Accounts for a new latitude value for the bounding box.
*
* @param latitude the latitude value in signed decimal degrees
*/
void updateLatitudeExtremities(double latitude) {
latitudeExtremities.update(latitude);
}
/**
* Accounts for a new longitude value for the bounding box.
*
* @param longitude the longitude value in signed decimal degrees
*/
void updateLongitudeExtremities(double longitude) {
longitudeExtremities.update(longitude);
}
/**
* Accounts for a new elevation value for the bounding box.
*
* @param elevation the elevation value in meters
*/
void updateElevationExtremities(double elevation) {
elevationExtremities.update(elevation);
}
/**
* Accounts for a new grade value.
*
* @param grade the grade value as a fraction
*/
void updateGradeExtremities(double grade) {
gradeExtremities.update(grade);
}
// String conversion
@Override
public String toString() {
return "TripStatistics { Start Time: " + getStartTime()
+ "; Total Time: " + getTotalTime()
+ "; Moving Time: " + getMovingTime()
+ "; Total Distance: " + getTotalDistance()
+ "; Elevation Gain: " + getTotalElevationGain()
+ "; Min Elevation: " + getMinElevation()
+ "; Max Elevation: " + getMaxElevation()
+ "; Average Speed: " + getAverageMovingSpeed()
+ "; Min Grade: " + getMinGrade()
+ "; Max Grade: " + getMaxGrade()
+ "}";
}
// Parcelable interface and creator
/**
* Creator of statistics data from parcels.
*/
public static class Creator
implements Parcelable.Creator<TripStatistics> {
@Override
public TripStatistics createFromParcel(Parcel source) {
TripStatistics data = new TripStatistics();
data.startTime = source.readLong();
data.movingTime = source.readLong();
data.totalTime = source.readLong();
data.totalDistance = source.readDouble();
data.totalElevationGain = source.readDouble();
data.maxSpeed = source.readDouble();
double minLat = source.readDouble();
double maxLat = source.readDouble();
data.latitudeExtremities.set(minLat, maxLat);
double minLong = source.readDouble();
double maxLong = source.readDouble();
data.longitudeExtremities.set(minLong, maxLong);
double minElev = source.readDouble();
double maxElev = source.readDouble();
data.elevationExtremities.set(minElev, maxElev);
double minGrade = source.readDouble();
double maxGrade = source.readDouble();
data.gradeExtremities.set(minGrade, maxGrade);
return data;
}
@Override
public TripStatistics[] newArray(int size) {
return new TripStatistics[size];
}
}
/**
* Creator of {@link TripStatistics} from parcels.
*/
public static final Creator CREATOR = new Creator();
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(startTime);
dest.writeLong(movingTime);
dest.writeLong(totalTime);
dest.writeDouble(totalDistance);
dest.writeDouble(totalElevationGain);
dest.writeDouble(maxSpeed);
dest.writeDouble(latitudeExtremities.getMin());
dest.writeDouble(latitudeExtremities.getMax());
dest.writeDouble(longitudeExtremities.getMin());
dest.writeDouble(longitudeExtremities.getMax());
dest.writeDouble(elevationExtremities.getMin());
dest.writeDouble(elevationExtremities.getMax());
dest.writeDouble(gradeExtremities.getMin());
dest.writeDouble(gradeExtremities.getMax());
}
}