When play track, add a containing folder to contain all the merged tracks

This commit is contained in:
Jimmy Shih
2013-10-02 15:22:00 -07:00
parent 7594f6b516
commit b182c1cb80
17 changed files with 503 additions and 369 deletions
+72 -62
View File
@@ -564,7 +564,7 @@ limitations under the License.
<string name="eula_body"
translation_description="The body in the 'Terms of Service. See http://m.google.com/toscountry.
%1$s: host name, 'm.google.com'">
%1$s host name, 'm.google.com'">
By using Google\'s mobile products and services (&#8220;Services&#8221;), you agree to be bound
by a) the YouTube Terms of Use (%1$s/tos_youtube) for YouTube-related Services, b) the Google
Maps Terms and Conditions (%1$s/tos_maps) for mapping, local and location-based Services, c) the
@@ -589,7 +589,7 @@ limitations under the License.
translation_description="The footer in the 'Terms of Service'. See
http://m.google.com/toscountry.
%1$s: host name, 'm.google.com'">
%1$s host name, 'm.google.com'">
Any required attribution or notice for the third party content may be found at
%1$s/legalnotices.
</string>
@@ -603,8 +603,8 @@ limitations under the License.
translation_description="When exporting all tracks to the external storage, the option to export
as a certain file format.
%1$s: the file format. E.g., 'KML'.
%2$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the file format. E.g., 'KML'.
%2$s the directory. E.g., '/MyTracks/kml'.">
All as %1$s to %2$s
</string>
<string name="export_all_title"
@@ -638,14 +638,14 @@ limitations under the License.
translation_description="When exporting a track to the external storage, the option to export as
a certain file format.
%1$s: the file format. E.g., 'KML'.
%2$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the file format. E.g., 'KML'.
%2$s the directory. E.g., '/MyTracks/kml'.">
as %1$s to %2$s
</string>
<string name="export_external_storage_progress_message"
translation_description="When exporting tracks to the external storage, the progress message.
%1$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the directory. E.g., '/MyTracks/kml'.">
Exporting to %1$s&#8230;
</string>
<string name="export_external_storage_success"
@@ -662,8 +662,8 @@ limitations under the License.
<string name="export_google_error"
translation_description="When exporting a track, the error message.
%1$s: service name. E.g, Google Maps.
%2$s: service url. E.g, maps.google.com.">
%1$s service name. E.g, Google Maps.
%2$s service url. E.g, maps.google.com.">
An error has occurred. Unable to export to %1$s (%2$s). Please try again.
</string>
<string name="export_google_fusion_tables"
@@ -702,8 +702,8 @@ limitations under the License.
translation_description="When sending a track to Google, the additional comment on the bottom of
the result page.
%1$s: service name. E.g, Google Maps.
%2$s: service url. E.g, maps.google.com.">
%1$s service name. E.g, Google Maps.
%2$s service url. E.g, maps.google.com.">
Track exported to %1$s (%2$s). It may take a few minutes for it to appear.
</string>
<string name="export_title"
@@ -830,6 +830,10 @@ limitations under the License.
translation_description="The title on an alert dialog indicating success.">
Success
</string>
<string name="generic_tracks"
translation_description="Generic title for a list of tracks.">
Tracks
</string>
<string name="generic_yes"
translation_description="The text on a button to say yes.">
Yes
@@ -933,14 +937,14 @@ limitations under the License.
translation_description="When importing from the external storage, the error message when the
directory doesn't exist.
%1$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the directory. E.g., '/MyTracks/kml'.">
%1$s does not exist.
</string>
<string name="import_no_file"
translation_description="When importing from the external storage, the message in the result
dialog when there is no files to import.
%1$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the directory. E.g., '/MyTracks/kml'.">
There were no files to import. Connect your device to your computer and place the files to
import in %1$s.
</string>
@@ -952,15 +956,15 @@ limitations under the License.
<string name="import_progress_message"
translation_description="When importing from the external storage, the progress message.
%1$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the directory. E.g., '/MyTracks/kml'.">
Importing from %1$s&#8230;
</string>
<string name="import_selection_option"
translation_description="When importing all from external storage, the option to import all the
files of a certain file format.
%1$s: the file format. E.g., 'KML'.
%2$s: the directory. E.g., '/MyTracks/kml'.">
%1$s the file format. E.g., 'KML'.
%2$s the directory. E.g., '/MyTracks/kml'.">
All %1$s from %2$s
</string>
<string name="import_selection_title"
@@ -978,7 +982,7 @@ limitations under the License.
<!-- List item -->
<string name="list_item_selected"
translation_description="Title indicating the number of items selected in a list.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d selected
</string>
@@ -1012,26 +1016,26 @@ limitations under the License.
translation_description="When inserting a marker to indicate the end of a track, the marker's
name. E.g., 'track_name (End)'.
%1$s track name. E.g., 'track_name'.">
%1$s track name. E.g., 'Grand Canyon trail'.">
%1$s (End)
</string>
<string name="marker_label_start"
translation_description="When inserting a marker to indicate the start of a track, the marker's
name. E.g., 'track_name (Start)'.
%1$s track name. E.g., 'track_name'.">
%1$s track name. E.g., 'Grand Canyon trail'.">
%1$s (Start)
</string>
<string name="marker_name_format"
translation_description="When adding a marker, the string format for the default name.
%1$d: number. E.g., '1'.">
%1$d number. E.g., '1'.">
Marker %1$d
</string>
<string name="marker_split_name_format"
translation_description="When adding a split marker, the string format for the default name.
%1$d: number. E.g., '1'.">
%1$d number. E.g., '1'.">
Split %1$d
</string>
@@ -1334,7 +1338,7 @@ limitations under the License.
translation_description="For a marker returned in the search result, the text field indicating
the track that the marker belongs to.
%1$s: track name. E.g., 'Grand Canyon trail'.">
%1$s track name. E.g., 'Grand Canyon trail'.">
In track &#8216;%1$s&#8217;.
</string>
<string name="search_voice_prompt"
@@ -1348,9 +1352,9 @@ limitations under the License.
translation_description="When sending a track to Google, a note indicating it is created by
Google My Tracks on Android.
%1$s: the html anchor opening tag. Place this placeholder before the app name,
%1$s the html anchor opening tag. Place this placeholder before the app name,
'Google My Tracks'.
%2$s: the html anchor closing tag. Place this placeholder after the app name,
%2$s the html anchor closing tag. Place this placeholder after the app name,
'Google My Tracks'.">
Created by %1$sGoogle My Tracks%2$s on Android.
</string>
@@ -1376,15 +1380,15 @@ limitations under the License.
<string name="send_google_progress_message"
translation_description="When sending a track to a Google service, the progress message.
%1$s: service name. 'Google Maps', 'Google Fusion Tables', or 'Google Spreadsheets'.">
%1$s service name. 'Google Maps', 'Google Fusion Tables', or 'Google Spreadsheets'.">
Sending to %1$s&#8230;
</string>
<string name="send_google_track_part_label"
translation_description="When sending a track to Google, the label to name segments of a large
track. E.g., 'track_name (Part 1)'.
%1$s: track name. E.g., 'track_name'.
%2$d: part number. E.g., '1'.">
%1$s track name. E.g., 'Grand Canyon trail'.
%2$d part number. E.g., '1'.">
%1$s (Part %2$d)
</string>
@@ -1405,7 +1409,7 @@ limitations under the License.
translation_description="In the 'Sensor state' page, the value for the 'Cadence'. Cadence is the
number of revolutions of the crank per minute. E.g., 'Cadence: 80 rpm'.
%1$d: a number. E.g., '80'.">
%1$d a number. E.g., '80'.">
%1$d rpm
</string>
<string name="sensor_state_connected"
@@ -1434,7 +1438,7 @@ limitations under the License.
translation_description="In the 'Sensor state' page, the value for the 'Heart rate'. E.g.,
'Hear rate: 100 bpm'.
%1$d: a number. E.g., '100'.">
%1$d a number. E.g., '100'.">
%1$d bpm
</string>
<string name="sensor_state_last_sensor_time"
@@ -1453,7 +1457,7 @@ limitations under the License.
translation_description="In the 'Sensor state' page, the value for the 'Power'. Power is the
power output of the rider. E.g., 'Power: 50 W'.
%1$d: a number. E.g., '50'.">
%1$d a number. E.g., '50'.">
%1$d W
</string>
<string name="sensor_state_sending"
@@ -1644,7 +1648,7 @@ limitations under the License.
summary for the 'Percentage from average' option explaining that the medium speed range is set
as a percentage from the average speed.
%1$d: an integer value. E.g., '15'.">
%1$d an integer value. E.g., '15'.">
The medium speed range is %1$d %% from the average speed
</string>
<string name="settings_map_slow"
@@ -1859,7 +1863,7 @@ limitations under the License.
translation_description="In the 'Sensor' settings, the summary to indicate that an ANT+ sensor
is paired. Note that ANT+ is a radio standard.
%1$d: device id number. E.g., '1'.">
%1$d device id number. E.g., '1'.">
Paired with %1$d
</string>
<string name="settings_sensor_ant_reset_bike_cadence_sensor"
@@ -1921,7 +1925,7 @@ limitations under the License.
<string name="settings_sensor_connected"
translation_description="A message when a sensor is connected.
%1$s: sensor name. E.g., 'Polar Bluetooth'.">
%1$s sensor name. E.g., 'Polar Bluetooth'.">
Connected to %1$s
</string>
<string name="settings_sensor_type"
@@ -2081,7 +2085,7 @@ limitations under the License.
translation_description="When sharing a track file with friends, the body of the message. Note
that \n is the new line character.
%1$s: track description.">
%1$s track description.">
I think you might be interested in this track.\n\nTo view this track, use Google Earth or other
mapping software.\n\n%1$s
</string>
@@ -2094,8 +2098,8 @@ limitations under the License.
translation_description="When sharing a track URL with friends, the body of the message. Note
that \n is the newline character.
%1$s: url. E.g., 'https://maps.google.com/maps'.
%2$s: track description.">
%1$s url. E.g., 'https://maps.google.com/maps'.
%2$s track description.">
I think you might be interested in this track:\n\n%1$s\n\n%2$s
</string>
<string name="share_track_share_url_title"
@@ -2222,7 +2226,7 @@ limitations under the License.
<string name="track_name_format"
translation_description="When creating a new track, the string format to name the track.
%1$d: track number. E.g., '1'.">
%1$d track number. E.g., '1'.">
Track %1$d
</string>
<string name="track_record_notification"
@@ -2230,7 +2234,13 @@ limitations under the License.
informing the user that My Tracks is actively recording his track.">
Recording your track&#8230;
</string>
<string name="track_markers"
translation_description="Title indicating a particular track's markers.
%1$s track name. E.g., 'Grand Canyon trail'.">
%1$s Markers
</string>
<!-- Track Delete -->
<string name="track_delete_all_confirm_message"
translation_description="When deleting all the tracks, the confirmation message.">
@@ -2431,140 +2441,140 @@ limitations under the License.
<string name="value_float_feet"
translation_description="Display a float value in feet (ft).
%1$.2f: a float number. E.g., '2.22'.">
%1$.2f a float number. E.g., '2.22'.">
%1$.2f ft
</string>
<string name="value_float_kilometer"
translation_description="Display a float value in kilometers (km).
%1$.2f: a float number. E.g., '2.22'.">
%1$.2f a float number. E.g., '2.22'.">
%1$.2f km
</string>
<string name="value_float_meter"
translation_description="Display a float value in meters (m).
%1$.2f: a float number. E.g., '2.22'.">
%1$.2f a float number. E.g., '2.22'.">
%1$.2f m
</string>
<string name="value_float_mile"
translation_description="Display a float value in miles (mi).
%1$.2f: a float number. E.g., '2.22'.">
%1$.2f a float number. E.g., '2.22'.">
%1$.2f mi
</string>
<string name="value_float_mile_poor_gps"
translation_description="In a setting picker, the string format to display a float value in
miles (mi), recommended when having poor GPS signal.
%1$.1f: a float number. E.g., '2.2'.">
%1$.1f a float number. E.g., '2.2'.">
%1$.1f mi (poor GPS)
</string>
<string name="value_integer_feet"
translation_description="In a setting picker, the string format to display an integer value in
feet (ft).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d ft
</string>
<string name="value_integer_feet_excellent_gps"
translation_description="In a setting picker, the string format to display an integer value in
feet (ft), recommended when having excellent GPS signal.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d ft (excellent GPS)
</string>
<string name="value_integer_feet_recommended"
translation_description="In a setting picker, the string format to display an integer value in
feet (ft) and that the value is the recommended value.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d ft (recommended)
</string>
<string name="value_integer_kilometer"
translation_description="In a setting picker, the string format to display an integer value in
kilometers (km).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d km
</string>
<string name="value_integer_kilogram"
translation_description="Display an integer value in kilogram (kg).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d kg
</string>
<string name="value_integer_kilometer_hour"
translation_description="Display an integer value in kilometers per hour (km/h).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d km/h
</string>
<string name="value_integer_meter"
translation_description="In a setting picker, the string format to display an integer value in
meters (m).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d m
</string>
<string name="value_integer_meter_excellent_gps"
translation_description="In a setting picker, the string format to display an integer value in
meters (m), recommended when having excellent GPS signal.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d m (excellent GPS)
</string>
<string name="value_integer_meter_poor_gps"
translation_description="In a setting picker, the string format to display an integer value in
meters (m), recommended when having poor GPS signal.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d m (poor GPS)
</string>
<string name="value_integer_meter_recommended"
translation_description="In a setting picker, the string format to display an integer value in
meters (m) and that the value is the recommended value.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d m (recommended)
</string>
<string name="value_integer_mile"
translation_description="In a setting picker, the string format to display an integer value in
miles (mi).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d mi
</string>
<string name="value_integer_mile_hour"
translation_description="Display an integer value in miles per hour (mi/h).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d mi/h
</string>
<string name="value_integer_minute"
translation_description="In a setting picker, the string format to display an integer value in
minutes (min).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d min
</string>
<string name="value_integer_percent"
translation_description="To display a value in percent like 2 %. %% is the escape sequence for
the percent symbol.
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d %%
</string>
<string name="value_integer_pound"
translation_description="Display an integer value in pound (lb).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d lb
</string>
<string name="value_integer_second"
translation_description="In a setting picker, the string format to display an integer value in
seconds (s).
%1$d: an integer value. E.g., '2'.">
%1$d an integer value. E.g., '2'.">
%1$d s
</string>
<string name="value_never"
@@ -2762,9 +2772,9 @@ limitations under the License.
<string name="voice_template"
translation_description="For the voice announcement, the template to make an announcement.
%1$s: distance string. E.g., '2.2 kilometers'.
%2$s: time string. E.g., '20 minutes 1 second'.
%3$s: speed/pace string. E.g., '2.2 miles per hour' for speed and
%1$s distance string. E.g., '2.2 kilometers'.
%2$s time string. E.g., '20 minutes 1 second'.
%3$s speed/pace string. E.g., '2.2 miles per hour' for speed and
'30 minutes 1 second per kilometer' for pace.">
My Tracks %1$s in %2$s at %3$s.
</string>
@@ -52,7 +52,8 @@ import java.util.ArrayList;
public class MyTracksProvider extends ContentProvider {
private static final String TAG = MyTracksProvider.class.getSimpleName();
private static final int DATABASE_VERSION = 22;
@VisibleForTesting
static final int DATABASE_VERSION = 22;
@VisibleForTesting
static final String DATABASE_NAME = "mytracks.db";
@@ -34,6 +34,7 @@ import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -188,7 +189,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
public void onSampledInTrackPoint(Location location) {
if (isResumed()) {
double[] data = new double[ChartView.NUM_SERIES + 1];
fillDataPoint(location, data);
fillDataPoint(getActivity(), location, data);
pendingPoints.add(data);
}
}
@@ -196,14 +197,14 @@ public class ChartFragment extends Fragment implements TrackDataListener {
@Override
public void onSampledOutTrackPoint(Location location) {
if (isResumed()) {
fillDataPoint(location, null);
fillDataPoint(getActivity(), location, null);
}
}
@Override
public void onSegmentSplit(Location location) {
if (isResumed()) {
fillDataPoint(location, null);
fillDataPoint(getActivity(), location, null);
}
}
@@ -437,11 +438,12 @@ public class ChartFragment extends Fragment implements TrackDataListener {
* data[5] = cadence <br>
* data[6] = power <br>
*
* @param context the context
* @param location the location
* @param data the data point to fill in, can be null
*/
@VisibleForTesting
void fillDataPoint(Location location, double data[]) {
void fillDataPoint(Context context, Location location, double data[]) {
double timeOrDistance = Double.NaN;
double elevation = Double.NaN;
double speed = Double.NaN;
@@ -451,8 +453,9 @@ public class ChartFragment extends Fragment implements TrackDataListener {
double power = Double.NaN;
if (tripStatisticsUpdater != null) {
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils
.getInt(getActivity(), R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
int weight = PreferencesUtils.getInt(
context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT);
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, weight);
TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics();
if (chartByDistance) {
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
@@ -18,25 +18,25 @@ import java.util.Locale;
public enum TrackFileFormat implements Parcelable {
KML {
@Override
public TrackWriter newTrackWriter(Context context, boolean inZip) {
return new KmlTrackWriter(context, inZip);
public TrackWriter newTrackWriter(Context context, boolean playTrack) {
return new KmlTrackWriter(context, playTrack);
}
},
GPX {
@Override
public TrackWriter newTrackWriter(Context context, boolean inZip) {
public TrackWriter newTrackWriter(Context context, boolean playTrack) {
return new GpxTrackWriter(context);
}
},
CSV {
@Override
public TrackWriter newTrackWriter(Context context, boolean inZip) {
public TrackWriter newTrackWriter(Context context, boolean playTrack) {
return new CsvTrackWriter(context);
}
},
TCX {
@Override
public TrackWriter newTrackWriter(Context context, boolean inZip) {
public TrackWriter newTrackWriter(Context context, boolean playTrack) {
return new TcxTrackWriter(context);
}
};
@@ -66,7 +66,7 @@ public enum TrackFileFormat implements Parcelable {
/**
* Creates a new track writer for the format.
*/
public abstract TrackWriter newTrackWriter(Context context, boolean inZip);
public abstract TrackWriter newTrackWriter(Context context, boolean playTrack);
/**
* Returns the mime type for each format.
@@ -46,7 +46,7 @@ import java.text.NumberFormat;
* "Segment","Point","Latitude (deg)","Longitude (deg)","Altitude (m)","Bearing
* (deg)","Accuracy (m)","Speed (m/s)","Time","Power (W)","Cadence (rpm)","Heart
* rate (bpm)","Battery level (%)"<br>
*
*
* @author Rodrigo Damazio
*/
public class CsvTrackWriter implements TrackWriter {
@@ -85,12 +85,13 @@ public class CsvTrackWriter implements TrackWriter {
printWriter = null;
}
}
@Override
public void writeHeader(Track track) {
public void writeHeader(Track[] tracks) {
writeCommaSeparatedLine(context.getString(R.string.generic_name),
context.getString(R.string.track_edit_activity_type_hint),
context.getString(R.string.generic_description));
Track track = tracks[0];
writeCommaSeparatedLine(track.getName(), track.getCategory(), track.getDescription());
writeCommaSeparatedLine();
}
@@ -101,7 +102,7 @@ public class CsvTrackWriter implements TrackWriter {
}
@Override
public void writeBeginWaypoints() {
public void writeBeginWaypoints(Track track) {
writeCommaSeparatedLine(context.getString(R.string.generic_name),
context.getString(R.string.marker_edit_marker_type_hint),
context.getString(R.string.generic_description),
@@ -122,20 +123,24 @@ public class CsvTrackWriter implements TrackWriter {
@Override
public void writeWaypoint(Waypoint waypoint) {
Location location = waypoint.getLocation();
writeCommaSeparatedLine(waypoint.getName(),
waypoint.getCategory(),
waypoint.getDescription(),
Double.toString(location.getLatitude()),
Double.toString(location.getLongitude()),
getAltitude(location),
getBearing(location),
getAccuracy(location),
getSpeed(location),
writeCommaSeparatedLine(waypoint.getName(), waypoint.getCategory(), waypoint.getDescription(),
Double.toString(location.getLatitude()), Double.toString(location.getLongitude()),
getAltitude(location), getBearing(location), getAccuracy(location), getSpeed(location),
StringUtils.formatDateTimeIso8601(location.getTime()));
}
@Override
public void writeBeginTrack(Track track, Location firstPoint) {
public void writeBeginTracks() {
// Do nothing
}
@Override
public void writeEndTracks() {
// Do nothing
}
@Override
public void writeBeginTrack(Track track, Location startLocation) {
writeCommaSeparatedLine(context.getString(R.string.description_track_segment),
context.getString(R.string.description_track_point),
context.getString(R.string.description_location_latitude),
@@ -151,7 +156,7 @@ public class CsvTrackWriter implements TrackWriter {
}
@Override
public void writeEndTrack(Track track, Location lastPoint) {
public void writeEndTrack(Track track, Location endLocation) {
// Do nothing
}
@@ -196,39 +201,31 @@ public class CsvTrackWriter implements TrackWriter {
}
}
pointIndex++;
writeCommaSeparatedLine(Integer.toString(segmentIndex),
Integer.toString(pointIndex),
Double.toString(location.getLatitude()),
Double.toString(location.getLongitude()),
getAltitude(location),
getBearing(location),
getAccuracy(location),
getSpeed(location),
StringUtils.formatDateTimeIso8601(location.getTime()),
power,
cadence,
heartRate);
writeCommaSeparatedLine(Integer.toString(segmentIndex), Integer.toString(pointIndex),
Double.toString(location.getLatitude()), Double.toString(location.getLongitude()),
getAltitude(location), getBearing(location), getAccuracy(location), getSpeed(location),
StringUtils.formatDateTimeIso8601(location.getTime()), power, cadence, heartRate);
}
private String getAltitude(Location location) {
return location.hasAltitude() ? Double.toString(location.getAltitude()) : null;
}
private String getBearing(Location location) {
return location.hasBearing() ? Double.toString(location.getBearing()) : null;
}
private String getAccuracy(Location location) {
return location.hasAccuracy() ? SHORT_FORMAT.format(location.getAccuracy()) : null;
}
private String getSpeed(Location location) {
return location.hasSpeed() ? SHORT_FORMAT.format(location.getSpeed()) : null;
}
/**
* Writes a single line of a CSV file.
*
*
* @param values the values to be written as CSV
*/
private void writeCommaSeparatedLine(String... values) {
@@ -22,11 +22,8 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.database.Cursor;
import android.location.Location;
import android.util.Log;
@@ -51,20 +48,11 @@ public class FileTrackExporter implements TrackExporter {
/**
* Constructor.
*
* @param context the context
* @param myTracksProviderUtils the my tracks provider utils
* @param tracks the tracks
* @param trackFileFormat the track file format
* @param trackWriter the track writer
* @param trackExporterListener the track export listener
*/
public FileTrackExporter(MyTracksProviderUtils myTracksProviderUtils,
Track[] tracks, TrackFileFormat trackFileFormat, Context context, boolean inZip,
TrackExporterListener trackExporterListener) {
this(myTracksProviderUtils, tracks, trackFileFormat.newTrackWriter(context, inZip),
trackExporterListener);
}
@VisibleForTesting
public FileTrackExporter(MyTracksProviderUtils myTracksProviderUtils, Track[] tracks,
TrackWriter trackWriter, TrackExporterListener trackExporterListener) {
this.myTracksProviderUtils = myTracksProviderUtils;
@@ -77,13 +65,17 @@ public class FileTrackExporter implements TrackExporter {
public boolean writeTrack(OutputStream outputStream) {
try {
trackWriter.prepare(outputStream);
trackWriter.writeHeader(tracks[0]);
long startTime = tracks[0].getTripStatistics().getStartTime();
trackWriter.writeHeader(tracks);
for (int i = 0; i < tracks.length; i++) {
writeWaypoints(tracks[i]);
}
trackWriter.writeBeginTracks();
long startTime = tracks[0].getTripStatistics().getStartTime();
for (int i = 0; i < tracks.length; i++) {
long offset = tracks[i].getTripStatistics().getStartTime() - startTime;
writeLocations(tracks[i], offset);
}
trackWriter.writeEndTracks();
trackWriter.writeFooter();
trackWriter.close();
return true;
@@ -117,7 +109,7 @@ public class FileTrackExporter implements TrackExporter {
throw new InterruptedException();
}
if (!hasWaypoints) {
trackWriter.writeBeginWaypoints();
trackWriter.writeBeginWaypoints(track);
hasWaypoints = true;
}
Waypoint waypoint = myTracksProviderUtils.createWaypoint(cursor);
@@ -78,7 +78,7 @@ public class GpxTrackWriter implements TrackWriter {
}
@Override
public void writeHeader(Track track) {
public void writeHeader(Track[] tracks) {
if (printWriter != null) {
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printWriter.println("<gpx");
@@ -94,6 +94,7 @@ public class GpxTrackWriter implements TrackWriter {
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd\">");
printWriter.println("<metadata>");
Track track = tracks[0];
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("</metadata>");
@@ -108,48 +109,7 @@ public class GpxTrackWriter implements TrackWriter {
}
@Override
public void writeBeginTrack(Track track, Location firstLocation) {
if (printWriter != null) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getCategory()) + "</type>");
printWriter.println("<extensions><topografix:color>c0c0c0</topografix:color></extensions>");
}
}
@Override
public void writeEndTrack(Track track, Location lastLocation) {
if (printWriter != null) {
printWriter.println("</trk>");
}
}
@Override
public void writeOpenSegment() {
printWriter.println("<trkseg>");
}
@Override
public void writeCloseSegment() {
printWriter.println("</trkseg>");
}
@Override
public void writeLocation(Location location) {
if (printWriter != null) {
printWriter.println("<trkpt " + formatLocation(location) + ">");
if (location.hasAltitude()) {
printWriter.println("<ele>" + ELEVATION_FORMAT.format(location.getAltitude()) + "</ele>");
}
printWriter.println(
"<time>" + StringUtils.formatDateTimeIso8601(location.getTime()) + "</time>");
printWriter.println("</trkpt>");
}
}
@Override
public void writeBeginWaypoints() {
public void writeBeginWaypoints(Track track) {
// Do nothing
}
@@ -179,6 +139,57 @@ public class GpxTrackWriter implements TrackWriter {
}
}
@Override
public void writeBeginTracks() {
// Do nothing
}
@Override
public void writeEndTracks() {
// Do nothing
}
@Override
public void writeBeginTrack(Track track, Location startLocation) {
if (printWriter != null) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getCategory()) + "</type>");
printWriter.println("<extensions><topografix:color>c0c0c0</topografix:color></extensions>");
}
}
@Override
public void writeEndTrack(Track track, Location endLocation) {
if (printWriter != null) {
printWriter.println("</trk>");
}
}
@Override
public void writeOpenSegment() {
printWriter.println("<trkseg>");
}
@Override
public void writeCloseSegment() {
printWriter.println("</trkseg>");
}
@Override
public void writeLocation(Location location) {
if (printWriter != null) {
printWriter.println("<trkpt " + formatLocation(location) + ">");
if (location.hasAltitude()) {
printWriter.println("<ele>" + ELEVATION_FORMAT.format(location.getAltitude()) + "</ele>");
}
printWriter.println(
"<time>" + StringUtils.formatDateTimeIso8601(location.getTime()) + "</time>");
printWriter.println("</trkpt>");
}
}
/**
* Formats a location with latitude and longitude coordinates.
*
@@ -70,7 +70,7 @@ public class KmlTrackWriter implements TrackWriter {
TRACK_ICON = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
private final Context context;
private final boolean inKmz;
private final boolean playTrack;
private final DescriptionGenerator descriptionGenerator;
private final MyTracksProviderUtils myTracksProviderUtils;
@@ -82,14 +82,14 @@ public class KmlTrackWriter implements TrackWriter {
private boolean hasCadence;
private boolean hasHeartRate;
public KmlTrackWriter(Context context, boolean inKmz) {
this(context, inKmz, new DescriptionGeneratorImpl(context));
public KmlTrackWriter(Context context, boolean playTrack) {
this(context, playTrack, new DescriptionGeneratorImpl(context));
}
@VisibleForTesting
KmlTrackWriter(Context context, boolean inKmz, DescriptionGenerator descriptionGenerator) {
KmlTrackWriter(Context context, boolean playTrack, DescriptionGenerator descriptionGenerator) {
this.context = context;
this.inKmz = inKmz;
this.playTrack = playTrack;
this.descriptionGenerator = descriptionGenerator;
this.myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
}
@@ -113,7 +113,7 @@ public class KmlTrackWriter implements TrackWriter {
}
@Override
public void writeHeader(Track track) {
public void writeHeader(Track[] tracks) {
if (printWriter != null) {
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printWriter.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\"");
@@ -122,6 +122,7 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<Document>");
printWriter.println("<open>1</open>");
printWriter.println("<visibility>1</visibility>");
Track track = tracks[0];
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<atom:author><atom:name>"
+ StringUtils.formatCData(context.getString(R.string.send_google_by_my_tracks, "", ""))
@@ -148,10 +149,11 @@ public class KmlTrackWriter implements TrackWriter {
}
@Override
public void writeBeginWaypoints() {
public void writeBeginWaypoints(Track track) {
if (printWriter != null) {
printWriter.println("<Folder><name>"
+ StringUtils.formatCData(context.getString(R.string.menu_markers)) + "</name>");
+ StringUtils.formatCData(context.getString(R.string.track_markers, track.getName()))
+ "</name>");
printWriter.println("<open>1</open>");
}
}
@@ -181,11 +183,31 @@ public class KmlTrackWriter implements TrackWriter {
}
@Override
public void writeBeginTrack(Track track, Location firstLocation) {
public void writeBeginTracks() {
if (printWriter != null && playTrack) {
printWriter.println("<Folder id=\"" + GoogleEarthUtils.TOUR_FEATURE_ID_VALUE + "\">");
printWriter.println("<name>" + context.getString(R.string.generic_tracks) + "</name>");
printWriter.println("<open>1</open>");
}
}
@Override
public void writeEndTracks() {
if (printWriter != null && playTrack) {
printWriter.println("</Folder>");
}
}
@Override
public void writeBeginTrack(Track track, Location startLocation) {
if (printWriter != null) {
String name = context.getString(R.string.marker_label_start, track.getName());
writePlacemark(name, "", "", START_STYLE, firstLocation);
printWriter.println("<Placemark id=\"" + GoogleEarthUtils.TOUR_FEATURE_ID_VALUE + "\">");
writePlacemark(name, "", "", START_STYLE, startLocation);
if (playTrack) {
printWriter.println("<Placemark>");
} else {
printWriter.println("<Placemark id=\"" + GoogleEarthUtils.TOUR_FEATURE_ID_VALUE + "\">");
}
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println(
"<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
@@ -198,13 +220,13 @@ public class KmlTrackWriter implements TrackWriter {
}
@Override
public void writeEndTrack(Track track, Location lastLocation) {
public void writeEndTrack(Track track, Location endLocation) {
if (printWriter != null) {
printWriter.println("</gx:MultiTrack>");
printWriter.println("</Placemark>");
String name = context.getString(R.string.marker_label_end, track.getName());
String description = descriptionGenerator.generateTrackDescription(track, null, null, false);
writePlacemark(name, "", description, END_STYLE, lastLocation);
writePlacemark(name, "", description, END_STYLE, endLocation);
}
}
@@ -353,12 +375,12 @@ public class KmlTrackWriter implements TrackWriter {
+ StringUtils.formatDateTimeIso8601(location.getTime()) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + styleName + "</styleUrl>");
writeCategory(category);
if (inKmz) {
if (playTrack) {
printWriter.println("<Icon><href>" + Uri.decode(photoUrl) + "</href></Icon>");
} else {
Uri uri = Uri.parse(photoUrl);
printWriter.println("<Icon><href>" + KmzTrackExporter.KMZ_IMAGES_DIR + File.separatorChar
+ uri.getLastPathSegment() + "</href></Icon>");
} else {
printWriter.println("<Icon><href>" + Uri.decode(photoUrl) + "</href></Icon>");
+ uri.getLastPathSegment() + "</href></Icon>");
}
printWriter.print("<ViewVolume>");
@@ -184,7 +184,7 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
return false;
}
Track track = tracks[0];
boolean useKmz = !playTrack && trackFileFormat == TrackFileFormat.KML;
boolean useKmz = trackFileFormat == TrackFileFormat.KML && !playTrack;
String extension = useKmz ? KmzTrackExporter.KMZ_EXTENSION : trackFileFormat.getExtension();
// Make sure the file doesn't exist yet (possibly by changing the filename)
@@ -195,7 +195,7 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
}
FileTrackExporter fileTrackExporter = new FileTrackExporter(myTracksProviderUtils, tracks,
trackFileFormat, context, useKmz, new TrackExporterListener() {
trackFileFormat.newTrackWriter(context, playTrack), new TrackExporterListener() {
@Override
public void onProgressUpdate(int number, int max) {
@@ -111,7 +111,7 @@ public class TcxTrackWriter implements TrackWriter {
}
@Override
public void writeHeader(Track track) {
public void writeHeader(Track[] tracks) {
if (printWriter != null) {
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printWriter.println("<TrainingCenterDatabase"
@@ -142,7 +142,32 @@ public class TcxTrackWriter implements TrackWriter {
}
@Override
public void writeBeginTrack(Track track, Location firstPoint) {
public void writeBeginWaypoints(Track track) {
// Do nothing
}
@Override
public void writeEndWaypoints() {
// Do nothing
}
@Override
public void writeWaypoint(Waypoint waypoint) {
// Do nothing
}
@Override
public void writeBeginTracks() {
// Do nothing
}
@Override
public void writeEndTracks() {
// Do nothing
}
@Override
public void writeBeginTrack(Track track, Location startLocation) {
sportType = getSportType(track.getCategory());
if (printWriter != null) {
String startTime = StringUtils.formatDateTimeIso8601(
@@ -164,7 +189,7 @@ public class TcxTrackWriter implements TrackWriter {
}
@Override
public void writeEndTrack(Track track, Location lastPoint) {
public void writeEndTrack(Track track, Location endLocation) {
if (printWriter != null) {
printWriter.println("</Lap>");
printWriter.println("<Notes>" + StringUtils.formatCData(track.getDescription()) + "</Notes>");
@@ -261,21 +286,6 @@ public class TcxTrackWriter implements TrackWriter {
}
}
@Override
public void writeBeginWaypoints() {
// Do nothing.
}
@Override
public void writeEndWaypoints() {
// Do nothing.
}
@Override
public void writeWaypoint(Waypoint waypoint) {
// Do nothing.
}
/**
* Writes the TCX Version.
*/
@@ -23,58 +23,57 @@ import android.location.Location;
import java.io.OutputStream;
/**
* Interface for writing tracks to a file.
*
* The expected sequence of calls is:
* <ul>
* <li>{@link #prepare}</li>
* <li>{@link #writeHeader}</li>
* <li>For each track:</li>
* <ul>
* <li>{@link #writeBeginWaypoints}
* <li>For each waypoint: {@link #writeWaypoint}
* <li>{@link #writeEndWaypoints}
* <li>{@link #writeBeginTrack}
* <li>For each segment:
* <ul>
* <li>{@link #writeOpenSegment}</li>
* <li>For each location in the segment: {@link #writeLocation}</li>
* <li>{@link #writeCloseSegment}</li>
* </ul>
* </li>
* <li>{@link #writeEndTrack}</li>
* </ul>
* <li>{@link #writeFooter}</li>
* <li>{@link #close}</li>
* </ul>
*
* Interface for writing tracks to a file. The expected sequence of calls is:
*
* <pre>
* {@link #prepare(OutputStream)}
* {@link #writeHeader(Track[])}
* For each track:
* {@link #writeBeginWaypoints(Track)}
* For each waypoint:
* {@link #writeWaypoint(Waypoint)}
* {@link #writeEndWaypoints()}
* {@link #writeBeginTracks()}
* For each track:
* {@link #writeBeginTrack(Track, Location)}
* For each segment:
* {@link #writeOpenSegment()}
* For each location in the segment:
* {@link #writeLocation(Location)}
* {@link #writeCloseSegment()}
* {@link #writeEndTrack(Track, Location)}
* {@link #writeEndTracks()}
* {@link #writeFooter()}
* {@link #close()}
* </pre>
*
* @author Rodrigo Damazio
*/
public interface TrackWriter {
/**
* Gets the file extension (i.e. gpx, kml, ...)
* Gets the file extension (e.g, gpx, kml, ...).
*/
public String getExtension();
/**
* Sets up the file handler.
*
* @param outputStream the output stream for the file handler
* Prepares the output stream.
*
* @param outputStream the output stream
*/
public void prepare(OutputStream outputStream);
/**
* Closes the underlying file handler.
* Closes the output stream.
*/
public void close();
/**
* Writes the header for a file
* Writes the header
*
* @param track the track
* @param tracks the tracks
*/
public void writeHeader(Track track);
public void writeHeader(Track[] tracks);
/**
* Writes the footer.
@@ -83,50 +82,62 @@ public interface TrackWriter {
/**
* Writes the beginning of the waypoints.
*
* @param track the track
*/
public void writeBeginWaypoints();
public void writeBeginWaypoints(Track track);
/**
* Writes the end of the waypoints.
*/
public void writeEndWaypoints();
/**
* Writes a waypoint.
*
*
* @param waypoint the waypoint
*/
public void writeWaypoint(Waypoint waypoint);
/**
* Writes the beginning of the track.
*
* @param track the track
* @param firstLocation the first location
* Writes the beginning of the tracks.
*/
public void writeBeginTrack(Track track, Location firstLocation);
public void writeBeginTracks();
/**
* Writes the end of the track.
*
* @param track the track
* @param lastLocation the last location
* Writes the end of the tracks,
*/
public void writeEndTrack(Track track, Location lastLocation);
public void writeEndTracks();
/**
* Writes the statements necessary to open a new segment.
* Writes the beginning of a track.
*
* @param track the track
* @param startLocation the start location
*/
public void writeBeginTrack(Track track, Location startLocation);
/**
* Writes the end of a track.
*
* @param track the track
* @param endLocation the end location
*/
public void writeEndTrack(Track track, Location endLocation);
/**
* Writes open segment.
*/
public void writeOpenSegment();
/**
* Writes the statements necessary to close a segment.
* Writes close segment.
*/
public void writeCloseSegment();
/**
* Writes a location.
*
*
* @param location the location
*/
public void writeLocation(Location location);
@@ -441,8 +441,8 @@ public class SyncUtils {
java.io.File file = new java.io.File(directory,
FileUtils.buildUniqueFileName(directory, track.getName(), trackFileFormat.getExtension()));
FileTrackExporter fileTrackExporter = new FileTrackExporter(
myTracksProviderUtils, new Track[] { track }, trackFileFormat, context, false, null);
FileTrackExporter fileTrackExporter = new FileTrackExporter(myTracksProviderUtils,
new Track[] { track }, trackFileFormat.newTrackWriter(context, false), null);
FileOutputStream fileOutputStream = null;
try {
@@ -13,6 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.MyTracksProvider.DatabaseHelper;
@@ -22,150 +23,202 @@ import android.net.Uri;
import android.test.AndroidTestCase;
/**
* A unit test for {@link MyTracksProvider}.
* Tests {@link MyTracksProvider}.
*
* @author Youtao Liu
*/
public class MyTracksProviderTest extends AndroidTestCase {
private static final String DATABASE_NAME = "mytrackstest.db";
private SQLiteDatabase db;
private MyTracksProvider myTracksProvider;
private String DATABASE_NAME = "mytrackstest.db";
@Override
protected void setUp() throws Exception {
super.setUp();
getContext().deleteDatabase(DATABASE_NAME);
db = (new DatabaseHelper(getContext(), DATABASE_NAME)).getWritableDatabase();
myTracksProvider = new MyTracksProvider();
super.setUp();
}
/**
* Tests the method {@link MyTracksProvider.DatabaseHelper#onCreate()}.
* Tests {@link MyTracksProvider.DatabaseHelper#onCreate(SQLiteDatabase)}.
*/
public void testDatabaseHelper_OnCreate() {
assertTrue(checkTable(TrackPointsColumns.TABLE_NAME));
assertTrue(checkTable(TracksColumns.TABLE_NAME));
assertTrue(checkTable(WaypointsColumns.TABLE_NAME));
assertTrue(hasTable(TracksColumns.TABLE_NAME));
assertTrue(hasTable(TrackPointsColumns.TABLE_NAME));
assertTrue(hasTable(WaypointsColumns.TABLE_NAME));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is less than 17.
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is less than 17.
*/
public void testDatabaseHelper_onUpgrade_Version16() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(WaypointsColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 16, 20);
assertTrue(checkTable(TrackPointsColumns.TABLE_NAME));
assertTrue(checkTable(TracksColumns.TABLE_NAME));
assertTrue(checkTable(WaypointsColumns.TABLE_NAME));
int oldVersion = 16;
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION);
assertTrue(hasTable(TracksColumns.TABLE_NAME));
assertTrue(hasTable(TrackPointsColumns.TABLE_NAME));
assertTrue(hasTable(WaypointsColumns.TABLE_NAME));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 17.
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 17.
*/
public void testDatabaseHelper_onUpgrade_Version17() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
setupUpgrade(17);
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 17, 20);
assertTrue(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertTrue(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 18.
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 18.
*/
public void testDatabaseHelper_onUpgrade_Version18() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
setupUpgrade(18);
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 18, 20);
assertFalse(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 19.
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 19.
*/
public void testDatabaseHelper_onUpgrade_Version19() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
setupUpgrade(19);
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 19, 20);
assertFalse(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests the method {@link MyTracksProvider#onCreate()}.
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 20.
*/
public void testDatabaseHelper_onUpgrade_Version20() {
setupUpgrade(20);
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 21.
*/
public void testDatabaseHelper_onUpgrade_Version21() {
setupUpgrade(21);
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
* int)} when version is 22.
*/
public void testDatabaseHelper_onUpgrade_Version22() {
setupUpgrade(22);
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
assertFalse(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
}
/**
* Tests {@link MyTracksProvider#onCreate(android.content.Context)}.
*/
public void testOnCreate() {
assertTrue(myTracksProvider.onCreate(getContext()));
}
/**
* Tests the method {@link MyTracksProvider#getType(Uri)}.
* Tests {@link MyTracksProvider#getType(Uri)}.
*/
public void testGetType() {
assertEquals(TrackPointsColumns.CONTENT_TYPE,
myTracksProvider.getType(TrackPointsColumns.CONTENT_URI));
assertEquals(TracksColumns.CONTENT_TYPE, myTracksProvider.getType(TracksColumns.CONTENT_URI));
assertEquals(WaypointsColumns.CONTENT_TYPE,
myTracksProvider.getType(WaypointsColumns.CONTENT_URI));
assertEquals(
TrackPointsColumns.CONTENT_TYPE, myTracksProvider.getType(TrackPointsColumns.CONTENT_URI));
assertEquals(
WaypointsColumns.CONTENT_TYPE, myTracksProvider.getType(WaypointsColumns.CONTENT_URI));
}
/**
* Creates an table only contains one column.
* Creates a table, containing one column.
*
* @param table the name of table
* @param table the table name
*/
private void createEmptyTable(String table) {
private void createTable(String table) {
db.execSQL("CREATE TABLE " + table + " (test INTEGER)");
}
/**
* Drops a table in database.
*
* @param table
* @param table the table name
*/
private void dropTable(String table) {
db.execSQL("Drop TABLE " + table);
}
/**
* Checks whether a table is existed.
* Returns true if the table exists.
*
* @param table the name of table
* @return true means the table has existed
* @param table the table name
*/
private boolean checkTable(String table) {
private boolean hasTable(String table) {
try {
db.rawQuery("select count(*) from " + table, null);
return true;
@@ -175,14 +228,12 @@ public class MyTracksProviderTest extends AndroidTestCase {
}
/**
* Checks whether a column in a table is existed by whether can order by the
* column.
* Returns true if the column in the table exists.
*
* @param table the name of table
* @param column the name of column
* @return true means the column has existed
* @param table the table name
* @param column the column name
*/
private boolean isColumnExisted(String table, String column) {
private boolean hasColumn(String table, String column) {
try {
db.execSQL("SElECT count(*) from " + table + " order by " + column);
} catch (Exception e) {
@@ -193,4 +244,20 @@ public class MyTracksProviderTest extends AndroidTestCase {
return true;
}
/**
* Sets up upgrade.
*
* @param oldVersion thd old database version
*/
private void setupUpgrade(int oldVersion) {
dropTable(TracksColumns.TABLE_NAME);
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(WaypointsColumns.TABLE_NAME);
createTable(TracksColumns.TABLE_NAME);
createTable(TrackPointsColumns.TABLE_NAME);
createTable(WaypointsColumns.TABLE_NAME);
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION);
}
}
@@ -33,9 +33,9 @@ import android.test.AndroidTestCase;
*/
public class ChartFragmentTest extends AndroidTestCase {
private ChartFragment chartFragment;
private static final double HOURS_PER_UNIT = 60.0;
private final double HOURS_PER_UNIT = 60.0;
private ChartFragment chartFragment;
@Override
protected void setUp() throws Exception {
@@ -46,7 +46,7 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the incorrect values of sensor in
* {@link ChartFragment#fillDataPoint(Location, double[])}
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}
*/
public void testFillDataPoint_sensorIncorrect() {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
@@ -83,7 +83,7 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the correct values of sensor in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}.
*/
public void testFillDataPoint_sensorCorrect() {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
@@ -118,7 +118,7 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the value of metric Distance in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}.
*/
public void testFillDataPoint_distanceMetric() {
// By distance.
@@ -159,7 +159,7 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the value of imperial Distance in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}.
*/
public void testFillDataPoint_distanceImperial() {
// By distance.
@@ -204,7 +204,7 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the values of time in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}.
*/
public void testFillDataPoint_time() {
// By time
@@ -220,9 +220,9 @@ public class ChartFragmentTest extends AndroidTestCase {
}
/**
* Tests the logic to get the value of elevation in
* {@link ChartFragment#fillDataPoint(Location, double[])} by one and two
* points.
* Tests the logic to get the value of elevation in
* {@link ChartFragment#fillDataPoint(android.content.Context,
* Location, double[])} by one and two points.
*/
public void testFillDataPoint_elevation() {
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
@@ -247,9 +247,10 @@ public class ChartFragmentTest extends AndroidTestCase {
/**
* Tests the logic to get the value of speed in
* {@link ChartFragment#fillDataPoint(Location, double[])}. In this test,
* firstly remove all points in memory, and then fill in two points one by
* one. The speed values of these points are 129, 130.
* {@link ChartFragment#fillDataPoint(android.content.Context, Location, double[])}. In this test,
* firstly remove all points in memory,
* and then fill in two points one by one. The speed values of these points
* are 129, 130.
*/
public void testFillDataPoint_speed() {
/*
@@ -358,7 +359,7 @@ public class ChartFragmentTest extends AndroidTestCase {
*/
private double[] fillDataPointTestHelper(Location location) {
double[] point = new double[ChartView.NUM_SERIES + 1];
chartFragment.fillDataPoint(location, point);
chartFragment.fillDataPoint(getContext(), location, point);
return point;
}
@@ -7,9 +7,6 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.exporter.FileTrackExporter;
import com.google.android.apps.mytracks.io.file.exporter.TrackExporterListener;
import com.google.android.apps.mytracks.io.file.exporter.TrackWriter;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
@@ -42,7 +39,7 @@ public class FileTrackExporterTest extends AndroidTestCase {
private IMocksControl mocksControl;
private TrackWriter trackWriter;
private Track track;
private Track[] tracks;
private OutputStream outputStream;
private FileTrackExporter fileTrackExporter;
@@ -65,10 +62,12 @@ public class FileTrackExporterTest extends AndroidTestCase {
mocksControl = EasyMock.createStrictControl();
trackWriter = mocksControl.createMock(TrackWriter.class);
track = new Track();
Track track = new Track();
track.setName(TRACK_NAME);
track.setId(TRACK_ID);
tracks = new Track[] {track};
outputStream = new ByteArrayOutputStream();
TrackExporterListener trackExporterListener = new TrackExporterListener() {
@@ -79,7 +78,7 @@ public class FileTrackExporterTest extends AndroidTestCase {
}
};
fileTrackExporter = new FileTrackExporter(
myTracksProviderUtils, new Track[] { track }, trackWriter, trackExporterListener);
myTracksProviderUtils, tracks, trackWriter, trackExporterListener);
}
@Override
@@ -95,10 +94,13 @@ public class FileTrackExporterTest extends AndroidTestCase {
// Set expected mock behavior
trackWriter.prepare(outputStream);
trackWriter.writeHeader(track);
trackWriter.writeBeginTrack(track, null);
trackWriter.writeEndTrack(track, null);
trackWriter.writeHeader(tracks);
trackWriter.writeBeginTracks();
trackWriter.writeBeginTrack(tracks[0], null);
trackWriter.writeEndTrack(tracks[0], null);
trackWriter.writeEndTracks();
trackWriter.writeFooter();
trackWriter.close();
mocksControl.replay();
assertTrue(fileTrackExporter.writeTrack(outputStream));
@@ -124,11 +126,14 @@ public class FileTrackExporterTest extends AndroidTestCase {
// Set expected mock behavior
trackWriter.prepare(outputStream);
trackWriter.writeHeader(track);
trackWriter.writeBeginTrack(track, null);
trackWriter.writeEndTrack(track, null);
trackWriter.writeHeader(tracks);
trackWriter.writeBeginTracks();
trackWriter.writeBeginTrack(tracks[0], null);
trackWriter.writeEndTrack(tracks[0], null);
trackWriter.writeEndTracks();
trackWriter.writeFooter();
trackWriter.close();
mocksControl.replay();
assertTrue(fileTrackExporter.writeTrack(outputStream));
@@ -161,16 +166,17 @@ public class FileTrackExporterTest extends AndroidTestCase {
}
trackWriter.prepare(outputStream);
trackWriter.writeHeader(track);
trackWriter.writeHeader(tracks);
// Expect reading/writing of the waypoints (except the first)
trackWriter.writeBeginWaypoints();
trackWriter.writeBeginWaypoints(tracks[0]);
trackWriter.writeWaypoint(waypointEq(waypoints[1]));
trackWriter.writeWaypoint(waypointEq(waypoints[2]));
trackWriter.writeEndWaypoints();
// Begin the track
trackWriter.writeBeginTrack(trackEq(track), locationEq(locations[0]));
trackWriter.writeBeginTracks();
trackWriter.writeBeginTrack(trackEq(tracks[0]), locationEq(locations[0]));
// Write locations 1-2
trackWriter.writeOpenSegment();
@@ -188,10 +194,12 @@ public class FileTrackExporterTest extends AndroidTestCase {
trackWriter.writeCloseSegment();
// End the track
trackWriter.writeEndTrack(trackEq(track), locationEq(locations[5]));
trackWriter.writeEndTrack(trackEq(tracks[0]), locationEq(locations[5]));
trackWriter.writeEndTracks();
trackWriter.writeFooter();
trackWriter.close();
mocksControl.replay();
assertTrue(fileTrackExporter.writeTrack(outputStream));
@@ -17,7 +17,6 @@ package com.google.android.apps.mytracks.io.file.exporter;
import com.google.android.apps.mytracks.content.DescriptionGenerator;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.file.exporter.KmlTrackWriter;
import com.google.android.apps.mytracks.stats.TripStatistics;
import android.location.Location;
@@ -5,7 +5,6 @@ import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.exporter.TrackWriter;
import android.test.AndroidTestCase;
@@ -117,11 +116,12 @@ public abstract class TrackWriterTest extends AndroidTestCase {
protected String writeTrack(TrackWriter trackWriter) throws Exception {
OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE);
trackWriter.prepare(output);
trackWriter.writeHeader(track);
trackWriter.writeBeginWaypoints();
trackWriter.writeHeader(new Track[] {track});
trackWriter.writeBeginWaypoints(track);
trackWriter.writeWaypoint(wp1);
trackWriter.writeWaypoint(wp2);
trackWriter.writeEndWaypoints();
trackWriter.writeBeginTracks();
trackWriter.writeBeginTrack(track, location1);
trackWriter.writeOpenSegment();
trackWriter.writeLocation(location1);
@@ -132,7 +132,9 @@ public abstract class TrackWriterTest extends AndroidTestCase {
trackWriter.writeLocation(location4);
trackWriter.writeCloseSegment();
trackWriter.writeEndTrack(track, location4);
trackWriter.writeEndTracks();
trackWriter.writeFooter();
trackWriter.close();
return output.toString();
}