diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java index 08d9f585b..ebb2ac31b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java @@ -950,46 +950,46 @@ public class MyTracks extends TabActivity implements OnTouchListener, showDialogSafely(DIALOG_IMPORT_PROGRESS); Thread t = new Thread() { @Override - public void run() { - int message = R.string.success; + public void run() { + int message = R.string.success; - long[] trackIdsImported = null; - - try { - try { - InputStream is = new FileInputStream(fileName); - trackIdsImported = GpxSaxImporter.importGPXFile(is, providerUtils); - } catch (SAXException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - message = R.string.error_generic; - } catch (ParserConfigurationException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - message = R.string.error_generic; - } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - message = R.string.error_unable_to_read_file; - } catch (NullPointerException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - message = R.string.error_invalid_gpx_format; - } catch (OutOfMemoryError e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - message = R.string.error_out_of_memory; - } - if (trackIdsImported != null && trackIdsImported.length > 0) { - // select last track from import file - setSelectedTrack(trackIdsImported[trackIdsImported.length -1]); - } else { - MyTracks.this.showMessageDialog(message, false/*success*/); - } - } finally { - runOnUiThread(new Runnable() { - public void run() { - dismissDialog(DIALOG_IMPORT_PROGRESS); - } - }); - } - } - }; + long[] trackIdsImported = null; + + try { + try { + InputStream is = new FileInputStream(fileName); + trackIdsImported = GpxSaxImporter.importGPXFile(is, providerUtils); + } catch (SAXException e) { + Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + message = R.string.error_generic; + } catch (ParserConfigurationException e) { + Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + message = R.string.error_generic; + } catch (IOException e) { + Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + message = R.string.error_unable_to_read_file; + } catch (NullPointerException e) { + Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + message = R.string.error_invalid_gpx_format; + } catch (OutOfMemoryError e) { + Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + message = R.string.error_out_of_memory; + } + if (trackIdsImported != null && trackIdsImported.length > 0) { + // select last track from import file + setSelectedTrack(trackIdsImported[trackIdsImported.length - 1]); + } else { + MyTracks.this.showMessageDialog(message, false/* success */); + } + } finally { + runOnUiThread(new Runnable() { + public void run() { + dismissDialog(DIALOG_IMPORT_PROGRESS); + } + }); + } + } + }; t.start(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/GpxSaxImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/GpxSaxImporter.java index 43d4ba4ee..24c6901f2 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/GpxSaxImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/GpxSaxImporter.java @@ -112,11 +112,10 @@ public class GpxSaxImporter extends DefaultHandler { private boolean isCurrentTrackRollbackable; private MyTracksProviderUtils providerUtils; - + /** - * flag to indicate if we in a track xml element - * some sub elements like name may be used in other - * parts of the gpx file - ignore them + * flag to indicate if we in a track xml element some sub elements like name + * may be used in other parts of the gpx file - ignore them */ private boolean isInTrackElement; @@ -124,34 +123,42 @@ public class GpxSaxImporter extends DefaultHandler { * Reads GPS tracks from a GPX file and append tracks and their coordinates to * the given list of tracks. * - * Callers must execute
rollbackUnfinishedTrack
in case of - * an exception to avoid inconsistent data + * Callers must execute + * + *
+	 * rollbackUnfinishedTrack
+	 * 
+ * + * in case of an exception to avoid inconsistent data * * @param tracks * a list of tracks * @param is * a input steam with gpx-xml data - * @throws SAXException a parsing error - * @throws ParserConfigurationException internal error - * @throws IOException a file reading problem + * @throws SAXException + * a parsing error + * @throws ParserConfigurationException + * internal error + * @throws IOException + * a file reading problem */ - public static long[] importGPXFile( - final InputStream is,final MyTracksProviderUtils providerUtils) + public static long[] importGPXFile(final InputStream is, + final MyTracksProviderUtils providerUtils) throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); GpxSaxImporter handler = new GpxSaxImporter(providerUtils); SAXParser parser = factory.newSAXParser(); long[] trackIds = null; - - try{ + + try { parser.parse(is, handler); trackIds = handler.getImportedTrackIds(); } finally { // delete track if not finished handler.rollbackUnfinishedTracks(); } - + return trackIds; } @@ -163,7 +170,7 @@ public class GpxSaxImporter extends DefaultHandler { tracksWritten = new ArrayList(); content = new StringBuilder(); } - + @Override public void characters(char[] ch, int start, int length) throws SAXException { content.append(ch, start, length); @@ -176,17 +183,16 @@ public class GpxSaxImporter extends DefaultHandler { if (localName.equalsIgnoreCase(TAG_TRACK)) { isInTrackElement = true; onTrackElementStart(); - + // process this element only as sub-elements of track - } else if(isInTrackElement) { - + } else if (isInTrackElement) { + if (localName.equalsIgnoreCase(TAG_TRACK_POINT)) { onTrackPointElementStart(attributes); } - } + } } - @Override public void endElement(String uri, String localName, String name) throws SAXException { @@ -194,10 +200,10 @@ public class GpxSaxImporter extends DefaultHandler { if (localName.equalsIgnoreCase(TAG_TRACK)) { onTrackElementEnd(); isInTrackElement = false; - + // process these elements only as sub-elements of track - } else if(isInTrackElement) { - + } else if (isInTrackElement) { + if (localName.equalsIgnoreCase(TAG_TRACK_POINT)) { onTrackPointElementEnd(); } else if (localName.equalsIgnoreCase(TAG_ALTITUDE)) { @@ -259,7 +265,6 @@ public class GpxSaxImporter extends DefaultHandler { return loc; } - private void onDescriptionElementEnd() { track.setDescription(content.toString().trim()); } @@ -272,25 +277,26 @@ public class GpxSaxImporter extends DefaultHandler { * Track point finished, write in database */ private void onTrackPointElementEnd() { - + if (MyTracksUtils.isValidLocation(location)) { - + stats.addLocation(location, location.getTime()); - // insert in db - Uri trackPointIdUri = providerUtils.insertTrackPoint(location, track.getId()); + // insert in db + Uri trackPointIdUri = providerUtils.insertTrackPoint(location, track + .getId()); // set start and stop id for track long trackPointId = Long.parseLong(trackPointIdUri.getLastPathSegment()); // first track point? - if(lastLocation == null) { + if (lastLocation == null) { track.setStartId(trackPointId); } // location has no setId method // updating stop id on track every time... track.setStopId(trackPointId); - + lastLocation = location; numberOfLocations++; } @@ -300,9 +306,9 @@ public class GpxSaxImporter extends DefaultHandler { * Track finished - update in database */ private void onTrackElementEnd() { - + if (lastLocation != null) { - + // Calculate statistics for the imported track and update stats.pauseAt(lastLocation.getTime()); track.setStopTime(lastLocation.getTime()); @@ -310,9 +316,9 @@ public class GpxSaxImporter extends DefaultHandler { stats.fillStatisticsForTrack(track); providerUtils.updateTrack(track); tracksWritten.add(new Long(track.getId())); - + } else { - + // track contains no track points makes not really // sense to import it as we have no location // information -> roll back @@ -321,18 +327,17 @@ public class GpxSaxImporter extends DefaultHandler { isCurrentTrackRollbackable = false; } - /** - * setting time and doing additional calculations - * as this is the last value required. Also sets the - * start time for track and statistics as there is - * no start time in the track root element + /** + * setting time and doing additional calculations as this is the last value + * required. Also sets the start time for track and statistics as there is no + * start time in the track root element */ private void onTimeElementEnd() { - + long time = parseTimeForAllFormats(content.toString().trim()); - - if(location != null) { - + + if (location != null) { + location.setTime(time); // initialize start time with time of first track point if (stats == null) { @@ -355,16 +360,16 @@ public class GpxSaxImporter extends DefaultHandler { } private void onAltitudeElementEnd() { - if(location != null) { + if (location != null) { String altitude = content.toString().trim(); // make altitude optional - if(altitude != null){ + if (altitude != null) { location.setAltitude(Double.parseDouble(altitude)); } } } - + /** * If a exception is thrown during the import callers must execute this method * in the catch clause to avoid inconsistent data diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/GpxImporterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/GpxImporterTest.java index 486bebbe5..cea99db3b 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/GpxImporterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/GpxImporterTest.java @@ -35,10 +35,10 @@ import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; * @author Steffen (steffen.horlacher@gmail.com) */ public class GpxImporterTest extends AndroidTestCase { - + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( - "yyyy-MM-dd'T'hh:mm:ss'Z'"); - + "yyyy-MM-dd'T'hh:mm:ss'Z'"); + private static final String TRACK_NAME = "blablub"; private static final String TRACK_DESC = "s'Laebe isch koi Schlotzer"; @@ -54,22 +54,25 @@ public class GpxImporterTest extends AndroidTestCase { private static final String TRACK_TIME_2 = "2010-04-22T18:21:50Z"; // TODO use real files from different sources with more track points - private static final String VALID_TEST_GPX = - "" + - "" + TRACK_ELE_1 + " +" + - "" + TRACK_ELE_2 + "" + - ""; - + private static final String VALID_TEST_GPX = "" + "" + TRACK_ELE_1 + " +" + "" + TRACK_ELE_2 + "" + ""; + // invalid xml - private static final String INVALID_TEST_GPX = VALID_TEST_GPX.substring(0,VALID_TEST_GPX.length() - 50); + private static final String INVALID_TEST_GPX = VALID_TEST_GPX.substring(0, + VALID_TEST_GPX.length() - 50); private static final long TRACK_ID = 1; private static final long TRACK_POINT_ID = 1; - private static final Uri TRACK_ID_URI = - ContentUris.appendId( TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID).build(); - private static final Uri TRACK_POINT_ID_URI = - ContentUris.appendId( TrackPointsColumns.CONTENT_URI.buildUpon(), TRACK_POINT_ID).build(); + private static final Uri TRACK_ID_URI = ContentUris.appendId( + TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID).build(); + private static final Uri TRACK_POINT_ID_URI = ContentUris.appendId( + TrackPointsColumns.CONTENT_URI.buildUpon(), TRACK_POINT_ID).build(); private MyTracksProviderUtils providerUtils; @@ -98,17 +101,15 @@ public class GpxImporterTest extends AndroidTestCase { Capture locParam = new Capture(); Capture idParam = new Capture(); - expect( - providerUtils.insertTrack(capture(trackParam))) - .andReturn(TRACK_ID_URI); - - expect( - providerUtils.insertTrackPoint(capture(locParam),capture(idParam))) - .andReturn(TRACK_POINT_ID_URI); + expect(providerUtils.insertTrack(capture(trackParam))).andReturn( + TRACK_ID_URI); + + expect(providerUtils.insertTrackPoint(capture(locParam), capture(idParam))) + .andReturn(TRACK_POINT_ID_URI); expectLastCall().times(2); - + providerUtils.updateTrack(capture(trackParam)); - + replay(providerUtils); InputStream is = new ByteArrayInputStream(VALID_TEST_GPX.getBytes()); @@ -120,40 +121,39 @@ public class GpxImporterTest extends AndroidTestCase { Track track = trackParam.getValue(); assertEquals(TRACK_NAME, track.getName()); assertEquals(TRACK_DESC, track.getDescription()); - assertEquals(DATE_FORMAT.parse(TRACK_TIME_1).getTime(), track.getStartTime()); + assertEquals(DATE_FORMAT.parse(TRACK_TIME_1).getTime(), track + .getStartTime()); assertNotSame(-1, track.getStartId()); assertNotSame(-1, track.getStopId()); - + // verify last location parameter Location loc = locParam.getValue(); - assertEquals(Double.parseDouble(TRACK_LAT_2),loc.getLatitude()); - assertEquals(Double.parseDouble(TRACK_LON_2),loc.getLongitude()); - assertEquals(Double.parseDouble(TRACK_ELE_2),loc.getAltitude()); + assertEquals(Double.parseDouble(TRACK_LAT_2), loc.getLatitude()); + assertEquals(Double.parseDouble(TRACK_LON_2), loc.getLongitude()); + assertEquals(Double.parseDouble(TRACK_ELE_2), loc.getAltitude()); assertEquals(DATE_FORMAT.parse(TRACK_TIME_2).getTime(), loc.getTime()); - + } /** - * Test if created track will be deleted on - * parsing errors + * Test if created track will be deleted on parsing errors */ public void testImportFailure() throws ParserConfigurationException, SAXException, IOException { + expect(providerUtils.insertTrack((Track) EasyMock.anyObject())).andReturn( + TRACK_ID_URI); expect( - providerUtils.insertTrack((Track) EasyMock.anyObject())).andReturn(TRACK_ID_URI); - expect( - providerUtils.insertTrackPoint( - (Location) EasyMock.anyObject(), + providerUtils.insertTrackPoint((Location) EasyMock.anyObject(), EasyMock.anyLong())).andReturn(TRACK_POINT_ID_URI); - + expectLastCall().anyTimes(); providerUtils.deleteTrack(TRACK_ID); replay(providerUtils); InputStream is = new ByteArrayInputStream(INVALID_TEST_GPX.getBytes()); - + try { GpxSaxImporter.importGPXFile(is, providerUtils); } catch (SAXException e) {