forked from upstream-mirrors/OpenTracks
Merge heads
This commit is contained in:
+5
-5
@@ -54,12 +54,12 @@ import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* Abstract class for various importers like {@link GpxImporter} and
|
||||
* {@link KmlImporter}.
|
||||
* Abstract class for various file track importers like {@link GpxFileTrackImporter} and
|
||||
* {@link KmlFileTrackImporter}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
abstract class AbstractImporter extends DefaultHandler {
|
||||
abstract class AbstractFileTrackImporter extends DefaultHandler implements TrackImporter {
|
||||
|
||||
/**
|
||||
* Data for the current track.
|
||||
@@ -131,12 +131,12 @@ abstract class AbstractImporter extends DefaultHandler {
|
||||
* @param importTrackId the track id to import to. -1L to import to a new
|
||||
* track.
|
||||
*/
|
||||
protected AbstractImporter(Context context, long importTrackId) {
|
||||
protected AbstractFileTrackImporter(Context context, long importTrackId) {
|
||||
this(context, importTrackId, MyTracksProviderUtils.Factory.get(context));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected AbstractImporter(
|
||||
protected AbstractFileTrackImporter(
|
||||
Context context, long importTrackId, MyTracksProviderUtils myTracksProviderUtils) {
|
||||
this.context = context;
|
||||
this.importTrackId = importTrackId;
|
||||
+3
-3
@@ -31,7 +31,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class GpxImporter extends AbstractImporter {
|
||||
public class GpxFileTrackImporter extends AbstractFileTrackImporter {
|
||||
|
||||
private static final String TAG_DESCRIPTION = "desc";
|
||||
private static final String TAG_COMMENT = "cmt";
|
||||
@@ -54,12 +54,12 @@ public class GpxImporter extends AbstractImporter {
|
||||
* @param context the context
|
||||
* @param importTrackId track id to import to. -1L to import to a new track.
|
||||
*/
|
||||
public GpxImporter(Context context, long importTrackId) {
|
||||
public GpxFileTrackImporter(Context context, long importTrackId) {
|
||||
super(context, importTrackId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public GpxImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) {
|
||||
public GpxFileTrackImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) {
|
||||
super(context, -1L, myTracksProviderUtils);
|
||||
}
|
||||
|
||||
@@ -158,10 +158,10 @@ public class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
*/
|
||||
private boolean importFile(final File file) {
|
||||
try {
|
||||
AbstractImporter importer = trackFileFormat == TrackFileFormat.KML ? new KmlImporter(
|
||||
TrackImporter trackImporter = trackFileFormat == TrackFileFormat.KML ? new KmlFileTrackImporter(
|
||||
context, -1L)
|
||||
: new GpxImporter(context, -1L);
|
||||
long trackIds[] = importer.importFile(new FileInputStream(file));
|
||||
: new GpxFileTrackImporter(context, -1L);
|
||||
long trackIds[] = trackImporter.importFile(new FileInputStream(file));
|
||||
int length = trackIds.length;
|
||||
if (length > 0) {
|
||||
trackId = trackIds[length - 1];
|
||||
|
||||
+8
-3
@@ -36,7 +36,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class KmlImporter extends AbstractImporter {
|
||||
public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
||||
|
||||
private static final String CADENCE = "cadence";
|
||||
private static final String HEART_RATE = "heart_rate";
|
||||
@@ -61,6 +61,7 @@ public class KmlImporter extends AbstractImporter {
|
||||
|
||||
private static final String ATTRIBUTE_NAME = "name";
|
||||
|
||||
private boolean trackStarted = false;
|
||||
private String sensorName;
|
||||
private ArrayList<Location> locationList;
|
||||
private ArrayList<Integer> cadenceList;
|
||||
@@ -73,12 +74,12 @@ public class KmlImporter extends AbstractImporter {
|
||||
* @param context the context
|
||||
* @param importTrackId track id to import to. -1L to import to a new track.
|
||||
*/
|
||||
public KmlImporter(Context context, long importTrackId) {
|
||||
public KmlFileTrackImporter(Context context, long importTrackId) {
|
||||
super(context, importTrackId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public KmlImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) {
|
||||
public KmlFileTrackImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) {
|
||||
super(context, -1L, myTracksProviderUtils);
|
||||
}
|
||||
|
||||
@@ -88,8 +89,12 @@ public class KmlImporter extends AbstractImporter {
|
||||
if (tag.equals(TAG_PLACEMARK)) {
|
||||
onWaypointStart();
|
||||
} else if (tag.equals(TAG_GX_MULTI_TRACK)) {
|
||||
trackStarted = true;
|
||||
onTrackStart();
|
||||
} else if (tag.equals(TAG_GX_TRACK)) {
|
||||
if (!trackStarted) {
|
||||
throw new SAXException("No " + TAG_GX_MULTI_TRACK);
|
||||
}
|
||||
onTrackSegmentStart();
|
||||
} else if (tag.equals(TAG_GX_SIMPLE_ARRAY_DATA)) {
|
||||
onSensorDataStart(attributes);
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
|
||||
import com.google.android.apps.mytracks.io.file.export.CsvTrackWriter;
|
||||
import com.google.android.apps.mytracks.io.file.export.GpxTrackWriter;
|
||||
import com.google.android.apps.mytracks.io.file.export.KmlTrackWriter;
|
||||
import com.google.android.apps.mytracks.io.file.export.TcxTrackWriter;
|
||||
import com.google.android.apps.mytracks.io.file.export.TrackWriter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@@ -12,25 +18,25 @@ import java.util.Locale;
|
||||
public enum TrackFileFormat implements Parcelable {
|
||||
KML {
|
||||
@Override
|
||||
TrackFormatWriter newFormatWriter(Context context) {
|
||||
return new KmlTrackWriter(context);
|
||||
public TrackWriter newTrackWriter(Context context, boolean inZip) {
|
||||
return new KmlTrackWriter(context, inZip);
|
||||
}
|
||||
},
|
||||
GPX {
|
||||
@Override
|
||||
TrackFormatWriter newFormatWriter(Context context) {
|
||||
public TrackWriter newTrackWriter(Context context, boolean inZip) {
|
||||
return new GpxTrackWriter(context);
|
||||
}
|
||||
},
|
||||
CSV {
|
||||
@Override
|
||||
public TrackFormatWriter newFormatWriter(Context context) {
|
||||
public TrackWriter newTrackWriter(Context context, boolean inZip) {
|
||||
return new CsvTrackWriter(context);
|
||||
}
|
||||
},
|
||||
TCX {
|
||||
@Override
|
||||
public TrackFormatWriter newFormatWriter(Context context) {
|
||||
public TrackWriter newTrackWriter(Context context, boolean inZip) {
|
||||
return new TcxTrackWriter(context);
|
||||
}
|
||||
};
|
||||
@@ -58,9 +64,9 @@ public enum TrackFileFormat implements Parcelable {
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates and returns a new format writer for each format.
|
||||
* Creates a new track writer for the format.
|
||||
*/
|
||||
abstract TrackFormatWriter newFormatWriter(Context context);
|
||||
public abstract TrackWriter newTrackWriter(Context context, boolean inZip);
|
||||
|
||||
/**
|
||||
* Returns the mime type for each format.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Interface for a track importer.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface TrackImporter {
|
||||
|
||||
public long[] importFile(InputStream inputStream)
|
||||
throws SAXException, IOException, ParserConfigurationException;
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013 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.export;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract class for {@link TrackExporter}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
abstract class AbstractTrackExporter implements TrackExporter {
|
||||
|
||||
private static final String TAG = AbstractTrackExporter.class.getSimpleName();
|
||||
|
||||
private Thread writeThread;
|
||||
private boolean success = false;
|
||||
|
||||
@Override
|
||||
public void writeTrack(final OutputStream outputStream) {
|
||||
writeThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
performWrite(outputStream);
|
||||
success = true;
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Unable to perform write", e);
|
||||
success = false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to perform write", e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
writeThread.start();
|
||||
try {
|
||||
writeThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Interrupted while waiting for write thread to finish", e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
abstract void performWrite(OutputStream outputStream) throws InterruptedException, IOException;
|
||||
}
|
||||
+3
-7
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
@@ -21,6 +21,7 @@ import com.google.android.apps.mytracks.content.Sensor.SensorData;
|
||||
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.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
@@ -48,7 +49,7 @@ import java.text.NumberFormat;
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class CsvTrackWriter implements TrackFormatWriter {
|
||||
public class CsvTrackWriter implements TrackWriter {
|
||||
|
||||
private static final NumberFormat SHORT_FORMAT = NumberFormat.getInstance();
|
||||
|
||||
@@ -77,11 +78,6 @@ public class CsvTrackWriter implements TrackFormatWriter {
|
||||
pointIndex = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeader(Track track) {
|
||||
writeCommaSeparatedLine(context.getString(R.string.generic_name),
|
||||
+50
-111
@@ -14,7 +14,7 @@
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
@@ -22,13 +22,13 @@ 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;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
@@ -38,32 +38,12 @@ import java.io.OutputStream;
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TrackWriter {
|
||||
|
||||
/**
|
||||
* Listener for when a track location is written.
|
||||
*/
|
||||
public interface OnWriteListener {
|
||||
|
||||
/**
|
||||
* When a track location is written.
|
||||
*
|
||||
* @param number the location number
|
||||
* @param max the maximum number of locations in a track, for calculation of completion
|
||||
* percentage
|
||||
*/
|
||||
public void onWrite(int number, int max);
|
||||
}
|
||||
|
||||
private final static String TAG = TrackWriter.class.getSimpleName();
|
||||
public class FileTrackExporter extends AbstractTrackExporter {
|
||||
|
||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||
private final Track[] tracks;
|
||||
private final TrackFormatWriter trackFormatWriter;
|
||||
private final OnWriteListener onWriteListener;
|
||||
|
||||
private Thread writeThread;
|
||||
private boolean success = false;
|
||||
private final TrackWriter trackWriter;
|
||||
private final TrackExporterListener trackExporterListener;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -72,86 +52,41 @@ public class TrackWriter {
|
||||
* @param myTracksProviderUtils the my tracks provider utils
|
||||
* @param tracks the tracks
|
||||
* @param trackFileFormat the track file format
|
||||
* @param onWriteListener the on write listener
|
||||
* @param trackExporterListener the track export listener
|
||||
*/
|
||||
public TrackWriter(Context context, MyTracksProviderUtils myTracksProviderUtils, Track[] tracks,
|
||||
TrackFileFormat trackFileFormat, OnWriteListener onWriteListener) {
|
||||
this(myTracksProviderUtils, tracks, trackFileFormat.newFormatWriter(context), onWriteListener);
|
||||
public FileTrackExporter(MyTracksProviderUtils myTracksProviderUtils,
|
||||
Track[] tracks, TrackFileFormat trackFileFormat, Context context, boolean inZip,
|
||||
TrackExporterListener trackExporterListener) {
|
||||
this(myTracksProviderUtils, tracks, trackFileFormat.newTrackWriter(context, inZip),
|
||||
trackExporterListener);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public TrackWriter(MyTracksProviderUtils myTracksProviderUtils, Track[] tracks,
|
||||
TrackFormatWriter trackFormatWriter, OnWriteListener onWriteListener) {
|
||||
public FileTrackExporter(MyTracksProviderUtils myTracksProviderUtils, Track[] tracks,
|
||||
TrackWriter trackWriter, TrackExporterListener trackExporterListener) {
|
||||
this.myTracksProviderUtils = myTracksProviderUtils;
|
||||
this.tracks = tracks;
|
||||
this.trackFormatWriter = trackFormatWriter;
|
||||
this.onWriteListener = onWriteListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the write completed successfully.
|
||||
*/
|
||||
public boolean wasSuccess() {
|
||||
return success;
|
||||
this.trackWriter = trackWriter;
|
||||
this.trackExporterListener = trackExporterListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given track to the output stream.
|
||||
*
|
||||
* @param outputStream the output stream.
|
||||
*/
|
||||
public void writeTrack(final OutputStream outputStream) {
|
||||
writeThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
trackFormatWriter.prepare(outputStream);
|
||||
trackFormatWriter.writeHeader(tracks[0]);
|
||||
long startTime = tracks[0].getTripStatistics().getStartTime();
|
||||
for (int i = 0; i < tracks.length; i++) {
|
||||
writeWaypoints(tracks[i]);
|
||||
long offset = tracks[i].getTripStatistics().getStartTime() - startTime;
|
||||
writeLocations(tracks[i], offset);
|
||||
}
|
||||
trackFormatWriter.writeFooter();
|
||||
trackFormatWriter.close();
|
||||
success = true;
|
||||
} catch (InterruptedException e) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
writeThread.start();
|
||||
try {
|
||||
writeThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Interrupted while waiting for write to complete", e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any in-progress writes.
|
||||
*/
|
||||
public void stopWriteTrack() {
|
||||
if (writeThread != null && writeThread.isAlive()) {
|
||||
Log.i(TAG, "Attempting to stop track write");
|
||||
writeThread.interrupt();
|
||||
|
||||
try {
|
||||
writeThread.join();
|
||||
Log.i(TAG, "Track write stopped");
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Interrupted while waiting for writer to stop", e);
|
||||
success = false;
|
||||
}
|
||||
@Override
|
||||
void performWrite(OutputStream outputStream) throws InterruptedException {
|
||||
trackWriter.prepare(outputStream);
|
||||
trackWriter.writeHeader(tracks[0]);
|
||||
long startTime = tracks[0].getTripStatistics().getStartTime();
|
||||
for (int i = 0; i < tracks.length; i++) {
|
||||
writeWaypoints(tracks[i]);
|
||||
long offset = tracks[i].getTripStatistics().getStartTime() - startTime;
|
||||
writeLocations(tracks[i], offset);
|
||||
}
|
||||
trackWriter.writeFooter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the waypoints.
|
||||
*/
|
||||
private void writeWaypoints(Track track) {
|
||||
private void writeWaypoints(Track track) throws InterruptedException {
|
||||
/*
|
||||
* TODO: Stream through the waypoints in chunks. I am leaving the number of
|
||||
* waypoints very high which should not be a problem because we don't try to
|
||||
@@ -168,12 +103,15 @@ public class TrackWriter {
|
||||
* first waypoint holds the stats for the track.
|
||||
*/
|
||||
while (cursor.moveToNext()) {
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
if (!hasWaypoints) {
|
||||
trackFormatWriter.writeBeginWaypoints();
|
||||
trackWriter.writeBeginWaypoints();
|
||||
hasWaypoints = true;
|
||||
}
|
||||
Waypoint waypoint = myTracksProviderUtils.createWaypoint(cursor);
|
||||
trackFormatWriter.writeWaypoint(waypoint);
|
||||
trackWriter.writeWaypoint(waypoint);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -182,7 +120,7 @@ public class TrackWriter {
|
||||
}
|
||||
}
|
||||
if (hasWaypoints) {
|
||||
trackFormatWriter.writeEndWaypoints();
|
||||
trackWriter.writeEndWaypoints();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,62 +134,63 @@ public class TrackWriter {
|
||||
TrackWriterLocationFactory locationFactory = new TrackWriterLocationFactory();
|
||||
LocationIterator iterator = myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
track.getId(), -1L, false, locationFactory);
|
||||
|
||||
|
||||
try {
|
||||
int locationNumber = 0;
|
||||
while (iterator.hasNext()) {
|
||||
Location location = iterator.next();
|
||||
setLocationTime(location, offset);
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
Location location = iterator.next();
|
||||
|
||||
setLocationTime(location, offset);
|
||||
locationNumber++;
|
||||
|
||||
boolean isLocationValid = LocationUtils.isValidLocation(location);
|
||||
boolean isSegmentValid = isLocationValid && isLastLocationValid;
|
||||
if (!wroteTrack && isSegmentValid) {
|
||||
// Found the first two consecutive locations that are valid
|
||||
trackFormatWriter.writeBeginTrack(track, locationFactory.lastLocation);
|
||||
// Found the first two consecutive locations that are valid
|
||||
trackWriter.writeBeginTrack(track, locationFactory.lastLocation);
|
||||
wroteTrack = true;
|
||||
}
|
||||
|
||||
if (isSegmentValid) {
|
||||
if (!wroteSegment) {
|
||||
// Start a segment
|
||||
trackFormatWriter.writeOpenSegment();
|
||||
trackWriter.writeOpenSegment();
|
||||
wroteSegment = true;
|
||||
|
||||
// Write the previous location, which we had previously skipped
|
||||
trackFormatWriter.writeLocation(locationFactory.lastLocation);
|
||||
trackWriter.writeLocation(locationFactory.lastLocation);
|
||||
}
|
||||
|
||||
// Write the current location
|
||||
trackFormatWriter.writeLocation(location);
|
||||
if (onWriteListener != null) {
|
||||
onWriteListener.onWrite(locationNumber, track.getNumberOfPoints());
|
||||
trackWriter.writeLocation(location);
|
||||
if (trackExporterListener != null) {
|
||||
trackExporterListener.onProgressUpdate(locationNumber, track.getNumberOfPoints());
|
||||
}
|
||||
} else {
|
||||
if (wroteSegment) {
|
||||
trackFormatWriter.writeCloseSegment();
|
||||
trackWriter.writeCloseSegment();
|
||||
wroteSegment = false;
|
||||
}
|
||||
}
|
||||
locationFactory.swapLocations();
|
||||
isLastLocationValid = isLocationValid;
|
||||
}
|
||||
|
||||
|
||||
if (wroteSegment) {
|
||||
trackFormatWriter.writeCloseSegment();
|
||||
trackWriter.writeCloseSegment();
|
||||
wroteSegment = false;
|
||||
}
|
||||
if (wroteTrack) {
|
||||
Location lastValidTrackPoint = myTracksProviderUtils.getLastValidTrackPoint(track.getId());
|
||||
setLocationTime(lastValidTrackPoint, offset);
|
||||
trackFormatWriter.writeEndTrack(track, lastValidTrackPoint);
|
||||
trackWriter.writeEndTrack(track, lastValidTrackPoint);
|
||||
} else {
|
||||
// Write an empty track
|
||||
trackFormatWriter.writeBeginTrack(track, null);
|
||||
trackFormatWriter.writeEndTrack(track, null);
|
||||
trackWriter.writeBeginTrack(track, null);
|
||||
trackWriter.writeEndTrack(track, null);
|
||||
}
|
||||
} finally {
|
||||
iterator.close();
|
||||
@@ -269,7 +208,7 @@ public class TrackWriter {
|
||||
location.setTime(location.getTime() - offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Track writer location factory. Keeping the last two locations.
|
||||
*
|
||||
+3
-10
@@ -14,10 +14,11 @@
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
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.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
@@ -34,7 +35,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class GpxTrackWriter implements TrackFormatWriter {
|
||||
public class GpxTrackWriter implements TrackWriter {
|
||||
|
||||
private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat COORDINATE_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
@@ -68,14 +69,6 @@ public class GpxTrackWriter implements TrackFormatWriter {
|
||||
this.printWriter = new PrintWriter(outputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
printWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeader(Track track) {
|
||||
if (printWriter != null) {
|
||||
+23
-17
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.DescriptionGenerator;
|
||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
||||
@@ -25,6 +25,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.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
@@ -35,6 +36,7 @@ import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -44,7 +46,7 @@ import java.util.ArrayList;
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class KmlTrackWriter implements TrackFormatWriter {
|
||||
public class KmlTrackWriter implements TrackWriter {
|
||||
|
||||
private static final String WAYPOINT_STYLE = "waypoint";
|
||||
private static final String STATISTICS_STYLE = "statistics";
|
||||
@@ -68,8 +70,10 @@ public class KmlTrackWriter implements TrackFormatWriter {
|
||||
TRACK_ICON = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
|
||||
|
||||
private final Context context;
|
||||
private final boolean inKmz;
|
||||
private final DescriptionGenerator descriptionGenerator;
|
||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||
|
||||
private PrintWriter printWriter;
|
||||
private ArrayList<Integer> powerList = new ArrayList<Integer>();
|
||||
private ArrayList<Integer> cadenceList = new ArrayList<Integer>();
|
||||
@@ -78,13 +82,14 @@ public class KmlTrackWriter implements TrackFormatWriter {
|
||||
private boolean hasCadence;
|
||||
private boolean hasHeartRate;
|
||||
|
||||
public KmlTrackWriter(Context context) {
|
||||
this(context, new DescriptionGeneratorImpl(context));
|
||||
public KmlTrackWriter(Context context, boolean inKmz) {
|
||||
this(context, inKmz, new DescriptionGeneratorImpl(context));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
KmlTrackWriter(Context context, DescriptionGenerator descriptionGenerator) {
|
||||
KmlTrackWriter(Context context, boolean inKmz, DescriptionGenerator descriptionGenerator) {
|
||||
this.context = context;
|
||||
this.inKmz = inKmz;
|
||||
this.descriptionGenerator = descriptionGenerator;
|
||||
this.myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
}
|
||||
@@ -99,14 +104,6 @@ public class KmlTrackWriter implements TrackFormatWriter {
|
||||
this.printWriter = new PrintWriter(outputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
printWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeader(Track track) {
|
||||
if (printWriter != null) {
|
||||
@@ -335,9 +332,8 @@ public class KmlTrackWriter implements TrackFormatWriter {
|
||||
if (location != null) {
|
||||
printWriter.println("<PhotoOverlay>");
|
||||
printWriter.println("<name>" + StringUtils.formatCData(name) + "</name>");
|
||||
printWriter.println("<description>"
|
||||
+ StringUtils.formatCData(StringUtils.getCategoryDescription(category, description))
|
||||
+ "</description>");
|
||||
printWriter.println(
|
||||
"<description>" + StringUtils.formatCData(description) + "</description>");
|
||||
printWriter.print("<Camera>");
|
||||
printWriter.print("<longitude>" + location.getLongitude() + "</longitude>");
|
||||
printWriter.print("<latitude>" + location.getLatitude() + "</latitude>");
|
||||
@@ -345,8 +341,18 @@ public class KmlTrackWriter implements TrackFormatWriter {
|
||||
printWriter.print("<heading>" + heading + "</heading>");
|
||||
printWriter.print("<tilt>90</tilt>");
|
||||
printWriter.println("</Camera>");
|
||||
printWriter.println("<TimeStamp><when>"
|
||||
+ StringUtils.formatDateTimeIso8601(location.getTime()) + "</when></TimeStamp>");
|
||||
printWriter.println("<styleUrl>#" + styleName + "</styleUrl>");
|
||||
printWriter.println("<Icon><href>" + Uri.decode(photoUrl) + "</href></Icon>");
|
||||
writeCategory(category);
|
||||
if (inKmz) {
|
||||
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>");
|
||||
}
|
||||
|
||||
printWriter.print("<ViewVolume>");
|
||||
printWriter.print("<near>10</near>");
|
||||
printWriter.print("<leftFov>-60</leftFov>");
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2013 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.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* KMZ track exporter.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class KmzTrackExporter extends AbstractTrackExporter {
|
||||
|
||||
public static final String KMZ_IMAGES_DIR = "images";
|
||||
public static final String KMZ_EXTENSION = "kmz";
|
||||
public static final int BUFFER_SIZE = 4096;
|
||||
public static final String KML_FILE_NAME = "doc.kml";
|
||||
|
||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||
private final FileTrackExporter fileTrackExporter;
|
||||
private final Track[] tracks;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param myTracksProviderUtils the my tracks provider utils
|
||||
* @param fileTrackExporter the file track exporter
|
||||
* @param tracks the tracks to export
|
||||
*/
|
||||
public KmzTrackExporter(MyTracksProviderUtils myTracksProviderUtils,
|
||||
FileTrackExporter fileTrackExporter, Track[] tracks) {
|
||||
this.myTracksProviderUtils = myTracksProviderUtils;
|
||||
this.fileTrackExporter = fileTrackExporter;
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuccess() {
|
||||
return fileTrackExporter.isSuccess() && super.isSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
void performWrite(OutputStream outputStream) throws InterruptedException, IOException {
|
||||
ZipOutputStream zipOutputStream = null;
|
||||
try {
|
||||
zipOutputStream = new ZipOutputStream(outputStream);
|
||||
|
||||
// Add kml file
|
||||
ZipEntry zipEntry = new ZipEntry(KML_FILE_NAME);
|
||||
zipOutputStream.putNextEntry(zipEntry);
|
||||
|
||||
fileTrackExporter.writeTrack(zipOutputStream);
|
||||
zipOutputStream.closeEntry();
|
||||
if (!fileTrackExporter.isSuccess()) {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
// Add photos
|
||||
addImages(zipOutputStream);
|
||||
} finally {
|
||||
if (zipOutputStream != null) {
|
||||
zipOutputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addImages(ZipOutputStream zipOutputStream) throws InterruptedException, IOException {
|
||||
for (Track track : tracks) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = myTracksProviderUtils.getWaypointCursor(track.getId(), -1L, -1);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
/*
|
||||
* Yes, this will skip the first waypoint and that is intentional as
|
||||
* the first waypoint holds the stats for the track.
|
||||
*/
|
||||
while (cursor.moveToNext()) {
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
Waypoint waypoint = myTracksProviderUtils.createWaypoint(cursor);
|
||||
String photoUrl = waypoint.getPhotoUrl();
|
||||
if (photoUrl != null && !photoUrl.equals("")) {
|
||||
addImage(zipOutputStream, photoUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addImage(ZipOutputStream zipOutputStream, String photoUrl) throws IOException {
|
||||
Uri uri = Uri.parse(photoUrl);
|
||||
ZipEntry zipEntry = new ZipEntry(
|
||||
KMZ_IMAGES_DIR + File.separatorChar + uri.getLastPathSegment());
|
||||
zipOutputStream.putNextEntry(zipEntry);
|
||||
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(new File(uri.getPath()));
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int byteCount = 0;
|
||||
while ((byteCount = fileInputStream.read(buffer)) != -1) {
|
||||
zipOutputStream.write(buffer, 0, byteCount);
|
||||
}
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
fileInputStream.close();
|
||||
}
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -14,8 +14,9 @@
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
@@ -99,7 +100,7 @@ public class SaveActivity extends Activity {
|
||||
saveAsyncTask = (SaveAsyncTask) retained;
|
||||
saveAsyncTask.setActivity(this);
|
||||
} else {
|
||||
saveAsyncTask = new SaveAsyncTask(this, trackFileFormat, trackIds, directory);
|
||||
saveAsyncTask = new SaveAsyncTask(this, trackFileFormat, trackIds, directory, playTrack);
|
||||
saveAsyncTask.execute();
|
||||
}
|
||||
}
|
||||
@@ -121,7 +122,6 @@ public class SaveActivity extends Activity {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
saveAsyncTask.cancel(true);
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
}, directoryDisplayName);
|
||||
return progressDialog;
|
||||
+47
-27
@@ -14,11 +14,12 @@
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
@@ -33,7 +34,7 @@ import android.util.Log;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Async Task to save tracks to the external storage.
|
||||
@@ -48,11 +49,12 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
private final TrackFileFormat trackFileFormat;
|
||||
private final long[] trackIds;
|
||||
private final File directory;
|
||||
private final boolean playTrack;
|
||||
private final Context context;
|
||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||
|
||||
private WakeLock wakeLock;
|
||||
private TrackWriter trackWriter;
|
||||
private TrackExporter trackExporter;
|
||||
|
||||
// true if the AsyncTask has completed
|
||||
private boolean completed;
|
||||
@@ -74,13 +76,15 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
* @param trackIds the track ids to save. To save all, set to size 1 with
|
||||
* trackIds[0] == -1L
|
||||
* @param directory the directory to save to
|
||||
* @param playTrack true to play track
|
||||
*/
|
||||
public SaveAsyncTask(
|
||||
SaveActivity saveActivity, TrackFileFormat trackFileFormat, long[] trackIds, File directory) {
|
||||
public SaveAsyncTask(SaveActivity saveActivity, TrackFileFormat trackFileFormat, long[] trackIds,
|
||||
File directory, boolean playTrack) {
|
||||
this.saveActivity = saveActivity;
|
||||
this.trackFileFormat = trackFileFormat;
|
||||
this.trackIds = trackIds;
|
||||
this.directory = directory;
|
||||
this.playTrack = playTrack;
|
||||
context = saveActivity.getApplicationContext();
|
||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
|
||||
@@ -163,8 +167,9 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
if (trackWriter != null) {
|
||||
trackWriter.stopWriteTrack();
|
||||
completed = true;
|
||||
if (saveActivity != null) {
|
||||
saveActivity.onAsyncTaskCompleted(successCount, totalCount, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,18 +183,21 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
return false;
|
||||
}
|
||||
Track track = tracks[0];
|
||||
boolean useKmz = !playTrack && trackFileFormat == TrackFileFormat.KML;
|
||||
String extension = useKmz ? KmzTrackExporter.KMZ_EXTENSION : trackFileFormat.getExtension();
|
||||
|
||||
// Make sure the file doesn't exist yet (possibly by changing the filename)
|
||||
String fileName = FileUtils.buildUniqueFileName(
|
||||
directory, track.getName(), trackFileFormat.getExtension());
|
||||
String fileName = FileUtils.buildUniqueFileName(directory, track.getName(), extension);
|
||||
if (fileName == null) {
|
||||
Log.d(TAG, "Unable to get a unique filename for " + track.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
trackWriter = new TrackWriter(
|
||||
context, myTracksProviderUtils, tracks, trackFileFormat, new TrackWriter.OnWriteListener() {
|
||||
FileTrackExporter fileTrackExporter = new FileTrackExporter(myTracksProviderUtils, tracks,
|
||||
trackFileFormat, context, useKmz, new TrackExporterListener() {
|
||||
|
||||
@Override
|
||||
public void onWrite(int number, int max) {
|
||||
public void onProgressUpdate(int number, int max) {
|
||||
/*
|
||||
* If only saving one track, update the progress dialog once every
|
||||
* 500 points
|
||||
@@ -200,24 +208,36 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
}
|
||||
});
|
||||
|
||||
File file = null;
|
||||
try {
|
||||
file = new File(directory, fileName);
|
||||
OutputStream outputStream = new FileOutputStream(file);
|
||||
trackWriter.writeTrack(outputStream);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.d(TAG, "File not found " + fileName, e);
|
||||
return false;
|
||||
}
|
||||
trackExporter = useKmz ? new KmzTrackExporter(myTracksProviderUtils, fileTrackExporter, tracks)
|
||||
: fileTrackExporter;
|
||||
|
||||
if (trackWriter.wasSuccess()) {
|
||||
savedPath = file.getAbsolutePath();
|
||||
} else {
|
||||
if (!file.delete()) {
|
||||
Log.w(TAG, "Failed to delete file " + file.getAbsolutePath());
|
||||
File file = new File(directory, fileName);
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(file);
|
||||
trackExporter.writeTrack(fileOutputStream);
|
||||
|
||||
if (trackExporter.isSuccess()) {
|
||||
savedPath = file.getAbsolutePath();
|
||||
return true;
|
||||
} else {
|
||||
if (!file.delete()) {
|
||||
Log.w(TAG, "Failed to delete file " + file.getAbsolutePath());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(TAG, "Unable to open file " + file.getName(), e);
|
||||
return false;
|
||||
} finally {
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to close file output stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return trackWriter.wasSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
+3
-10
@@ -13,13 +13,14 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
@@ -40,7 +41,7 @@ import java.util.Locale;
|
||||
* @author Sandor Dornbush
|
||||
* @author Dominik Rttsches
|
||||
*/
|
||||
public class TcxTrackWriter implements TrackFormatWriter {
|
||||
public class TcxTrackWriter implements TrackWriter {
|
||||
|
||||
/**
|
||||
* TCX sport type. See the TCX spec.
|
||||
@@ -96,14 +97,6 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
||||
this.printWriter = new PrintWriter(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
printWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return TrackFileFormat.TCX.getExtension();
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2011 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.export;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Track exporting for exporting track to an {@link OutputStream}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface TrackExporter {
|
||||
|
||||
/**
|
||||
* Write track to an output stream
|
||||
*
|
||||
* @param outputStream the output stream
|
||||
*/
|
||||
void writeTrack(OutputStream outputStream);
|
||||
|
||||
/**
|
||||
* Returns true if {@link #writeTrack(OutputStream)} completed successfully.
|
||||
*/
|
||||
boolean isSuccess();
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.export;
|
||||
|
||||
/**
|
||||
* Listener for {@link TrackExporter} progress.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface TrackExporterListener {
|
||||
|
||||
/**
|
||||
* Called to update progress.
|
||||
*
|
||||
* @param number the number of locations written
|
||||
* @param max the maximum number of locations in a track, for calculation of
|
||||
* completion percentage
|
||||
*/
|
||||
public void onProgressUpdate(int number, int max);
|
||||
}
|
||||
+2
-7
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
package com.google.android.apps.mytracks.io.file.export;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
@@ -50,7 +50,7 @@ import java.io.OutputStream;
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public interface TrackFormatWriter {
|
||||
public interface TrackWriter {
|
||||
|
||||
/**
|
||||
* Gets the file extension (i.e. gpx, kml, ...)
|
||||
@@ -64,11 +64,6 @@ public interface TrackFormatWriter {
|
||||
*/
|
||||
public void prepare(OutputStream outputStream);
|
||||
|
||||
/**
|
||||
* Closes the underlying file handler.
|
||||
*/
|
||||
public void close();
|
||||
|
||||
/**
|
||||
* Writes the header for a file
|
||||
*
|
||||
@@ -18,7 +18,7 @@ package com.google.android.apps.mytracks.io.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.io.file.KmlImporter;
|
||||
import com.google.android.apps.mytracks.io.file.KmlFileTrackImporter;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.gms.auth.GoogleAuthException;
|
||||
@@ -348,9 +348,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
if (driveFile != null) {
|
||||
InputStream inputStream = downloadDriveFile(driveFile, true);
|
||||
if (inputStream != null) {
|
||||
KmlImporter kmlImporter = new KmlImporter(context, -1L);
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, -1L);
|
||||
try {
|
||||
long[] trackIds = kmlImporter.importFile(inputStream);
|
||||
long[] trackIds = kmlFileTrackImporter.importFile(inputStream);
|
||||
if (trackIds.length == 1) {
|
||||
Track track = myTracksProviderUtils.getTrack(trackIds[0]);
|
||||
if (track == null) {
|
||||
@@ -494,9 +494,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
Log.e(TAG, "Unable to update track. Input stream is null for track " + track.getName());
|
||||
return false;
|
||||
}
|
||||
KmlImporter kmlImporter = new KmlImporter(context, track.getId());
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, track.getId());
|
||||
try {
|
||||
long[] trackIds = kmlImporter.importFile(inputStream);
|
||||
long[] trackIds = kmlFileTrackImporter.importFile(inputStream);
|
||||
if (trackIds.length == 1) {
|
||||
Track newTrack = myTracksProviderUtils.getTrack(trackIds[0]);
|
||||
if (newTrack == null) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.io.file.TrackWriter;
|
||||
import com.google.android.apps.mytracks.io.file.export.FileTrackExporter;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
@@ -441,15 +441,31 @@ public class SyncUtils {
|
||||
|
||||
java.io.File file = new java.io.File(directory,
|
||||
FileUtils.buildUniqueFileName(directory, track.getName(), trackFileFormat.getExtension()));
|
||||
TrackWriter trackWriter = new TrackWriter(
|
||||
context, myTracksProviderUtils, new Track[] {track}, trackFileFormat, null);
|
||||
FileTrackExporter fileTrackExporter = new FileTrackExporter(
|
||||
myTracksProviderUtils, new Track[] { track }, trackFileFormat, context, false, null);
|
||||
|
||||
trackWriter.writeTrack(new FileOutputStream(file));
|
||||
if (trackWriter.wasSuccess()) {
|
||||
return file;
|
||||
}
|
||||
Log.d(TAG, "Unable to get file for track " + track.getName());
|
||||
return null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(file);
|
||||
fileTrackExporter.writeTrack(fileOutputStream);
|
||||
if (fileTrackExporter.isSuccess()) {
|
||||
return file;
|
||||
} else {
|
||||
if (!file.delete()) {
|
||||
Log.d(TAG, "Unable to delete file for track " + track.getName());
|
||||
}
|
||||
Log.d(TAG, "Unable to get file for track " + track.getName());
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to close file output stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user