diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml
index 8d7c37b0f..b7afaee25 100644
--- a/MyTracks/res/values/strings.xml
+++ b/MyTracks/res/values/strings.xml
@@ -45,6 +45,7 @@ limitations under the License.
File does not have a valid GPX format.
An error occurred. Please try again.
Track does not exist.
+ The operation was cancelled.
This file is too big (must be less than 500 KB). Aborting.
Unable to insert marker. No location fix available.
diff --git a/MyTracks/src/com/google/android/apps/mytracks/WriteProgressController.java b/MyTracks/src/com/google/android/apps/mytracks/WriteProgressController.java
index 514f2fc02..3f0356756 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/WriteProgressController.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/WriteProgressController.java
@@ -20,6 +20,7 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.ProgressDialog;
+import android.content.DialogInterface;
/**
* Given a {@link TrackWriter}, this class manages the process of writing the
@@ -66,6 +67,7 @@ class WriteProgressController {
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage(activity.getString(R.string.write_progress_message));
dialog.setIndeterminate(true);
+ dialog.setOnCancelListener(dialogCancelListener);
writer.setOnCompletionListener(writerCompleteListener);
writer.setOnWriteListener(writerWriteListener);
@@ -87,6 +89,14 @@ class WriteProgressController {
return dialog;
}
+ private final DialogInterface.OnCancelListener dialogCancelListener =
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ writer.stopWriteTrack();
+ }
+ };
+
private final TrackWriter.OnCompletionListener writerCompleteListener =
new TrackWriter.OnCompletionListener() {
@Override
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java
index 11f93079c..0b7101c6f 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java
@@ -1,12 +1,12 @@
/*
* 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
@@ -54,7 +54,7 @@ public interface TrackFormatWriter {
void prepare(Track track, OutputStream out);
/**
- * @return The file extentsion (i.e. gpx, kml, ...)
+ * @return The file extension (i.e. gpx, kml, ...)
*/
String getExtension();
@@ -77,7 +77,7 @@ public interface TrackFormatWriter {
*
* @param location the location to write
*/
- void writeLocation(Location location);
+ void writeLocation(Location location) throws InterruptedException;
/**
* Write a way point.
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriter.java
index 411ae5061..bace24d33 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriter.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriter.java
@@ -75,6 +75,11 @@ public interface TrackWriter {
*/
void writeTrack();
+ /**
+ * Stop any in-progress writes
+ */
+ void stopWriteTrack();
+
/**
* Returns true if the write completed successfully.
*/
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java
index 5e0adc968..d74a9c8f4 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java
@@ -57,6 +57,7 @@ class TrackWriterImpl implements TrackWriter {
private File file = null;
private OnCompletionListener onCompletionListener;
private OnWriteListener onWriteListener;
+ private Thread writeThread;
TrackWriterImpl(Context context, MyTracksProviderUtils providerUtils,
Track track, TrackFormatWriter writer) {
@@ -89,28 +90,60 @@ class TrackWriterImpl implements TrackWriter {
@Override
public void writeTrackAsync() {
- Thread t = new Thread() {
+ writeThread = new Thread() {
@Override
public void run() {
- writeTrack();
+ doWriteTrack();
}
};
- t.start();
+ writeThread.start();
}
@Override
public void writeTrack() {
+ writeTrackAsync();
+ try {
+ writeThread.join();
+ } catch (InterruptedException e) {
+ Log.e(Constants.TAG, "Interrupted waiting for write to complete", e);
+ }
+ }
+
+ private void doWriteTrack() {
// Open the input and output
success = false;
errorMessage = R.string.error_track_does_not_exist;
if (track != null) {
if (openFile()) {
- writeDocument();
+ try {
+ writeDocument();
+ } catch (InterruptedException e) {
+ Log.i(Constants.TAG, "The track write was interrupted");
+ if (file != null) {
+ file.delete();
+ }
+ success = false;
+ errorMessage = R.string.error_operation_cancelled;
+ }
}
}
finished();
}
+ public void stopWriteTrack() {
+ if (writeThread != null && writeThread.isAlive()) {
+ Log.i(Constants.TAG, "Attempting to stop track write");
+ writeThread.interrupt();
+
+ try {
+ writeThread.join();
+ Log.i(Constants.TAG, "Track write stopped");
+ } catch (InterruptedException e) {
+ Log.e(Constants.TAG, "Failed to wait for writer to stop", e);
+ }
+ }
+ }
+
@Override
public int getErrorMessage() {
return errorMessage;
@@ -253,7 +286,7 @@ class TrackWriterImpl implements TrackWriter {
/**
* Does the actual work of writing the track to the now open file.
*/
- void writeDocument() {
+ void writeDocument() throws InterruptedException {
Log.d(Constants.TAG, "Started writing track.");
writer.writeHeader();
writeWaypoints(track.getId());
@@ -265,7 +298,7 @@ class TrackWriterImpl implements TrackWriter {
errorMessage = R.string.io_write_finished;
}
- private void writeLocations() {
+ private void writeLocations() throws InterruptedException {
boolean wroteFirst = false;
boolean segmentOpen = false;
boolean isLastValid = false;
@@ -303,6 +336,9 @@ class TrackWriterImpl implements TrackWriter {
int pointNumber = 0;
while (it.hasNext()) {
Location loc = it.next();
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
pointNumber++;
diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/MockTrackWriter.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/MockTrackWriter.java
index c5fbb18a3..813d42a52 100644
--- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/MockTrackWriter.java
+++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/MockTrackWriter.java
@@ -59,6 +59,11 @@ public class MockTrackWriter implements TrackWriter {
throw new UnsupportedOperationException("not implemented");
}
+ @Override
+ public void stopWriteTrack() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
@Override
public boolean wasSuccess() {
return false;
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 8c265bc26..6af065c5d 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
@@ -5,18 +5,9 @@ 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.TrackFormatWriter;
import android.test.AndroidTestCase;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -29,6 +20,14 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
/**
* Base class for track format writer tests, which sets up a fake track and
* gives auxiliary methods for verifying XML output.
@@ -105,9 +104,9 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase {
* track in {@link #track}.
*
* @param writer the writer to write to
- * @return the written contents
+ * @return the written contents
*/
- protected String writeTrack(TrackFormatWriter writer) {
+ protected String writeTrack(TrackFormatWriter writer) throws Exception {
OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE);
writer.prepare(track, output);
writer.writeHeader();
diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java
index 1f74dd500..7ec10b12a 100644
--- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java
+++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java
@@ -9,10 +9,9 @@ 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.TrackFormatWriter;
-import com.google.android.apps.mytracks.io.file.TrackWriterImpl;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
+import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.location.Location;
@@ -25,6 +24,7 @@ import java.io.FileNotFoundException;
import java.io.OutputStream;
import org.easymock.EasyMock;
+import org.easymock.IAnswer;
import org.easymock.IArgumentMatcher;
import org.easymock.IMocksControl;
@@ -180,6 +180,43 @@ public class TrackWriterTest extends AndroidTestCase {
mocksControl.verify();
}
+ public void testWriteTrack_cancelled() throws Exception {
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ writer = new OpenFileTrackWriter(
+ getContext(), providerUtils, track, formatWriter, stream, true);
+
+ formatWriter.prepare(track, stream);
+
+ final Location[] locs = {
+ new Location("fake0"),
+ new Location("fake1"),
+ };
+ fillLocations(locs);
+ assertEquals(locs.length, providerUtils.bulkInsertTrackPoints(locs, locs.length, TRACK_ID));
+
+ formatWriter.writeHeader();
+ formatWriter.writeBeginTrack(locEq(locs[0]));
+ formatWriter.writeOpenSegment();
+
+ formatWriter.writeLocation(locEq(locs[0]));
+ //EasyMock.expectLastCall().andThrow(new InterruptedException());
+ EasyMock.expectLastCall().andAnswer(new IAnswer