forked from upstream-mirrors/OpenTracks
Import/export track UUID (necessary for synchronization).
If a track with a UUID is presented in OpenTracks, it cannot be imported again (enforced by database constraint). Fixes #307.
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
targetNamespace="http://opentracksapp.com/xmlschemas/v1">
|
||||||
|
|
||||||
|
<xs:element name="trackuuid"
|
||||||
|
type="xs:string" />
|
||||||
|
|
||||||
|
</xs:schema>
|
||||||
+10
-8
@@ -22,7 +22,6 @@ import android.net.Uri;
|
|||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -30,6 +29,9 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link CustomContentProvider}.
|
* Tests {@link CustomContentProvider}.
|
||||||
*
|
*
|
||||||
@@ -51,7 +53,7 @@ public class CustomContentProviderTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOnCreate() {
|
public void testOnCreate() {
|
||||||
Assert.assertTrue(customContentProvider.onCreate(context));
|
assertTrue(customContentProvider.onCreate(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,13 +61,13 @@ public class CustomContentProviderTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetType() {
|
public void testGetType() {
|
||||||
Assert.assertEquals(TracksColumns.CONTENT_TYPE, customContentProvider.getType(TracksColumns.CONTENT_URI));
|
assertEquals(TracksColumns.CONTENT_TYPE, customContentProvider.getType(TracksColumns.CONTENT_URI));
|
||||||
Assert.assertEquals(TracksColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), 1).build()));
|
assertEquals(TracksColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), 1).build()));
|
||||||
|
|
||||||
Assert.assertEquals(TrackPointsColumns.CONTENT_TYPE, customContentProvider.getType(TrackPointsColumns.CONTENT_URI_BY_ID));
|
assertEquals(TrackPointsColumns.CONTENT_TYPE, customContentProvider.getType(TrackPointsColumns.CONTENT_URI_BY_ID));
|
||||||
Assert.assertEquals(TrackPointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TrackPointsColumns.CONTENT_URI_BY_TRACKID.buildUpon(), 1).build()));
|
assertEquals(TrackPointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TrackPointsColumns.CONTENT_URI_BY_TRACKID.buildUpon(), 1).build()));
|
||||||
|
|
||||||
Assert.assertEquals(WaypointsColumns.CONTENT_TYPE, customContentProvider.getType(WaypointsColumns.CONTENT_URI));
|
assertEquals(WaypointsColumns.CONTENT_TYPE, customContentProvider.getType(WaypointsColumns.CONTENT_URI));
|
||||||
Assert.assertEquals(WaypointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), 1).build()));
|
assertEquals(WaypointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), 1).build()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+38
-19
@@ -2,6 +2,7 @@ package de.dennisguse.opentracks.content.provider;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteConstraintException;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -21,6 +22,10 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class CustomSQLiteOpenHelperTest {
|
public class CustomSQLiteOpenHelperTest {
|
||||||
|
|
||||||
@@ -88,6 +93,7 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@After
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
context.deleteDatabase(DATABASE_NAME);
|
context.deleteDatabase(DATABASE_NAME);
|
||||||
}
|
}
|
||||||
@@ -95,13 +101,15 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
@Test
|
@Test
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
||||||
Assert.assertTrue(hasSqlCreate(db, TracksColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, TracksColumns.CREATE_TABLE));
|
||||||
|
|
||||||
Assert.assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE));
|
||||||
Assert.assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
||||||
|
|
||||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
||||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,18 +135,18 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then - verify table structure
|
// then - verify table structure
|
||||||
Assert.assertEquals(3, tableByUpgrade.size());
|
assertEquals(3, tableByUpgrade.size());
|
||||||
Assert.assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
||||||
|
|
||||||
Assert.assertEquals(tablesByCreate.get(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(tablesByCreate.get(TrackPointsColumns.TABLE_NAME), tableByUpgrade.get(TrackPointsColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(TrackPointsColumns.TABLE_NAME), tableByUpgrade.get(TrackPointsColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(tablesByCreate.get(WaypointsColumns.TABLE_NAME), tableByUpgrade.get(WaypointsColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(WaypointsColumns.TABLE_NAME), tableByUpgrade.get(WaypointsColumns.TABLE_NAME));
|
||||||
|
|
||||||
// then - verify custom indices
|
// then - verify custom indices
|
||||||
Assert.assertEquals(3, indicesByCreate.size());
|
assertEquals(3, indicesByCreate.size());
|
||||||
Assert.assertEquals(indicesByUpgrade.get(TracksColumns.TABLE_NAME), indicesByCreate.get(TracksColumns.TABLE_NAME));
|
assertEquals(indicesByUpgrade.get(TracksColumns.TABLE_NAME), indicesByCreate.get(TracksColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(indicesByUpgrade.get(TrackPointsColumns.TABLE_NAME), indicesByCreate.get(TrackPointsColumns.TABLE_NAME));
|
assertEquals(indicesByUpgrade.get(TrackPointsColumns.TABLE_NAME), indicesByCreate.get(TrackPointsColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(indicesByUpgrade.get(WaypointsColumns.TABLE_NAME), indicesByCreate.get(WaypointsColumns.TABLE_NAME));
|
assertEquals(indicesByUpgrade.get(WaypointsColumns.TABLE_NAME), indicesByCreate.get(WaypointsColumns.TABLE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -155,12 +163,23 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then - verify table structure
|
// then - verify table structure
|
||||||
Assert.assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
||||||
Assert.assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
||||||
Assert.assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
||||||
|
|
||||||
// then - verify custom indices
|
// then - verify custom indices
|
||||||
Assert.assertEquals(0, indicesByDowngrade.size());
|
assertEquals(0, indicesByDowngrade.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void track_uuid_unique() {
|
||||||
|
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
||||||
|
db.execSQL("INSERT INTO tracks (uuid) VALUES (0x00)");
|
||||||
|
db.execSQL("INSERT INTO tracks (uuid) VALUES (0x00)");
|
||||||
|
fail("unique constraint not enforced");
|
||||||
|
} catch (SQLiteConstraintException e) {
|
||||||
|
assertTrue(e.getMessage().contains("UNIQUE constraint failed: tracks.uuid"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createVersion23() {
|
private void createVersion23() {
|
||||||
|
|||||||
+6
-6
@@ -29,13 +29,13 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
|
|
||||||
@@ -64,11 +64,11 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
|
|
||||||
static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
||||||
static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||||
static final long TRACK_ID_0 = 1;
|
|
||||||
static final long TRACK_POINT_ID_0 = 1;
|
static final long TRACK_POINT_ID_0 = 1;
|
||||||
static final long TRACK_POINT_ID_1 = 2;
|
static final long TRACK_POINT_ID_1 = 2;
|
||||||
static final long TRACK_POINT_ID_3 = 4;
|
static final long TRACK_POINT_ID_3 = 4;
|
||||||
static final Uri TRACK_ID_0_URI = ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build();
|
|
||||||
private static final long WAYPOINT_ID_0 = 1;
|
private static final long WAYPOINT_ID_0 = 1;
|
||||||
private static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
private static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
// We can't omit the timezones in the test, otherwise it'll use the local timezone and fail depending on where the test runner is.
|
// We can't omit the timezones in the test, otherwise it'll use the local timezone and fail depending on where the test runner is.
|
||||||
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
|
TimeZone utc = SimpleTimeZone.getTimeZone(ZoneOffset.UTC);
|
||||||
DATE_FORMAT_0.setTimeZone(utc);
|
DATE_FORMAT_0.setTimeZone(utc);
|
||||||
DATE_FORMAT_1.setTimeZone(utc);
|
DATE_FORMAT_1.setTimeZone(utc);
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
protected void expectTrackUpdate(ArgumentCaptor<Track> trackCaptor, boolean lastTrack, long trackId) {
|
protected void expectTrackUpdate(ArgumentCaptor<Track> trackCaptor, boolean lastTrack, long trackId) {
|
||||||
contentProviderUtils.updateTrack(trackCaptor.capture());
|
contentProviderUtils.updateTrack(trackCaptor.capture());
|
||||||
|
|
||||||
when(contentProviderUtils.insertWaypoint((Waypoint) any())).thenReturn(WAYPOINT_ID_O_URI);
|
when(contentProviderUtils.insertWaypoint(any())).thenReturn(WAYPOINT_ID_O_URI);
|
||||||
if (lastTrack) {
|
if (lastTrack) {
|
||||||
// Return null to not add waypoints
|
// Return null to not add waypoints
|
||||||
when(contentProviderUtils.getTrack(trackId)).thenReturn(null);
|
when(contentProviderUtils.getTrack(trackId)).thenReturn(null);
|
||||||
|
|||||||
+54
-2
@@ -31,6 +31,7 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export a track to {@link TrackFileFormat} and verify that the import is identical.
|
* Export a track to {@link TrackFileFormat} and verify that the import is identical.
|
||||||
@@ -109,10 +110,11 @@ public class ExportImportTest {
|
|||||||
// 1. export
|
// 1. export
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
trackExporter.writeTrack(context, outputStream);
|
trackExporter.writeTrack(context, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
// 2. import
|
// 2. import
|
||||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context, -1L);
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
importTrackId = trackImporter.importFile(inputStream);
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -123,6 +125,7 @@ public class ExportImportTest {
|
|||||||
assertEquals(track.getDescription(), importedTrack.getDescription());
|
assertEquals(track.getDescription(), importedTrack.getDescription());
|
||||||
assertEquals(track.getName(), importedTrack.getName());
|
assertEquals(track.getName(), importedTrack.getName());
|
||||||
assertEquals(track.getIcon(), importedTrack.getIcon());
|
assertEquals(track.getIcon(), importedTrack.getIcon());
|
||||||
|
assertEquals(track.getUuid(), importedTrack.getUuid());
|
||||||
|
|
||||||
// 2. waypoints
|
// 2. waypoints
|
||||||
assertWaypoints();
|
assertWaypoints();
|
||||||
@@ -143,10 +146,11 @@ public class ExportImportTest {
|
|||||||
// 1. export
|
// 1. export
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
trackExporter.writeTrack(context, outputStream);
|
trackExporter.writeTrack(context, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
// 2. import
|
// 2. import
|
||||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context, -1L);
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
importTrackId = trackImporter.importFile(inputStream);
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -165,6 +169,29 @@ public class ExportImportTest {
|
|||||||
assertTrackpoints(true, true, true);
|
assertTrackpoints(true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
@Test
|
||||||
|
public void kml_with_trackdetail_and_sensordata_duplicate_trackUUID() {
|
||||||
|
// given
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
|
TrackExporter trackExporter = TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.newTrackExporter(context, new Track[]{track});
|
||||||
|
|
||||||
|
// when
|
||||||
|
// 1. export
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
trackExporter.writeTrack(context, outputStream);
|
||||||
|
|
||||||
|
// 2. import
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||||
|
assertNull(importedTrack);
|
||||||
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@Test
|
@Test
|
||||||
public void kmz_only_track() {
|
public void kmz_only_track() {
|
||||||
@@ -205,6 +232,7 @@ public class ExportImportTest {
|
|||||||
// 1. export
|
// 1. export
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
trackExporter.writeTrack(context, outputStream);
|
trackExporter.writeTrack(context, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
// 2. import
|
// 2. import
|
||||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
@@ -229,6 +257,30 @@ public class ExportImportTest {
|
|||||||
assertTrackpoints(false, true, true);
|
assertTrackpoints(false, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
@Test
|
||||||
|
public void gpx_duplicate_trackUUID() {
|
||||||
|
// given
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
|
TrackExporter trackExporter = TrackFileFormat.GPX.newTrackExporter(context, new Track[]{track});
|
||||||
|
|
||||||
|
// when
|
||||||
|
// 1. export
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
trackExporter.writeTrack(context, outputStream);
|
||||||
|
|
||||||
|
// 2. import
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
|
AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
||||||
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
|
// then
|
||||||
|
// 1. track
|
||||||
|
Track trackImported = contentProviderUtils.getTrack(importTrackId);
|
||||||
|
assertNull(trackImported);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertWaypoints() {
|
private void assertWaypoints() {
|
||||||
assertEquals(waypoints.size(), contentProviderUtils.getWaypointCount(importTrackId));
|
assertEquals(waypoints.size(), contentProviderUtils.getWaypointCount(importTrackId));
|
||||||
|
|
||||||
|
|||||||
-217
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 de.dennisguse.opentracks.io.file.importer;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.anyLong;
|
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
|
||||||
import static org.mockito.Mockito.eq;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link GpxFileTrackImporter}.
|
|
||||||
*
|
|
||||||
* @author Steffen Horlacher
|
|
||||||
*/
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|
||||||
|
|
||||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg><trkseg>"
|
|
||||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + "</trkseg></trk></gpx>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, null) + getTrackPoint(1, null) + "</trkseg><trkseg>"
|
|
||||||
+ getTrackPoint(2, null) + getTrackPoint(3, null) + "</trkseg></trk></gpx>";
|
|
||||||
|
|
||||||
private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring(0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50);
|
|
||||||
private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LATITUDE), "1000.0");
|
|
||||||
private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(TRACK_TIME_0, "invalid");
|
|
||||||
private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_ELEVATION), "invalid");
|
|
||||||
private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LATITUDE), "invalid");
|
|
||||||
private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LONGITUDE), "invalid");
|
|
||||||
|
|
||||||
private static String getNameAndDescription(String name, String description) {
|
|
||||||
return "<name><![CDATA[" + name + "]]></name>" + "<desc><![CDATA[" + description + "]]></desc>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getTrackPoint(int index, String time) {
|
|
||||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
|
||||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
|
||||||
String elevation = Double.toString(TRACK_ELEVATION + index);
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
buffer.append("<trkpt lat=\"").append(latitude).append("\" lon=\"").append(longitude).append("\"><ele>").append(elevation).append("</ele>");
|
|
||||||
if (time != null) {
|
|
||||||
buffer.append("<time>").append(time).append("</time>");
|
|
||||||
}
|
|
||||||
buffer.append("</trkpt>");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackOneSegment() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
TrackPoint trackPoint1 = createTrackPoint(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
|
||||||
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegments() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
|
||||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0 + time3 - time2, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegmentsNoTime() {
|
|
||||||
// given
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
Assert.assertEquals(0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidXml() {
|
|
||||||
testInvalidGpx(INVALID_XML_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLocation() {
|
|
||||||
testInvalidGpx(INVALID_LOCATION_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidTime() {
|
|
||||||
testInvalidGpx(INVALID_TIME_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidAltitude() {
|
|
||||||
testInvalidGpx(INVALID_ALTITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLatitude() {
|
|
||||||
testInvalidGpx(INVALID_LATITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLongitude() {
|
|
||||||
testInvalidGpx(INVALID_LONGITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testInvalidGpx(String xml) {
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
|
|
||||||
// For the following, use StubReturn since we don't care whether they are invoked or not.
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), anyLong())).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
contentProviderUtils.deleteTrack(context, TRACK_ID_0);
|
|
||||||
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
Assert.assertEquals(-1L, trackId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-133
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 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 de.dennisguse.opentracks.io.file.importer;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
|
||||||
import static org.mockito.Mockito.eq;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link KmlFileTrackImporter}.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|
||||||
|
|
||||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1)
|
|
||||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</gx:Track><gx:Track>"
|
|
||||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3)
|
|
||||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
|
||||||
|
|
||||||
private static String getNameAndDescription(String name, String description) {
|
|
||||||
return "<name><![CDATA[" + name + "]]></name><description><![CDATA[" + description
|
|
||||||
+ "]]></description>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getTrackPoint(int index, String time) {
|
|
||||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
|
||||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
|
||||||
String altitude = Double.toString(TRACK_ELEVATION + index);
|
|
||||||
return "<when>" + time + "</when>" + "<gx:coord>" + longitude + " " + latitude + " " + altitude + "</gx:coord>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackOneSegment() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
TrackPoint trackPointl1 = createTrackPoint(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
|
||||||
|
|
||||||
contentProviderUtils.clearTrack(context, TRACK_ID_0);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
|
||||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, TRACK_ID_0, contentProviderUtils);
|
|
||||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegments() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
|
|
||||||
contentProviderUtils.clearTrack(context, TRACK_ID_0);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
|
||||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, TRACK_ID_0, contentProviderUtils);
|
|
||||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
|
||||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0 + time3 - time2, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -205,9 +205,9 @@ public class ImportProgressDialogFragment extends DialogFragment {
|
|||||||
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
|
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
|
||||||
trackImporter = new GpxFileTrackImporter(context);
|
trackImporter = new GpxFileTrackImporter(context);
|
||||||
} else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
|
} else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
|
||||||
trackImporter = new KmlFileTrackImporter(ImportProgressDialogFragment.this.getContext(), -1L);
|
trackImporter = new KmlFileTrackImporter(ImportProgressDialogFragment.this.getContext());
|
||||||
} else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
|
} else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
|
||||||
trackImporter = new KmzTrackImporter(context, -1L, file.getUri());
|
trackImporter = new KmzTrackImporter(context, file.getUri());
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Unsupported file format.");
|
Log.i(TAG, "Unsupported file format.");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import de.dennisguse.opentracks.util.StringUtils;
|
|||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
|
//TODO Export waypoints
|
||||||
public class GpxTrackWriter implements TrackWriter {
|
public class GpxTrackWriter implements TrackWriter {
|
||||||
|
|
||||||
private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US);
|
private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||||
@@ -93,10 +94,15 @@ public class GpxTrackWriter implements TrackWriter {
|
|||||||
printWriter.println("xmlns=\"http://www.topografix.com/GPX/1/1\"");
|
printWriter.println("xmlns=\"http://www.topografix.com/GPX/1/1\"");
|
||||||
printWriter.println("xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\"");
|
printWriter.println("xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\"");
|
||||||
printWriter.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
|
printWriter.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
|
||||||
|
printWriter.println("xmlns:atom=\"http://www.w3.org/2005/Atom\"");
|
||||||
|
printWriter.println("xmlns:opentracks=\"http://opentracksapp.com/xmlschemas/v1\"");
|
||||||
printWriter.println("xmlns:gpxtpx=\"http://www.garmin.com/xmlschemes/TrackPointExtension/v2\"");
|
printWriter.println("xmlns:gpxtpx=\"http://www.garmin.com/xmlschemes/TrackPointExtension/v2\"");
|
||||||
printWriter.println("xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
printWriter.println("xsi:schemaLocation=" +
|
||||||
|
"\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
||||||
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd"
|
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd"
|
||||||
+ " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd\">");
|
+ " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd"
|
||||||
|
+ " http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd\">");
|
||||||
|
|
||||||
printWriter.println("<metadata>");
|
printWriter.println("<metadata>");
|
||||||
|
|
||||||
Track track = tracks[0];
|
Track track = tracks[0];
|
||||||
@@ -127,17 +133,15 @@ public class GpxTrackWriter implements TrackWriter {
|
|||||||
public void writeWaypoint(Waypoint waypoint) {
|
public void writeWaypoint(Waypoint waypoint) {
|
||||||
if (printWriter != null) {
|
if (printWriter != null) {
|
||||||
Location location = waypoint.getLocation();
|
Location location = waypoint.getLocation();
|
||||||
if (location != null) {
|
printWriter.println("<wpt " + formatLocation(location) + ">");
|
||||||
printWriter.println("<wpt " + formatLocation(location) + ">");
|
if (location.hasAltitude()) {
|
||||||
if (location.hasAltitude()) {
|
printWriter.println("<ele>" + ELEVATION_FORMAT.format(location.getAltitude()) + "</ele>");
|
||||||
printWriter.println("<ele>" + ELEVATION_FORMAT.format(location.getAltitude()) + "</ele>");
|
|
||||||
}
|
|
||||||
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(location.getTime()) + "</time>");
|
|
||||||
printWriter.println("<name>" + StringUtils.formatCData(waypoint.getName()) + "</name>");
|
|
||||||
printWriter.println("<desc>" + StringUtils.formatCData(waypoint.getDescription()) + "</desc>");
|
|
||||||
printWriter.println("<type>" + StringUtils.formatCData(waypoint.getCategory()) + "</type>");
|
|
||||||
printWriter.println("</wpt>");
|
|
||||||
}
|
}
|
||||||
|
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(location.getTime()) + "</time>");
|
||||||
|
printWriter.println("<name>" + StringUtils.formatCData(waypoint.getName()) + "</name>");
|
||||||
|
printWriter.println("<desc>" + StringUtils.formatCData(waypoint.getDescription()) + "</desc>");
|
||||||
|
printWriter.println("<type>" + StringUtils.formatCData(waypoint.getCategory()) + "</type>");
|
||||||
|
printWriter.println("</wpt>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +162,11 @@ public class GpxTrackWriter implements TrackWriter {
|
|||||||
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
|
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
|
||||||
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
|
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
|
||||||
printWriter.println("<type>" + StringUtils.formatCData(track.getCategory()) + "</type>");
|
printWriter.println("<type>" + StringUtils.formatCData(track.getCategory()) + "</type>");
|
||||||
printWriter.println("<extensions><topografix:color>c0c0c0</topografix:color></extensions>");
|
|
||||||
|
printWriter.println("<extensions>");
|
||||||
|
printWriter.println("<topografix:color>c0c0c0</topografix:color>");
|
||||||
|
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
|
||||||
|
printWriter.println("</extensions>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,10 @@ public class KmlTrackWriter implements TrackWriter {
|
|||||||
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
printWriter.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\"");
|
printWriter.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\"");
|
||||||
printWriter.println("xmlns:gx=\"http://www.google.com/kml/ext/2.2\"");
|
printWriter.println("xmlns:gx=\"http://www.google.com/kml/ext/2.2\"");
|
||||||
printWriter.println("xmlns:atom=\"http://www.w3.org/2005/Atom\">");
|
printWriter.println("xmlns:atom=\"http://www.w3.org/2005/Atom\"");
|
||||||
|
printWriter.println("xmlns:opentracks=\"http://opentracksapp.com/xmlschemas/v1\">");
|
||||||
|
//TODO ADD xsi:schemaLocation here!
|
||||||
|
|
||||||
printWriter.println("<Document>");
|
printWriter.println("<Document>");
|
||||||
printWriter.println("<open>1</open>");
|
printWriter.println("<open>1</open>");
|
||||||
printWriter.println("<visibility>1</visibility>");
|
printWriter.println("<visibility>1</visibility>");
|
||||||
@@ -204,6 +207,7 @@ public class KmlTrackWriter implements TrackWriter {
|
|||||||
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
|
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
|
||||||
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
|
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
|
||||||
printWriter.println("<icon>" + StringUtils.formatCData(track.getIcon()) + "</icon>");
|
printWriter.println("<icon>" + StringUtils.formatCData(track.getIcon()) + "</icon>");
|
||||||
|
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
|
||||||
}
|
}
|
||||||
|
|
||||||
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
|
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
|
||||||
@@ -460,7 +464,7 @@ public class KmlTrackWriter implements TrackWriter {
|
|||||||
/**
|
/**
|
||||||
* Writes a simple array style.
|
* Writes a simple array style.
|
||||||
*
|
*
|
||||||
* @param name the name of the simple array.
|
* @param name the name of the simple array.
|
||||||
* @param extendedDataType the extended data display name
|
* @param extendedDataType the extended data display name
|
||||||
*/
|
*/
|
||||||
private void writeSimpleArrayStyle(String name, String extendedDataType) {
|
private void writeSimpleArrayStyle(String name, String extendedDataType) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import de.dennisguse.opentracks.util.FileUtils;
|
|||||||
* @author Jimmy Shih
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
public class KmzTrackExporter implements TrackExporter {
|
public class KmzTrackExporter implements TrackExporter {
|
||||||
|
|
||||||
private static final String KMZ_IMAGES_DIR = "images";
|
private static final String KMZ_IMAGES_DIR = "images";
|
||||||
public static final String KMZ_KML_FILE = "doc.kml";
|
public static final String KMZ_KML_FILE = "doc.kml";
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ public class KmzTrackExporter implements TrackExporter {
|
|||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
private final ContentProviderUtils contentProviderUtils;
|
private final ContentProviderUtils contentProviderUtils;
|
||||||
private final TrackExporter fileTrackExporter;
|
private final FileTrackExporter fileTrackExporter;
|
||||||
private final Track[] tracks;
|
private final Track[] tracks;
|
||||||
|
|
||||||
private final boolean exportPhotos;
|
private final boolean exportPhotos;
|
||||||
@@ -58,10 +59,10 @@ public class KmzTrackExporter implements TrackExporter {
|
|||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param contentProviderUtils the content provider utils
|
* @param contentProviderUtils the content provider utils
|
||||||
* @param trackExporter the file track exporter
|
* @param trackExporter the file track exporter
|
||||||
* @param tracks the tracks to export
|
* @param tracks the tracks to export
|
||||||
*/
|
*/
|
||||||
public KmzTrackExporter(ContentProviderUtils contentProviderUtils, TrackExporter trackExporter, Track[] tracks, boolean exportPhotos) {
|
public KmzTrackExporter(ContentProviderUtils contentProviderUtils, FileTrackExporter trackExporter, Track[] tracks, boolean exportPhotos) {
|
||||||
this.contentProviderUtils = contentProviderUtils;
|
this.contentProviderUtils = contentProviderUtils;
|
||||||
this.fileTrackExporter = trackExporter;
|
this.fileTrackExporter = trackExporter;
|
||||||
this.tracks = tracks;
|
this.tracks = tracks;
|
||||||
|
|||||||
+16
-13
@@ -17,6 +17,7 @@
|
|||||||
package de.dennisguse.opentracks.io.file.importer;
|
package de.dennisguse.opentracks.io.file.importer;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteConstraintException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -62,11 +63,12 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
|
|
||||||
// The maximum number of buffered locations for bulk-insertion
|
// The maximum number of buffered locations for bulk-insertion
|
||||||
private static final int MAX_BUFFERED_LOCATIONS = 512;
|
private static final int MAX_BUFFERED_LOCATIONS = 512;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final long importTrackId;
|
|
||||||
private final ContentProviderUtils contentProviderUtils;
|
private final ContentProviderUtils contentProviderUtils;
|
||||||
private final int recordingDistanceInterval;
|
private final int recordingDistanceInterval;
|
||||||
|
|
||||||
|
private long importTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
private final List<Long> trackIds = new ArrayList<>();
|
private final List<Long> trackIds = new ArrayList<>();
|
||||||
private final List<Waypoint> waypoints = new ArrayList<>();
|
private final List<Waypoint> waypoints = new ArrayList<>();
|
||||||
|
|
||||||
@@ -96,19 +98,17 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
// The SAX locator to get the current line information
|
// The SAX locator to get the current line information
|
||||||
private Locator locator;
|
private Locator locator;
|
||||||
|
|
||||||
/**
|
AbstractFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils) {
|
||||||
* @param context the context
|
|
||||||
* @param importTrackId the track id to import to. -1L to import to a new track.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
// Remove importTrackId
|
|
||||||
AbstractFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.importTrackId = importTrackId;
|
|
||||||
this.contentProviderUtils = contentProviderUtils;
|
this.contentProviderUtils = contentProviderUtils;
|
||||||
this.recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context);
|
this.recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils, long importTrackId) {
|
||||||
|
this(context, contentProviderUtils);
|
||||||
|
this.importTrackId = importTrackId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDocumentLocator(Locator locator) {
|
public void setDocumentLocator(Locator locator) {
|
||||||
this.locator = locator;
|
this.locator = locator;
|
||||||
@@ -134,12 +134,10 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
saxParser.parse(inputStream, this);
|
saxParser.parse(inputStream, this);
|
||||||
Log.d(TAG, "Total import time: " + (System.currentTimeMillis() - start) + "ms");
|
Log.d(TAG, "Total import time: " + (System.currentTimeMillis() - start) + "ms");
|
||||||
if (trackIds.size() != 1) {
|
if (trackIds.size() != 1) {
|
||||||
Log.d(TAG, trackIds.size() + " tracks imported");
|
throw new MultiTracksImportException();
|
||||||
cleanImport();
|
|
||||||
return -1L;
|
|
||||||
}
|
}
|
||||||
return trackIds.get(0);
|
return trackIds.get(0);
|
||||||
} catch (IOException | SAXException | ParserConfigurationException e) {
|
} catch (MultiTracksImportException | IOException | SAXException | SQLiteConstraintException | ParserConfigurationException e) {
|
||||||
Log.e(TAG, "Unable to import file", e);
|
Log.e(TAG, "Unable to import file", e);
|
||||||
cleanImport();
|
cleanImport();
|
||||||
return -1L;
|
return -1L;
|
||||||
@@ -544,4 +542,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
// The number of buffered locations
|
// The number of buffered locations
|
||||||
int numBufferedTrackPoints = 0;
|
int numBufferedTrackPoints = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
//TODO According to the reader AND writer, we support multiple tracks per file; we should implement it here also.
|
||||||
|
private static class MultiTracksImportException extends RuntimeException {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class GpxFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
private static final String TAG_TRACK_SEGMENT = "trkseg";
|
private static final String TAG_TRACK_SEGMENT = "trkseg";
|
||||||
private static final String TAG_TYPE = "type";
|
private static final String TAG_TYPE = "type";
|
||||||
private static final String TAG_WAYPOINT = "wpt";
|
private static final String TAG_WAYPOINT = "wpt";
|
||||||
|
private static final String TAG_ID = "opentracks:trackid";
|
||||||
|
|
||||||
private static final String ATTRIBUTE_LAT = "lat";
|
private static final String ATTRIBUTE_LAT = "lat";
|
||||||
private static final String ATTRIBUTE_LON = "lon";
|
private static final String ATTRIBUTE_LON = "lon";
|
||||||
@@ -64,7 +65,7 @@ public class GpxFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
GpxFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils) {
|
GpxFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils) {
|
||||||
super(context, -1L, contentProviderUtils);
|
super(context, contentProviderUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -144,6 +145,10 @@ public class GpxFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
cadence = content.trim();
|
cadence = content.trim();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TAG_ID:
|
||||||
|
if (content != null) {
|
||||||
|
uuid = content.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset element content
|
// Reset element content
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
private static final String TAG_STYLE_URL = "styleUrl";
|
private static final String TAG_STYLE_URL = "styleUrl";
|
||||||
private static final String TAG_VALUE = "value";
|
private static final String TAG_VALUE = "value";
|
||||||
private static final String TAG_WHEN = "when";
|
private static final String TAG_WHEN = "when";
|
||||||
|
private static final String TAG_UUID = "opentracks:trackid";
|
||||||
|
|
||||||
private static final String ATTRIBUTE_NAME = "name";
|
private static final String ATTRIBUTE_NAME = "name";
|
||||||
|
|
||||||
@@ -68,23 +69,17 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
private ArrayList<Float> heartRateList;
|
private ArrayList<Float> heartRateList;
|
||||||
private ArrayList<Float> powerList;
|
private ArrayList<Float> powerList;
|
||||||
|
|
||||||
/**
|
public KmlFileTrackImporter(Context context) {
|
||||||
* @param context the context
|
this(context, new ContentProviderUtils(context));
|
||||||
* @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported.
|
|
||||||
*/
|
|
||||||
@Deprecated //TODO Do not pass importTrackId here; get it from somewhere else
|
|
||||||
public KmlFileTrackImporter(Context context, long importTrackId) {
|
|
||||||
this(context, importTrackId, new ContentProviderUtils(context));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
KmlFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) {
|
KmlFileTrackImporter(Context context, ContentProviderUtils contentProviderUtils) {
|
||||||
super(context, importTrackId, contentProviderUtils);
|
super(context, contentProviderUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String tag, Attributes attributes)
|
public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException {
|
||||||
throws SAXException {
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case TAG_PLACEMARK:
|
case TAG_PLACEMARK:
|
||||||
case TAG_PHOTO_OVERLAY:
|
case TAG_PHOTO_OVERLAY:
|
||||||
@@ -109,50 +104,70 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endElement(String uri, String localName, String tag) throws SAXException {
|
public void endElement(String uri, String localName, String tag) throws SAXException {
|
||||||
//TODO Check if order is relevant (uses localname and tag); and convert to switch statement
|
switch (tag) {
|
||||||
if (tag.equals(TAG_KML)) {
|
case TAG_KML:
|
||||||
onFileEnd();
|
onFileEnd();
|
||||||
} else if (tag.equals(TAG_PLACEMARK) || tag.equals(TAG_PHOTO_OVERLAY)) {
|
break;
|
||||||
// Note that a track is contained in a Placemark, calling onWaypointend is save since waypointType is not set for a track.
|
case TAG_PLACEMARK:
|
||||||
onWaypointEnd();
|
case TAG_PHOTO_OVERLAY:
|
||||||
} else if (localName.equals(TAG_COORDINATES)) {
|
// Note that a track is contained in a Placemark, calling onWaypointend is save since waypointType is not set for a track.
|
||||||
onWaypointLocationEnd();
|
onWaypointEnd();
|
||||||
} else if (tag.equals(TAG_GX_MULTI_TRACK)) {
|
break;
|
||||||
onTrackEnd();
|
case TAG_COORDINATES:
|
||||||
} else if (tag.equals(TAG_GX_TRACK)) {
|
onWaypointLocationEnd();
|
||||||
onTrackSegmentEnd();
|
break;
|
||||||
} else if (tag.equals(TAG_GX_COORD)) {
|
case TAG_GX_MULTI_TRACK:
|
||||||
onTrackPointEnd();
|
onTrackEnd();
|
||||||
} else if (tag.equals(TAG_GX_VALUE)) {
|
break;
|
||||||
onExtendedDataValueEnd();
|
case TAG_GX_TRACK:
|
||||||
} else if (tag.equals(TAG_NAME)) {
|
onTrackSegmentEnd();
|
||||||
if (content != null) {
|
break;
|
||||||
name = content.trim();
|
case TAG_GX_COORD:
|
||||||
}
|
onTrackPointEnd();
|
||||||
} else if (localName.equals(TAG_DESCRIPTION)) {
|
break;
|
||||||
if (content != null) {
|
case TAG_GX_VALUE:
|
||||||
description = content.trim();
|
onExtendedDataValueEnd();
|
||||||
}
|
break;
|
||||||
} else if (localName.equals(TAG_ICON)) {
|
case TAG_NAME:
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
icon = content.trim();
|
name = content.trim();
|
||||||
}
|
}
|
||||||
} else if (localName.equals(TAG_VALUE)) {
|
break;
|
||||||
if (content != null) {
|
case TAG_UUID:
|
||||||
category = content.trim();
|
if (content != null) {
|
||||||
}
|
uuid = content.trim();
|
||||||
} else if (localName.equals(TAG_WHEN)) {
|
}
|
||||||
if (content != null) {
|
break;
|
||||||
time = content.trim();
|
case TAG_DESCRIPTION:
|
||||||
}
|
if (content != null) {
|
||||||
} else if (localName.equals(TAG_STYLE_URL)) {
|
description = content.trim();
|
||||||
if (content != null) {
|
}
|
||||||
waypointType = content.trim();
|
break;
|
||||||
}
|
case TAG_ICON:
|
||||||
} else if (localName.equals(TAG_HREF)) {
|
if (content != null) {
|
||||||
if (content != null) {
|
icon = content.trim();
|
||||||
photoUrl = content.trim();
|
}
|
||||||
}
|
break;
|
||||||
|
case TAG_VALUE:
|
||||||
|
if (content != null) {
|
||||||
|
category = content.trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TAG_WHEN:
|
||||||
|
if (content != null) {
|
||||||
|
time = content.trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TAG_STYLE_URL:
|
||||||
|
if (content != null) {
|
||||||
|
waypointType = content.trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TAG_HREF:
|
||||||
|
if (content != null) {
|
||||||
|
photoUrl = content.trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset element content
|
// Reset element content
|
||||||
|
|||||||
@@ -52,18 +52,15 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final long importTrackId;
|
private long importTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
private final Uri uriKmzFile;
|
private final Uri uriKmzFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context the context
|
* @param context the context
|
||||||
* @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported.
|
* @param uriFile URI of the kmz file.
|
||||||
* @param uriFile URI of the kmz file.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated //TODO Do not pass importTrackId here; get it from somewhere else
|
public KmzTrackImporter(Context context, Uri uriFile) {
|
||||||
public KmzTrackImporter(Context context, long importTrackId, Uri uriFile) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.importTrackId = importTrackId;
|
|
||||||
this.uriKmzFile = uriFile;
|
this.uriKmzFile = uriFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +241,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
* @return the imported track id or -1L
|
* @return the imported track id or -1L
|
||||||
*/
|
*/
|
||||||
private long parseKml(ZipInputStream zipInputStream) throws IOException {
|
private long parseKml(ZipInputStream zipInputStream) throws IOException {
|
||||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, importTrackId);
|
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context);
|
||||||
|
|
||||||
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream))) {
|
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream))) {
|
||||||
return kmlFileTrackImporter.importFile(byteArrayInputStream);
|
return kmlFileTrackImporter.importFile(byteArrayInputStream);
|
||||||
|
|||||||
Reference in New Issue
Block a user