diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxTrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxTrackWriter.java index f5894fc7c..1e0f128f9 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxTrackWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxTrackWriter.java @@ -20,51 +20,41 @@ import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.StringUtils; +import com.google.android.maps.mytracks.R; +import android.content.Context; import android.location.Location; -import android.os.Build; import java.io.OutputStream; import java.io.PrintWriter; -import java.nio.charset.Charset; import java.text.NumberFormat; -import java.util.Date; import java.util.Locale; /** - * Log of one track. + * Write track as GPX to a file. * * @author Sandor Dornbush */ public class GpxTrackWriter implements TrackFormatWriter { - private final NumberFormat elevationFormatter; - private final NumberFormat coordinateFormatter; - private PrintWriter pw = null; - private Track track; - - public GpxTrackWriter() { + private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US); + private static final NumberFormat COORDINATE_FORMAT = NumberFormat.getInstance(Locale.US); + static { // GPX readers expect to see fractional numbers with US-style punctuation. // That is, they want periods for decimal points, rather than commas. - elevationFormatter = NumberFormat.getInstance(Locale.US); - elevationFormatter.setMaximumFractionDigits(1); - elevationFormatter.setGroupingUsed(false); + ELEVATION_FORMAT.setMaximumFractionDigits(1); + ELEVATION_FORMAT.setGroupingUsed(false); - coordinateFormatter = NumberFormat.getInstance(Locale.US); - coordinateFormatter.setMaximumFractionDigits(5); - coordinateFormatter.setMaximumIntegerDigits(3); - coordinateFormatter.setGroupingUsed(false); + COORDINATE_FORMAT.setMaximumFractionDigits(5); + COORDINATE_FORMAT.setMaximumIntegerDigits(3); + COORDINATE_FORMAT.setGroupingUsed(false); } - private String formatLocation(Location l) { - return "lat=\"" + coordinateFormatter.format(l.getLatitude()) - + "\" lon=\"" + coordinateFormatter.format(l.getLongitude()) + "\""; - } + private final Context context; + private Track track; + private PrintWriter printWriter; - @SuppressWarnings("hiding") - @Override - public void prepare(Track track, OutputStream out) { - this.track = track; - this.pw = new PrintWriter(out); + public GpxTrackWriter(Context context) { + this.context = context; } @Override @@ -72,81 +62,85 @@ public class GpxTrackWriter implements TrackFormatWriter { return TrackFileFormat.GPX.getExtension(); } + @Override + public void prepare(Track aTrack, OutputStream outputStream) { + this.track = aTrack; + this.printWriter = new PrintWriter(outputStream); + } + + @Override + public void close() { + if (printWriter != null) { + printWriter.close(); + printWriter = null; + } + } + @Override public void writeHeader() { - if (pw != null) { - pw.format("\n", - Charset.defaultCharset().name()); - pw.println(""); - pw.println(""); - // TODO: Author etc. + if (printWriter != null) { + printWriter.println(""); + printWriter.println(""); + printWriter.println(""); + printWriter.println("" + StringUtils.stringAsCData(track.getName()) + ""); + printWriter.println("" + StringUtils.stringAsCData(track.getDescription()) + ""); + printWriter.println(""); } } @Override public void writeFooter() { - if (pw != null) { - pw.println(""); + if (printWriter != null) { + printWriter.println(""); } } @Override - public void writeBeginTrack(Location firstPoint) { - if (pw != null) { - pw.println(""); - pw.println("" + StringUtils.stringAsCData(track.getName()) - + ""); - pw.println("" + StringUtils.stringAsCData(track.getDescription()) - + ""); - pw.println("" + track.getId() + ""); - pw.println("c0c0c0"); + public void writeBeginTrack(Location firstLocation) { + if (printWriter != null) { + printWriter.println(""); + printWriter.println("" + StringUtils.stringAsCData(track.getName()) + ""); + printWriter.println("" + StringUtils.stringAsCData(track.getDescription()) + ""); + printWriter.println("c0c0c0"); } } @Override - public void writeEndTrack(Location lastPoint) { - if (pw != null) { - pw.println(""); + public void writeEndTrack(Location lastLocation) { + if (printWriter != null) { + printWriter.println(""); } } @Override public void writeOpenSegment() { - pw.println(""); + printWriter.println(""); } @Override public void writeCloseSegment() { - pw.println(""); + printWriter.println(""); } @Override - public void writeLocation(Location l) { - if (pw != null) { - pw.println(""); - Date d = new Date(l.getTime()); - pw.println("" + elevationFormatter.format(l.getAltitude()) + ""); - pw.println(""); - pw.println(""); - } - } - - @Override - public void close() { - if (pw != null) { - pw.close(); - pw = null; + public void writeLocation(Location location) { + if (printWriter != null) { + printWriter.println(""); + printWriter.println("" + ELEVATION_FORMAT.format(location.getAltitude()) + ""); + printWriter.println( + ""); + printWriter.println(""); } } @@ -162,18 +156,28 @@ public class GpxTrackWriter implements TrackFormatWriter { @Override public void writeWaypoint(Waypoint waypoint) { - if (pw != null) { - Location l = waypoint.getLocation(); - if (l != null) { - pw.println(""); - pw.println("" + elevationFormatter.format(l.getAltitude()) + ""); - pw.println(""); - pw.println("" + StringUtils.stringAsCData(waypoint.getName()) - + ""); - pw.println("" - + StringUtils.stringAsCData(waypoint.getDescription()) + ""); - pw.println(""); + if (printWriter != null) { + Location location = waypoint.getLocation(); + if (location != null) { + printWriter.println(""); + printWriter.println("" + ELEVATION_FORMAT.format(location.getAltitude()) + ""); + printWriter.println( + ""); + printWriter.println("" + StringUtils.stringAsCData(waypoint.getName()) + ""); + printWriter.println( + "" + StringUtils.stringAsCData(waypoint.getDescription()) + ""); + printWriter.println(""); } } } + + /** + * Formats a location with latitude and longitude coordinates. + * + * @param location the location + */ + private String formatLocation(Location location) { + return "lat=\"" + COORDINATE_FORMAT.format(location.getLatitude()) + "\" lon=\"" + + COORDINATE_FORMAT.format(location.getLongitude()) + "\""; + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlTrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlTrackWriter.java index 3ff1d1ec5..019c23dc8 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlTrackWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlTrackWriter.java @@ -24,6 +24,7 @@ import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat; +import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.maps.mytracks.R; import com.google.common.annotations.VisibleForTesting; @@ -65,7 +66,7 @@ public class KmlTrackWriter implements TrackFormatWriter { private boolean hasCadence; private boolean hasHeartRate; private boolean hasBatteryLevel; - + public KmlTrackWriter(Context context) { this(context, new DescriptionGeneratorImpl(context)); } @@ -231,7 +232,8 @@ public class KmlTrackWriter implements TrackFormatWriter { @Override public void writeLocation(Location location) { if (printWriter != null) { - printWriter.println("" + StringUtils.formatXmlDateTime(location.getTime()) + ""); + printWriter.println( + "" + FileUtils.FILE_TIMESTAMP_FORMAT.format(location.getTime()) + ""); printWriter.println( "" + location.getLongitude() + " " + location.getLatitude() + " " + location.getAltitude() + ""); @@ -347,7 +349,7 @@ public class KmlTrackWriter implements TrackFormatWriter { /** * Writes a sensor style. - * + * * @param name the name of the sesnor * @param displayName the sensor display name */ diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterFactory.java index 49f1f9f01..5af558ae0 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterFactory.java @@ -38,7 +38,7 @@ public class TrackWriterFactory { GPX { @Override TrackFormatWriter newFormatWriter(Context context) { - return new GpxTrackWriter(); + return new GpxTrackWriter(context); } }, KML { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java index 61efffe2d..b77f737c5 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java @@ -144,15 +144,6 @@ public class StringUtils { BASE_XML_DATE_FORMAT.setTimeZone(new SimpleTimeZone(0, "UTC")); } - /** - * Formats the time to the XML date time format. - * - * @param time time in milliseconds - */ - public static final String formatXmlDateTime(long time) { - return BASE_XML_DATE_FORMAT.format(new Date(time)); - } - private static final Pattern XML_DATE_EXTRAS_PATTERN = Pattern.compile("^(\\.\\d+)?(?:Z|([+-])(\\d{2}):(\\d{2}))?$"); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxTrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxTrackWriterTest.java index 36c78a33c..660cdec80 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxTrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxTrackWriterTest.java @@ -1,23 +1,34 @@ -// Copyright 2010 Google Inc. All Rights Reserved. +/* + * 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.io.file; -import com.google.android.apps.mytracks.io.file.GpxTrackWriter; -import com.google.android.apps.mytracks.io.file.TrackFormatWriter; +import java.util.List; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.List; - /** - * Tests for the GPX track exporter. + * Tests for {@link GpxTrackWriter}. * * @author Rodrigo Damazio */ public class GpxTrackWriterTest extends TrackFormatWriterTest { public void testXmlOutput() throws Exception { - TrackFormatWriter writer = new GpxTrackWriter(); + TrackFormatWriter writer = new GpxTrackWriter(getContext()); String result = writeTrack(writer); Document doc = parseXmlDocument(result); @@ -25,44 +36,41 @@ public class GpxTrackWriterTest extends TrackFormatWriterTest { Element trackTag = getChildElement(gpxTag, "trk"); assertEquals(TRACK_NAME, getChildTextValue(trackTag, "name")); assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackTag, "desc")); - assertEquals(Long.toString(TRACK_ID), - getChildTextValue(trackTag, "number")); List segmentTags = getChildElements(trackTag, "trkseg", 2); List segPointTags = getChildElements(segmentTags.get(0), "trkpt", 2); - assertTagMatchesLocation(segPointTags.get(0), - "0", "0", "1970-01-01T02:46:40Z", "0"); - assertTagMatchesLocation(segPointTags.get(1), - "1", "-1", "1970-01-01T02:46:41Z", "5000000"); + assertTagMatchesLocation(segPointTags.get(0), "0", "0", "1970-01-01T02:46:40Z", "0"); + assertTagMatchesLocation(segPointTags.get(1), "1", "-1", "1970-01-01T02:46:41Z", "5000000"); segPointTags = getChildElements(segmentTags.get(1), "trkpt", 2); - assertTagMatchesLocation(segPointTags.get(0), - "2", "-2", "1970-01-01T02:46:42Z", "10000000"); - assertTagMatchesLocation(segPointTags.get(1), - "3", "-3", "1970-01-01T02:46:43Z", "15000000"); + assertTagMatchesLocation(segPointTags.get(0), "2", "-2", "1970-01-01T02:46:42Z", "10000000"); + assertTagMatchesLocation(segPointTags.get(1), "3", "-3", "1970-01-01T02:46:43Z", "15000000"); List waypointTags = getChildElements(gpxTag, "wpt", 2); Element wptTag = waypointTags.get(0); assertEquals(WAYPOINT1_NAME, getChildTextValue(wptTag, "name")); assertEquals(WAYPOINT1_DESCRIPTION, getChildTextValue(wptTag, "desc")); - assertTagMatchesLocation(wptTag, - "1", "-1", "1970-01-01T02:46:41Z", "5000000"); + assertTagMatchesLocation(wptTag, "1", "-1", "1970-01-01T02:46:41Z", "5000000"); wptTag = waypointTags.get(1); assertEquals(WAYPOINT2_NAME, getChildTextValue(wptTag, "name")); assertEquals(WAYPOINT2_DESCRIPTION, getChildTextValue(wptTag, "desc")); - assertTagMatchesLocation(wptTag, - "2", "-2", "1970-01-01T02:46:42Z", "10000000"); + assertTagMatchesLocation(wptTag, "2", "-2", "1970-01-01T02:46:42Z", "10000000"); } /** - * Asserts that the given tag describes the location given by the - * Strings lat, lon, time, and ele. + * Asserts that the given tag describes a location. + * + * @param tag the tag + * @param latitude the location's latitude + * @param longitude the location's longitude + * @param time the location's time + * @param elevation the location's elevation */ - private void assertTagMatchesLocation(Element tag, String lat, - String lon, String time, String ele) { - assertEquals(lat, tag.getAttribute("lat")); - assertEquals(lon, tag.getAttribute("lon")); + private void assertTagMatchesLocation( + Element tag, String latitude, String longitude, String time, String elevation) { + assertEquals(latitude, tag.getAttribute("lat")); + assertEquals(longitude, tag.getAttribute("lon")); assertEquals(time, getChildTextValue(tag, "time")); - assertEquals(ele, getChildTextValue(tag, "ele")); + assertEquals(elevation, getChildTextValue(tag, "ele")); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java index 93a6e2804..9d23eb5e0 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java @@ -13,7 +13,6 @@ * License for the specific language governing permissions and limitations under * the License. */ - package com.google.android.apps.mytracks.io.file; import com.google.android.apps.mytracks.content.DescriptionGenerator; @@ -34,6 +33,7 @@ import org.w3c.dom.Element; * @author Rodrigo Damazio */ public class KmlTrackWriterTest extends TrackFormatWriterTest { + private static final String FULL_TRACK_DESCRIPTION = "full track description"; /** diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackFormatWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackFormatWriterTest.java index 6af065c5d..bba7f8df7 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackFormatWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackFormatWriterTest.java @@ -45,7 +45,6 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase { protected static final String WAYPOINT2_NAME = "point]]>2"; protected static final String WAYPOINT2_DESCRIPTION = "point 2]]>description"; private static final int BUFFER_SIZE = 10240; - protected static final long TRACK_ID = 12345L; protected Track track; protected MyTracksLocation location1, location2, location3, location4; protected Waypoint wp1, wp2; @@ -55,7 +54,6 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase { super.setUp(); track = new Track(); - track.setId(TRACK_ID); track.setName(TRACK_NAME); track.setDescription(TRACK_DESCRIPTION);