diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/AbstractImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/AbstractImporter.java index 2de8d6d13..37a62fa48 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/AbstractImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/AbstractImporter.java @@ -101,6 +101,7 @@ abstract class AbstractImporter extends DefaultHandler { private static final int MAX_BUFFERED_LOCATIONS = 512; private final Context context; + private final long importTrackId; private final MyTracksProviderUtils myTracksProviderUtils; private final int minRecordingDistance; private final List trackIds; @@ -124,17 +125,25 @@ abstract class AbstractImporter extends DefaultHandler { protected String time; protected String waypointType; - protected AbstractImporter(Context context) { - this(context, MyTracksProviderUtils.Factory.get(context)); + /** + * Constructor. + * + * @param context the context + * @param importTrackId the track id to import to. -1L to import to a new + * track. + */ + protected AbstractImporter(Context context, long importTrackId) { + this(context, importTrackId, MyTracksProviderUtils.Factory.get(context)); } @VisibleForTesting protected AbstractImporter( - Context context, MyTracksProviderUtils myTracksProviderUtils) { + Context context, long importTrackId, MyTracksProviderUtils myTracksProviderUtils) { this.context = context; + this.importTrackId = importTrackId; this.myTracksProviderUtils = myTracksProviderUtils; - this.minRecordingDistance = PreferencesUtils.getInt(context, R.string.min_recording_distance_key, - PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT); + this.minRecordingDistance = PreferencesUtils.getInt(context, + R.string.min_recording_distance_key, PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT); trackIds = new ArrayList(); waypoints = new ArrayList(); } @@ -286,12 +295,22 @@ abstract class AbstractImporter extends DefaultHandler { /** * On track start. */ - protected void onTrackStart() { + protected void onTrackStart() throws SAXException { trackData = new TrackData(); - Uri uri = myTracksProviderUtils.insertTrack(trackData.track); - long id = Long.parseLong(uri.getLastPathSegment()); - trackIds.add(id); - trackData.track.setId(id); + long trackId; + if (importTrackId == -1L) { + Uri uri = myTracksProviderUtils.insertTrack(trackData.track); + trackId = Long.parseLong(uri.getLastPathSegment()); + } else { + if (trackIds.size() > 0) { + throw new SAXException(createErrorMessage( + "Cannot import more than one track to an existing track " + importTrackId)); + } + trackId = importTrackId; + myTracksProviderUtils.clearTrack(trackId); + } + trackIds.add(trackId); + trackData.track.setId(trackId); } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java index c9eee1249..3f6acc670 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java @@ -48,13 +48,19 @@ public class GpxImporter extends AbstractImporter { private static final String ATTRIBUTE_LAT = "lat"; private static final String ATTRIBUTE_LON = "lon"; - public GpxImporter(Context context) { - super(context); + /** + * Constructor. + * + * @param context the context + * @param importTrackId track id to import to. -1L to import to a new track. + */ + public GpxImporter(Context context, long importTrackId) { + super(context, importTrackId); } @VisibleForTesting public GpxImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) { - super(context, myTracksProviderUtils); + super(context, -1L, myTracksProviderUtils); } @Override @@ -112,7 +118,7 @@ public class GpxImporter extends AbstractImporter { } @Override - protected void onTrackStart() { + protected void onTrackStart() throws SAXException { super.onTrackStart(); name = null; description = null; diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportAsyncTask.java index 6f9e20dc7..e600b41e6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportAsyncTask.java @@ -73,7 +73,7 @@ public class ImportAsyncTask extends AsyncTask { this.trackFileFormat = trackFileFormat; this.path = path; context = importActivity.getApplicationContext(); - + // Get the wake lock if not recording or paused if (PreferencesUtils.getLong(importActivity, R.string.recording_track_id_key) == PreferencesUtils.RECORDING_TRACK_ID_DEFAULT || PreferencesUtils.getBoolean( @@ -157,8 +157,9 @@ public class ImportAsyncTask extends AsyncTask { */ private boolean importFile(final File file) { try { - AbstractImporter importer = trackFileFormat == TrackFileFormat.KML ? new KmlImporter(context) - : new GpxImporter(context); + AbstractImporter importer = trackFileFormat == TrackFileFormat.KML ? new KmlImporter( + context, -1L) + : new GpxImporter(context, -1L); long trackIds[] = importer.importFile(new FileInputStream(file)); int length = trackIds.length; if (length > 0) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlImporter.java index e9a74222f..59dd5b2e4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/KmlImporter.java @@ -67,15 +67,21 @@ public class KmlImporter extends AbstractImporter { private ArrayList heartRateList; private ArrayList powerList; - public KmlImporter(Context context) { - super(context); + /** + * Constructor. + * + * @param context the context + * @param importTrackId track id to import to. -1L to import to a new track. + */ + public KmlImporter(Context context, long importTrackId) { + super(context, importTrackId); } @VisibleForTesting public KmlImporter(Context context, MyTracksProviderUtils myTracksProviderUtils) { - super(context, myTracksProviderUtils); + super(context, -1L, myTracksProviderUtils); } - + @Override public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException { diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java index fc96df102..dee6ed262 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java @@ -40,6 +40,13 @@ public interface MyTracksProviderUtils { */ public static final String AUTHORITY = "com.google.android.maps.mytracks"; + /** + * Clears a track. Removes waypoints and trackpoints. Only keeps the track id. + * + * @param trackId the track id + */ + public void clearTrack(long trackId); + /** * Creates a {@link Track} from a cursor. * @@ -122,7 +129,8 @@ public interface MyTracksProviderUtils { * deletion. The generator is used to update the next statistics waypoint. * * @param waypointId the waypoint id - * @param descriptionGenerator the description generator. Can be null for waypoint marker + * @param descriptionGenerator the description generator. Can be null for + * waypoint marker */ public void deleteWaypoint(long waypointId, DescriptionGenerator descriptionGenerator); @@ -143,8 +151,8 @@ public interface MyTracksProviderUtils { public Waypoint getLastWaypoint(long trackId, WaypointType waypointType); /** - * Gets the next waypoint number for a type. Returns -1 if not able to get the next - * waypoint number. + * Gets the next waypoint number for a type. Returns -1 if not able to get the + * next waypoint number. * * @param trackId the track id * @param waypointType the waypoint type @@ -165,7 +173,8 @@ public interface MyTracksProviderUtils { * @param selection the selection. Can be null * @param selectionArgs the selection arguments. Can be null * @param sortOrder the sort order. Can be null - * @param maxWaypoints the maximum number of waypoints to return. -1 for no limit + * @param maxWaypoints the maximum number of waypoints to return. -1 for no + * limit */ public Cursor getWaypointCursor( String selection, String[] selectionArgs, String sortOrder, int maxWaypoints); @@ -176,7 +185,8 @@ public interface MyTracksProviderUtils { * * @param trackId the track id * @param minWaypointId the minimum waypoint id. -1L to ignore - * @param maxWaypoints the maximum number of waypoints to return. -1 for no limit + * @param maxWaypoints the maximum number of waypoints to return. -1 for no + * limit */ public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints); @@ -228,12 +238,13 @@ public interface MyTracksProviderUtils { public long getLastTrackPointId(long trackId); /** - * Gets the first valid location for a track. Returns null if it doesn't exist. + * Gets the first valid location for a track. Returns null if it doesn't + * exist. * * @param trackId the track id */ public Location getFirstValidTrackPoint(long trackId); - + /** * Gets the last valid location for a track. Returns null if it doesn't exist. * diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java index 50eb9bae5..d5b95e18d 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java @@ -50,6 +50,14 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { this.contentResolver = contentResolver; } + @Override + public void clearTrack(long trackId) { + deleteTrackPointsAndWaypoints(trackId); + Track track = new Track(); + track.setId(trackId); + updateTrack(track); + } + @Override public Track createTrack(Cursor cursor) { int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID); @@ -164,6 +172,21 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { @Override public void deleteTrack(long trackId) { + deleteTrackPointsAndWaypoints(trackId); + + // Delete track last since it triggers a database vaccum call + contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", + new String[] { Long.toString(trackId) }); + } + + /** + * Deletes track points and waypoints of a track. Assumes + * {@link TracksColumns#STARTID}, {@link TracksColumns#STOPID}, and + * {@link TracksColumns#NUMPOINTS} will be updated by the caller. + * + * @param trackId the track id + */ + private void deleteTrackPointsAndWaypoints(long trackId) { Track track = getTrack(trackId); if (track != null) { String where = TrackPointsColumns._ID + ">=? AND " + TrackPointsColumns._ID + "<=?"; @@ -173,9 +196,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { } contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", new String[] { Long.toString(trackId) }); - // Delete tracks last since it triggers a database vaccum call - contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", - new String[] { Long.toString(trackId) }); } @Override @@ -759,7 +779,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { String[] selectionArgs = new String[] { Long.toString(trackId) }; return findTrackPointBy(selection, selectionArgs); } - + @Override public Location getLastValidTrackPoint(long trackId) { if (trackId < 0) {