mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 09:33:06 +02:00
Allow cancellation of track write
This commit is contained in:
@@ -45,6 +45,7 @@ limitations under the License.
|
||||
<string name="error_invalid_gpx_format">File does not have a valid GPX format.</string>
|
||||
<string name="error_generic">An error occurred. Please try again.</string>
|
||||
<string name="error_track_does_not_exist">Track does not exist.</string>
|
||||
<string name="error_operation_cancelled">The operation was cancelled.</string>
|
||||
<string name="error_out_of_memory">This file is too big (must be less than 500 KB). Aborting.</string>
|
||||
<string name="error_unable_to_insert_marker">Unable to insert marker. No location fix available.</string>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -75,6 +75,11 @@ public interface TrackWriter {
|
||||
*/
|
||||
void writeTrack();
|
||||
|
||||
/**
|
||||
* Stop any in-progress writes
|
||||
*/
|
||||
void stopWriteTrack();
|
||||
|
||||
/**
|
||||
* Returns true if the write completed successfully.
|
||||
*/
|
||||
|
||||
@@ -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++;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+10
-11
@@ -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();
|
||||
|
||||
@@ -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<Object>() {
|
||||
@Override
|
||||
public Object answer() throws Throwable {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
});
|
||||
|
||||
mocksControl.replay();
|
||||
|
||||
writer.writeTrack();
|
||||
|
||||
mocksControl.verify();
|
||||
|
||||
assertFalse(writer.wasSuccess());
|
||||
assertEquals(R.string.error_operation_cancelled, writer.getErrorMessage());
|
||||
}
|
||||
|
||||
public void testWriteTrack_openFails() {
|
||||
writer = new WriteTracksTrackWriter(getContext(), providerUtils, track,
|
||||
formatWriter, false);
|
||||
@@ -229,7 +266,7 @@ public class TrackWriterTest extends AndroidTestCase {
|
||||
mocksControl.verify();
|
||||
}
|
||||
|
||||
public void testWriteDocument_emptyTrack() {
|
||||
public void testWriteDocument_emptyTrack() throws Exception {
|
||||
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
|
||||
|
||||
// Set expected mock behavior
|
||||
@@ -244,7 +281,7 @@ public class TrackWriterTest extends AndroidTestCase {
|
||||
mocksControl.verify();
|
||||
}
|
||||
|
||||
public void testWriteDocument() {
|
||||
public void testWriteDocument() throws Exception {
|
||||
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
|
||||
|
||||
final Location[] locs = {
|
||||
|
||||
Reference in New Issue
Block a user