diff --git a/src/androidTest/java/de/dennisguse/opentracks/BootReceiverTest.java b/src/androidTest/java/de/dennisguse/opentracks/BootReceiverTest.java index 1ef234a22..bf752bc12 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/BootReceiverTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/BootReceiverTest.java @@ -87,6 +87,8 @@ public class BootReceiverTest { */ private boolean isServiceExisted(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + Assert.assertNotNull(activityManager); + List serviceList = activityManager.getRunningServices(Integer.MAX_VALUE); for (int i = 0; i < serviceList.size(); i++) { diff --git a/src/androidTest/java/de/dennisguse/opentracks/TrackStubUtils.java b/src/androidTest/java/de/dennisguse/opentracks/TrackStubUtils.java index a2f0f5ca5..79c34f9c8 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/TrackStubUtils.java +++ b/src/androidTest/java/de/dennisguse/opentracks/TrackStubUtils.java @@ -24,7 +24,6 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet; /** * Commons utilities for creating stubs of track, location. - * The class will be enriched if needs more similar stubs for test. * * @author Youtao Liu */ @@ -50,8 +49,7 @@ public class TrackStubUtils { public static Track createTrack(int numberOfLocations) { Track track = new Track(); for (int i = 0; i < numberOfLocations; i++) { - track.addLocation(createSensorDataSetLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE - + i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE)); + track.addLocation(createSensorDataSetLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE + i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE)); } return track; @@ -71,7 +69,7 @@ public class TrackStubUtils { * * @return a SensorDataSetLocation stub. */ - public static SensorDataSetLocation createSensorDataSetLocation(double latitude, double longitude, double altitude) { + private static SensorDataSetLocation createSensorDataSetLocation(double latitude, double longitude, double altitude) { // Initial Location Location loc = new Location(LOCATION_PROVIDER); loc.setLatitude(latitude); diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/CustomContentProviderUtilsImplTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/CustomContentProviderUtilsImplTest.java index 3d454a79f..432c0577e 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/CustomContentProviderUtilsImplTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/CustomContentProviderUtilsImplTest.java @@ -137,8 +137,7 @@ public class CustomContentProviderUtilsImplTest { long lastPointId = initializeTrack(trackId, numPoints); ((ContentProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize); List locations = new ArrayList(numPoints); - LocationIterator it = providerUtils.getTrackPointLocationIterator(trackId, -1L, descending, locationFactory); - try { + try (LocationIterator it = providerUtils.getTrackPointLocationIterator(trackId, -1L, descending, locationFactory)) { while (it.hasNext()) { Location loc = it.next(); Assert.assertNotNull(loc); @@ -148,8 +147,6 @@ public class CustomContentProviderUtilsImplTest { : lastPointId - numPoints + locations.size(), it.getLocationId()); } Assert.assertEquals(numPoints, locations.size()); - } finally { - it.close(); } return locations; } @@ -177,15 +174,12 @@ public class CustomContentProviderUtilsImplTest { // Load all inserted locations. long lastPointId = -1; int counter = 0; - LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY); - try { + try (LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY)) { while (it.hasNext()) { it.next(); lastPointId = it.getLocationId(); counter++; } - } finally { - it.close(); } Assert.assertTrue(numPoints == 0 || lastPointId > 0); @@ -270,26 +264,20 @@ public class CustomContentProviderUtilsImplTest { providerUtils.insertWaypoint(waypoint); ContentResolver contentResolver = context.getContentResolver(); - Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, - TracksColumns._ID); + Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); Assert.assertEquals(3, tracksCursor.getCount()); - Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, - null, TrackPointsColumns._ID); + Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, null, TrackPointsColumns._ID); Assert.assertEquals(20, tracksPointsCursor.getCount()); - Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, - null, WaypointsColumns._ID); + Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); Assert.assertEquals(1, waypointCursor.getCount()); // Delete one track. providerUtils.deleteTrack(context, trackId); // Check whether all data of a track has been deleted. - tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, - TracksColumns._ID); + tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID); Assert.assertEquals(2, tracksCursor.getCount()); - tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, - null, TrackPointsColumns._ID); + tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, null, TrackPointsColumns._ID); Assert.assertEquals(20, tracksPointsCursor.getCount()); - waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, - null, WaypointsColumns._ID); + waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID); Assert.assertEquals(0, waypointCursor.getCount()); } @@ -374,12 +362,12 @@ public class CustomContentProviderUtilsImplTest { waypoint.setType(WaypointType.STATISTICS); waypoint.setTripStatistics(statistics); - Location loc = new Location("test"); - loc.setLatitude(22); - loc.setLongitude(22); - loc.setAccuracy((float) 1 / 100.0f); - loc.setAltitude(2.5); - waypoint.setLocation(loc); + Location location = new Location("test"); + location.setLatitude(22); + location.setLongitude(22); + location.setAccuracy((float) 1 / 100.0f); + location.setAltitude(2.5); + waypoint.setLocation(location); providerUtils.insertWaypoint(waypoint); ContentProviderUtilsImpl contentProviderUtils = new ContentProviderUtilsImpl(contentResolverMock); @@ -780,9 +768,7 @@ public class CustomContentProviderUtilsImplTest { } /** - * Tests the method - * {@link ContentProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} - * in descending. + * Tests the method {@link ContentProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} in descending. */ @Test public void testGetTrackPointCursor_desc() { @@ -801,9 +787,7 @@ public class CustomContentProviderUtilsImplTest { } /** - * Tests the method - * {@link ContentProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} - * in ascending. + * Tests the method {@link ContentProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} in ascending. */ @Test public void testGetTrackPointCursor_asc() { @@ -849,9 +833,7 @@ public class CustomContentProviderUtilsImplTest { } /** - * Tests the method - * {@link ContentProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)} - * in ascending. + * Tests the method {@link ContentProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)} in ascending. */ @Test public void testGetTrackPointLocationIterator_asc() { @@ -914,8 +896,7 @@ public class CustomContentProviderUtilsImplTest { /** * Checks the value of a location. * - * @param i the index of this location which created in the method - * {@link CustomContentProviderUtilsImplTest#getTrack(long, int)} + * @param i the index of this location which created in the method {@link CustomContentProviderUtilsImplTest#getTrack(long, int)} * @param location the location to be checked */ private void checkLocation(int i, Location location) { diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/DescriptionGeneratorImplTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/DescriptionGeneratorImplTest.java index 91cd97381..86f3c5964 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/DescriptionGeneratorImplTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/DescriptionGeneratorImplTest.java @@ -49,7 +49,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track, java.util.Vector, java.util.Vector, boolean)}. + * Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track, boolean)}. */ @Test public void testGenerateTrackDescription() { @@ -128,8 +128,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder, - * int, String)}. + * Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder, int, String)}. */ @Test public void testWriteDistance() { @@ -139,8 +138,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int, - * String)}. + * Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int, String)}. */ @Test public void testWriteTime() { @@ -150,8 +148,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder, - * int, String)}. + * Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder, int, String)}. */ @Test public void testWriteSpeed() { @@ -161,8 +158,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder, - * int, String)}. + * Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder, int, String)}. */ @Test public void testWriteElevation() { @@ -172,8 +168,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writePace(double, StringBuilder, int, - * String)}. + * Tests {@link DescriptionGeneratorImpl#writePace(double, StringBuilder, int, String)}. */ @Test public void testWritePace() { @@ -183,8 +178,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, - * int, String)}. + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, int, String)}. */ @Test public void testWriteGrade() { @@ -194,8 +188,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, - * int, String)} with a NaN. + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, int, String)} with a NaN. */ @Test public void testWriteGrade_nan() { @@ -205,8 +198,7 @@ public class DescriptionGeneratorImplTest { } /** - * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, - * int, String)} with an infinite number. + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, int, String)} with an infinite number. */ @Test public void testWriteGrade_infinite() { diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java index 5d2e99cb2..7351809ab 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/SearchEngineTest.java @@ -40,9 +40,8 @@ import de.dennisguse.opentracks.stats.TripStatistics; /** * Tests for {@link SearchEngine}. - * These are not meant to be quality tests, but instead feature-by-feature tests - * (in other words, they don't test the mixing of different score boostings, just - * each boosting separately) + * These are not meant to be quality tests, but instead feature-by-feature tests. + * In other words, they don't test the mixing of different score boostings, just each boosting separately. * * @author Rodrigo Damazio */ @@ -50,7 +49,7 @@ import de.dennisguse.opentracks.stats.TripStatistics; public class SearchEngineTest { private static final Location HERE = new Location("gps"); - private static final long NOW = 1234567890000L; // After OLDEST_ALLOWED_TIMESTAMP + private static final long NOW = SearchEngine.OLDEST_ALLOWED_TIMESTAMP + 1000; // After OLDEST_ALLOWED_TIMESTAMP private ContentProviderUtils providerUtils; private SearchEngine engine; diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/WaypointCreationRequestTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/WaypointCreationRequestTest.java index 1aa920645..2fc4acdeb 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/WaypointCreationRequestTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/WaypointCreationRequestTest.java @@ -26,8 +26,7 @@ import org.junit.runner.RunWith; import de.dennisguse.opentracks.content.Waypoint.WaypointType; /** - * Tests for the WaypointCreationRequest class. - * {@link WaypointCreationRequest} + * Tests for the {@link WaypointCreationRequest} class. * * @author Sandor Dornbush */ diff --git a/src/androidTest/java/de/dennisguse/opentracks/fragments/ChartFragmentTest.java b/src/androidTest/java/de/dennisguse/opentracks/fragments/ChartFragmentTest.java index e1c0d7775..e4b5b3417 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/fragments/ChartFragmentTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/fragments/ChartFragmentTest.java @@ -52,7 +52,7 @@ public class ChartFragmentTest { } /** - * Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(Location, double[])} + * Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(Location, double[])}. */ @Test public void testFillDataPoint_sensorIncorrect() { @@ -161,12 +161,11 @@ public class ChartFragmentTest { point = fillDataPointTestHelper(sensorDataSetLocation2); /* - * Computes the distance between Latitude 22 and 23. And for we set using - * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. + * Computes the distance between Latitude 22 and 23. + * And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. */ float[] results = new float[4]; - Location.distanceBetween(sensorDataSetLocation1.getLatitude(), sensorDataSetLocation1.getLongitude(), - sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), results); + Location.distanceBetween(sensorDataSetLocation1.getLatitude(), sensorDataSetLocation1.getLongitude(), sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), results); double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; Assert.assertEquals(distance1, point[0], 0.01); @@ -176,11 +175,10 @@ public class ChartFragmentTest { point = fillDataPointTestHelper(sensorDataSetLocation3); /* - * Computes the distance between Latitude 23 and 24. And for we set using - * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. + * Computes the distance between Latitude 23 and 24. + * And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. */ - Location.distanceBetween(sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), - sensorDataSetLocation3.getLatitude(), sensorDataSetLocation3.getLongitude(), results); + Location.distanceBetween(sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), sensorDataSetLocation3.getLatitude(), sensorDataSetLocation3.getLongitude(), results); double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; Assert.assertEquals(distance1 + distance2, point[0], 0.01); } @@ -210,15 +208,14 @@ public class ChartFragmentTest { SensorDataSetLocation sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); /* - * At first, clear old points of elevation, so give true to the second - * parameter. Then only one value INITIALLONGTITUDE in buffer. + * At first, clear old points of elevation, so give true to the second parameter. + * Then only one value INITIAL_ALTITUDE in buffer. */ double[] point = fillDataPointTestHelper(sensorDataSetLocation1); Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1], 0.01); /* - * Send another value to buffer, now there are two values, INITIALALTITUDE - * and INITIALALTITUDE * 2. + * Send another value to buffer, now there are two values, INITIAL_ALTITUDE and INITIAL_ALTITUDE * 2. */ SensorDataSetLocation sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); sensorDataSetLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2); @@ -235,8 +232,8 @@ public class ChartFragmentTest { @Test public void testFillDataPoint_speed() { /* - * At first, clear old points of speed, so give true to the second - * parameter. It will not be filled in to the speed buffer. + * At first, clear old points of speed, so give true to the second parameter. + * It will not be filled in to the speed buffer. */ SensorDataSetLocation sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); sensorDataSetLocation1.setSpeed(128.5f); @@ -244,14 +241,13 @@ public class ChartFragmentTest { Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01); /* - * Tests the logic when both metricUnits and reportSpeed are true.This - * location will be filled into speed buffer. + * Tests the logic when both metricUnits and reportSpeed are true. + * This location will be filled into speed buffer. */ SensorDataSetLocation sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); /* - * Add a time span here to make sure the second point is valid, the value - * 222 here is doesn't matter. + * Add a time span here to make sure the second point is valid, the value 222 here is doesn't matter. */ sensorDataSetLocation2.setTime(sensorDataSetLocation1.getTime() + 222); sensorDataSetLocation2.setSpeed(130); @@ -276,9 +272,8 @@ public class ChartFragmentTest { SensorDataSetLocation sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); /* - * Add a time span here to make sure the second point is valid and the speed - * is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION - * * timeDifference speedDifference = 102 -100 timeDifference = 222 + * Add a time span here to make sure the second point and the speed is valid. + * Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222 */ sensorDataSetLocation2.setTime(sensorDataSetLocation2.getTime() + 222); sensorDataSetLocation2.setSpeed(102); @@ -303,9 +298,8 @@ public class ChartFragmentTest { SensorDataSetLocation sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); /* - * Add a time span here to make sure the second point is valid and the speed - * is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION - * * timeDifference speedDifference = 102 -100 timeDifference = 222 + * Add a time span here to make sure the second point and the speed is valid. + * Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222 */ sensorDataSetLocation2.setTime(sensorDataSetLocation2.getTime() + 222); sensorDataSetLocation2.setSpeed(102); @@ -314,8 +308,7 @@ public class ChartFragmentTest { } /** - * Tests the logic to get pace value when reportSpeed is false and average - * speed is zero. + * Tests the logic to get pace value when reportSpeed is false and average speed is zero. */ @Test public void testFillDataPoint_pace_zeroSpeed() { diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java index 588571213..c0d5c0233 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java @@ -49,40 +49,32 @@ import static org.mockito.Mockito.when; */ public abstract class AbstractTestFileTrackImporter { - protected static final String TRACK_NAME_0 = "blablub"; - protected static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer"; + static final String TRACK_NAME_0 = "blablub"; + static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer"; - protected static final String TRACK_NAME_1 = "another track"; - protected static final String TRACK_DESCRIPTION_1 = "another description"; + static final double TRACK_LATITUDE = 48.768364; + static final double TRACK_LONGITUDE = 9.177886; + static final double TRACK_ELEVATION = 324.0; - protected static final double TRACK_LATITUDE = 48.768364; - protected static final double TRACK_LONGITUDE = 9.177886; - protected static final double TRACK_ELEVATION = 324.0; + static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z"; + static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123"; + static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123"; + static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123"; - protected static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z"; - protected static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123"; - protected static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123"; - protected static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123"; - - protected static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US); - protected static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US); - protected static final long TRACK_ID_0 = 1; - protected static final long TRACK_ID_1 = 2; - protected static final long TRACK_POINT_ID_0 = 1; - protected static final long TRACK_POINT_ID_1 = 2; - protected static final long TRACK_POINT_ID_3 = 4; - protected static final long WAYPOINT_ID_0 = 1; - protected static final Uri TRACK_ID_0_URI = ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build(); - protected static final Uri TRACK_ID_1_URI = ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_1).build(); - protected static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build(); + 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 long TRACK_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_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 Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build(); protected final Context context = ApplicationProvider.getApplicationContext(); 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"); DATE_FORMAT_0.setTimeZone(utc); DATE_FORMAT_1.setTimeZone(utc); @@ -91,7 +83,7 @@ public abstract class AbstractTestFileTrackImporter { @Mock public ContentProviderUtils contentProviderUtils; - protected Location createLocation(int index, long time) { + Location createLocation(int index, long time) { Location location = new Location(LocationManager.GPS_PROVIDER); location.setLatitude(TRACK_LATITUDE + index); location.setLongitude(TRACK_LONGITUDE + index); diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporterTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporterTest.java index f03a402ea..3c5bbfdf0 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporterTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporterTest.java @@ -38,7 +38,6 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; - /** * Tests for {@link GpxFileTrackImporter}. * @@ -58,6 +57,7 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + getTrackPoint(0, null) + getTrackPoint(1, null) + "" + getTrackPoint(2, null) + getTrackPoint(3, null) + ""; + 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"); @@ -82,9 +82,6 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { return buffer.toString(); } - /** - * Tests one track with one segment. - */ @Test public void testOneTrackOneSegment() throws Exception { ArgumentCaptor trackCaptor = ArgumentCaptor.forClass(Track.class); @@ -113,9 +110,6 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0); } - /** - * Tests one track with two segments. - */ @Test public void testOneTrackTwoSegments() throws Exception { ArgumentCaptor trackCaptor = ArgumentCaptor.forClass(Track.class); @@ -145,9 +139,6 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); } - /** - * Tests one track with two segments, but no time in the track points. - */ @Test public void testOneTrackTwoSegmentsNoTime() { ArgumentCaptor trackCaptor = ArgumentCaptor.forClass(Track.class); @@ -171,49 +162,31 @@ public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L); } - /** - * Test an invalid xml input. - */ @Test public void testInvalidXml() { testInvalidGpx(INVALID_XML_GPX); } - /** - * Test an invalid location. - */ @Test public void testInvalidLocation() { testInvalidGpx(INVALID_LOCATION_GPX); } - /** - * Test an invalid time. - */ @Test public void testInvalidTime() { testInvalidGpx(INVALID_TIME_GPX); } - /** - * Test an invalid altitude. - */ @Test public void testInvalidAltitude() { testInvalidGpx(INVALID_ALTITUDE_GPX); } - /** - * Test an invalid latitude. - */ @Test public void testInvalidLatitude() { testInvalidGpx(INVALID_LATITUDE_GPX); } - /** - * Test an invalid longitude. - */ @Test public void testInvalidLongitude() { testInvalidGpx(INVALID_LONGITUDE_GPX); diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporterTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporterTest.java index 95a3e9adc..3fedfbe90 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporterTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporterTest.java @@ -36,7 +36,6 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; - /** * Tests for {@link KmlFileTrackImporter}. * @@ -45,13 +44,11 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { - private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = - "" + private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "" + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + ""; - private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = - "" + private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "" + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "" + getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) @@ -66,14 +63,9 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { String latitude = Double.toString(TRACK_LATITUDE + index); String longitude = Double.toString(TRACK_LONGITUDE + index); String altitude = Double.toString(TRACK_ELEVATION + index); - StringBuilder buffer = new StringBuilder(); - buffer.append("" + time + "" + "" + longitude + " " + latitude + " " + altitude + ""); - return buffer.toString(); + return "" + time + "" + "" + longitude + " " + latitude + " " + altitude + ""; } - /** - * Tests one track with one segment. - */ @Test public void testOneTrackOneSegment() throws Exception { ArgumentCaptor trackCaptor = ArgumentCaptor.forClass(Track.class); @@ -102,9 +94,6 @@ public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0); } - /** - * Tests one track with two segments. - */ @Test public void testOneTrackTwoSegments() throws Exception { ArgumentCaptor trackCaptor = ArgumentCaptor.forClass(Track.class); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicyTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicyTest.java index 9c477e0d3..22407acef 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicyTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicyTest.java @@ -40,9 +40,7 @@ public class AdaptiveLocationListenerPolicyTest extends TestCase { } /** - * Tests the - * {@link AdaptiveLocationListenerPolicy#getDesiredPollingInterval()} in four - * situations. + * Tests the {@link AdaptiveLocationListenerPolicy#getDesiredPollingInterval()} in four situations. *
    *
  • The newIdleTime is bigger than max interval.
  • *
  • The newIdleTime is between min and max interval.
  • @@ -68,9 +66,9 @@ public class AdaptiveLocationListenerPolicyTest extends TestCase { } /** - * Tests the method {@link AdaptiveLocationListenerPolicy#getMinDistance()}. + * Tests the method {@link AdaptiveLocationListenerPolicy#getMinDistance_m()}. */ public void testGetMinDistance() { - assertEquals(MIN_DISTANCE, adocationListenerPolicy.getMinDistance()); + assertEquals(MIN_DISTANCE, adocationListenerPolicy.getMinDistance_m()); } } diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/ControlRecordingServiceTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/ControlRecordingServiceTest.java index 982edac31..3ad6f8d86 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/ControlRecordingServiceTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/ControlRecordingServiceTest.java @@ -59,9 +59,7 @@ public class ControlRecordingServiceTest { private ControlRecordingService subject; /** - * Tests the start of {@link ControlRecordingService} and tests the method - * {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} - * to start a track recording. + * Tests the start of {@link ControlRecordingService} and tests the method {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} to start a track recording. */ @Test public void testStartRecording() throws TimeoutException { @@ -75,9 +73,7 @@ public class ControlRecordingServiceTest { } /** - * Tests the method - * {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} - * to stop a track recording. + * Tests the method {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} to stop a track recording. */ @Test public void testStopRecording() throws TimeoutException { diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java index 9ec4d0934..1b431274a 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTest.java @@ -67,8 +67,9 @@ public class TrackRecordingServiceTest { @Rule public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS); - private ContentProviderUtils providerUtils; + private Context context = ApplicationProvider.getApplicationContext(); + private ContentProviderUtils providerUtils; private long trackId = Math.abs(new Random().nextLong()); @@ -210,7 +211,7 @@ public class TrackRecordingServiceTest { // We don't expect to resume the previous track, because it has expired. Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); } @MediumTest @@ -234,7 +235,7 @@ public class TrackRecordingServiceTest { // We don't expect to resume the previous track, because there were already too many attempts. Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); } @MediumTest @@ -256,7 +257,7 @@ public class TrackRecordingServiceTest { ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context))); Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); } @MediumTest @@ -268,14 +269,14 @@ public class TrackRecordingServiceTest { // Make sure that the service will not start recording and will clear the bogus track. ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context))); Assert.assertFalse(service.isRecording()); - Assert.assertEquals(-1L, service.getRecordingTrackId()); + Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); } @MediumTest @Test public void testStartNewTrack_noRecording() throws Exception { - // NOTICE: due to the way Android permissions work, if this fails, - // uninstall the test apk then retry - the test must be installed *after* the app (go figure). + // NOTICE: due to the way Android permissions work, if this fails, uninstall the test apk then retry. + // The test must be installed *after* the app (go figure). // Reference: http://code.google.com/p/android/issues/detail?id=5521 BlockingBroadcastReceiver startReceiver = new BlockingBroadcastReceiver(); String startAction = context.getString(R.string.track_started_broadcast_action); @@ -287,15 +288,15 @@ public class TrackRecordingServiceTest { ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context))); Assert.assertFalse(service.isRecording()); - long id = service.startNewTrack(); - Assert.assertTrue(id >= 0); + long newTrackId = service.startNewTrack(); + Assert.assertTrue(newTrackId >= 0); Assert.assertTrue(service.isRecording()); - Track track = providerUtils.getTrack(id); + Track track = providerUtils.getTrack(newTrackId); Assert.assertNotNull(track); - Assert.assertEquals(id, track.getId()); + Assert.assertEquals(newTrackId, track.getId()); Assert.assertEquals(PreferencesUtils.getString(context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT), track.getCategory()); - Assert.assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); - Assert.assertEquals(id, service.getRecordingTrackId()); + Assert.assertEquals(newTrackId, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + Assert.assertEquals(newTrackId, service.getRecordingTrackId()); // Verify that the start broadcast was received. Assert.assertTrue(startReceiver.waitUntilReceived(1)); @@ -303,7 +304,7 @@ public class TrackRecordingServiceTest { Assert.assertEquals(1, receivedIntents.size()); Intent broadcastIntent = receivedIntents.get(0); Assert.assertEquals(startAction, broadcastIntent.getAction()); - Assert.assertEquals(id, broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L)); + Assert.assertEquals(newTrackId, broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L)); context.unregisterReceiver(startReceiver); } @@ -316,9 +317,8 @@ public class TrackRecordingServiceTest { ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context))); Assert.assertTrue(service.isRecording()); - // Starting a new track when there is a recording should just return -1L. - long newTrack = service.startNewTrack(); - Assert.assertEquals(-1L, newTrack); + long newTrackId = service.startNewTrack(); + Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId); Assert.assertEquals(trackId, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); Assert.assertEquals(trackId, service.getRecordingTrackId()); @@ -360,9 +360,7 @@ public class TrackRecordingServiceTest { ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(createStartIntent(context))); Assert.assertFalse(service.isRecording()); - /* - * Ending the current track when there is no recording should not result in any error. - */ + // Ending the current track when there is no recording should not result in any error. service.endCurrentTrack(); Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); @@ -407,7 +405,7 @@ public class TrackRecordingServiceTest { // TODO: Check waypoint 2. } - private Track createDummyTrack(long id, long stopTime, boolean isRecording) { + private void createDummyTrack(long id, long stopTime, boolean isRecording) { Track dummyTrack = new Track(); dummyTrack.setId(id); dummyTrack.setName("Dummy Track"); @@ -415,7 +413,6 @@ public class TrackRecordingServiceTest { tripStatistics.setStopTime(stopTime); dummyTrack.setTripStatistics(tripStatistics); addTrack(dummyTrack, isRecording); - return dummyTrack; } private void addTrack(Track track, boolean isRecording) { @@ -427,7 +424,7 @@ public class TrackRecordingServiceTest { } /** - * Inserts a location and waits for 100ms. + * Inserts a location and waits for 200ms. */ private void insertLocation(ITrackRecordingService trackRecordingService) throws InterruptedException { Location location = new Location("gps"); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java index 7ceb67a08..f2533ccc6 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceTestLooper.java @@ -45,9 +45,11 @@ public class TrackRecordingServiceTestLooper { @Rule public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS); - private ContentProviderUtils providerUtils; + private Context context = ApplicationProvider.getApplicationContext(); + private ContentProviderUtils providerUtils; + @BeforeClass public static void preSetUp() { // Prepare looper for Android's message queue @@ -93,28 +95,28 @@ public class TrackRecordingServiceTestLooper { @MediumTest @Test - public void testWithProperties_minRequiredAccuracy() throws Exception { + public void testWithProperties_minRequiredAccuracy() throws TimeoutException { PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, 500); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_voiceFrequencyDefault() throws Exception { + public void testWithProperties_voiceFrequencyDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_voiceFrequencyByDistance() throws Exception { + public void testWithProperties_voiceFrequencyByDistance() throws TimeoutException { PreferencesUtils.setInt(context, R.string.voice_frequency_key, -1); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_voiceFrequencyByTime() throws Exception { + public void testWithProperties_voiceFrequencyByTime() throws TimeoutException { PreferencesUtils.setInt(context, R.string.voice_frequency_key, 1); fullRecordingSession(); } @@ -122,97 +124,97 @@ public class TrackRecordingServiceTestLooper { @MediumTest @Test - public void testWithProperties_maxRecordingDistanceDefault() throws Exception { + public void testWithProperties_maxRecordingDistanceDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.max_recording_distance_key, PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_maxRecordingDistance() throws Exception { + public void testWithProperties_maxRecordingDistance() throws TimeoutException { PreferencesUtils.setInt(context, R.string.max_recording_distance_key, 50); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_minRecordingDistanceDefault() throws Exception { + public void testWithProperties_minRecordingDistanceDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_minRecordingDistance() throws Exception { + public void testWithProperties_minRecordingDistance() throws TimeoutException { PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, 2); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_splitFrequencyDefault() throws Exception { + public void testWithProperties_splitFrequencyDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_splitFrequencyByDistance() throws Exception { + public void testWithProperties_splitFrequencyByDistance() throws TimeoutException { PreferencesUtils.setInt(context, R.string.split_frequency_key, -1); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_splitFrequencyByTime() throws Exception { + public void testWithProperties_splitFrequencyByTime() throws TimeoutException { PreferencesUtils.setInt(context, R.string.split_frequency_key, 1); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_metricUnitsDefault() throws Exception { + public void testWithProperties_metricUnitsDefault() throws TimeoutException { PreferencesUtils.setString(context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_metricUnitsDisabled() throws Exception { + public void testWithProperties_metricUnitsDisabled() throws TimeoutException { PreferencesUtils.setString(context, R.string.stats_units_key, context.getString(R.string.stats_units_imperial)); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_minRecordingIntervalDefault() throws Exception { + public void testWithProperties_minRecordingIntervalDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.min_recording_interval_key, PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_minRecordingInterval() throws Exception { + public void testWithProperties_minRecordingInterval() throws TimeoutException { PreferencesUtils.setInt(context, R.string.min_recording_interval_key, 2); fullRecordingSession(); } @MediumTest @Test - public void testWithProperties_minRequiredAccuracyDefault() throws Exception { + public void testWithProperties_minRequiredAccuracyDefault() throws TimeoutException { PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT); fullRecordingSession(); } @MediumTest @Test - public void testIntegration_completeRecordingSession() throws Exception { + public void testIntegration_completeRecordingSession() throws TimeoutException { List tracks = providerUtils.getAllTracks(); Assert.assertTrue(tracks.isEmpty()); fullRecordingSession(); } - private void fullRecordingSession() throws Exception { + private void fullRecordingSession() throws TimeoutException { ITrackRecordingService service = ((ITrackRecordingService) mServiceRule.bindService(TrackRecordingServiceTest.createStartIntent(context))); Assert.assertFalse(service.isRecording()); diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java index f56e7bdce..a58c52dce 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java @@ -30,7 +30,6 @@ import org.junit.runner.RunWith; /** * Tests for {@link AnnouncementPeriodicTaskFactory}. - * These tests require Donut+ to run. * * @author Rodrigo Damazio */ diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskTest.java index d598a23b0..50b88c67a 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTaskTest.java @@ -52,8 +52,10 @@ import static org.mockito.Mockito.when; /** * Tests for {@link AnnouncementPeriodicTask}. - * WARNING: I'm not responsible if your eyes start bleeding while reading this - * code. You have been warned. It's still better than no test, though. + * + * WARNING: I'm not responsible if your eyes start bleeding while reading this code. + * You have been warned. + * It's still better than no test, though. * * @author Rodrigo Damazio */ diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/FileUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/FileUtilsTest.java index ef508319a..0042e8dfd 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/FileUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/FileUtilsTest.java @@ -32,16 +32,13 @@ public class FileUtilsTest extends TestCase { * Tests {@link FileUtils#getPath(String...)}. */ public void testBuildExternalDirectoryPath() { - String expectedName = Environment.getExternalStorageDirectory() + File.separator - + FileUtils.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator - + "c"; + String expectedName = Environment.getExternalStorageDirectory() + File.separator + FileUtils.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator + "c"; String dirName = FileUtils.getPath("a", "b", "c"); assertEquals(expectedName, dirName); } /** - * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the - * file is new. + * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the file is new. */ public void testBuildUniqueFileName_new() { String filename = FileUtils.buildUniqueFileName(new File("/dir"), "Filename", "ext"); @@ -49,8 +46,7 @@ public class FileUtilsTest extends TestCase { } /** - * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the - * file exists already. + * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the file exists already. */ public void testBuildUniqueFileName_exist() { // Expect "/default.prop" to exist on the phone/emulator @@ -69,8 +65,8 @@ public class FileUtilsTest extends TestCase { } /** - * Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in - * Chinese and Russian). Verifies that they are allowed. + * Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in Chinese and Russian). + * Verifies that they are allowed. */ public void testSanitizeFileName_i18n() { String name = "您好-привет"; @@ -79,8 +75,8 @@ public class FileUtilsTest extends TestCase { } /** - * Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32 - * characters. Verifies that they are allowed. + * Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32 characters. + * Verifies that they are allowed. */ public void testSanitizeFileName_special_characters() { String name = "$%'-_@~`!(){}^#&+,;=[] "; @@ -89,8 +85,8 @@ public class FileUtilsTest extends TestCase { } /** - * Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped - * characters in a row. Verifies that they are collapsed into one underscore. + * Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped characters in a row. + * Verifies that they are collapsed into one underscore. */ public void testSanitizeFileName_collapse() { String name = "hello//there"; @@ -99,8 +95,8 @@ public class FileUtilsTest extends TestCase { } /** - * Tests {@link FileUtils#truncateFileName(File, String, String)}. Verifies - * the a long file name is truncated. + * Tests {@link FileUtils#truncateFileName(File, String, String)}. + * Verifies the a long file name is truncated. */ public void testTruncateFileName() { File directory = new File("/dir1/dir2/"); @@ -115,7 +111,6 @@ public class FileUtilsTest extends TestCase { for (int i = 0; i < truncated.length(); i++) { assertEquals('a', truncated.charAt(i)); } - assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH, - new File(directory, truncated + suffix).getPath().length()); + assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH, new File(directory, truncated + suffix).getPath().length()); } } diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java index 0304f4b88..dc4693486 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java @@ -161,8 +161,7 @@ public class StringUtilsTest { } /** - * Asserts the {@link StringUtils#getTime(String)} returns the expected - * values. + * Asserts the {@link StringUtils#getTime(String)} returns the expected values. * * @param xmlDateTime the xml date time string * @param year the expected year @@ -173,8 +172,7 @@ public class StringUtilsTest { * @param second the expected second * @param millisecond the expected milliseconds */ - private void assertGetTime(String xmlDateTime, int year, int month, int day, int hour, int minute, - int second, int millisecond) { + private void assertGetTime(String xmlDateTime, int year, int month, int day, int hour, int minute, int second, int millisecond) { GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); calendar.set(year, month - 1, day, hour, minute, second); calendar.set(GregorianCalendar.MILLISECOND, millisecond); diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java index ccb94b160..74e1dcb42 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/TrackNameUtilsTest.java @@ -45,8 +45,7 @@ public class TrackNameUtilsTest { private static final Context CONTEXT = ApplicationProvider.getApplicationContext(); /** - * Tests when the track_name_key is - * settings_recording_track_name_date_local_value. + * Tests when the track_name_key is settings_recording_track_name_date_local_value. */ @Test public void testTrackName_date_local() { @@ -55,8 +54,7 @@ public class TrackNameUtilsTest { } /** - * Tests when the track_name_key is - * settings_recording_track_name_date_iso_8601_value. + * Tests when the track_name_key is settings_recording_track_name_date_iso_8601_value. */ @Test public void testTrackName_date_iso_8601() { @@ -66,8 +64,7 @@ public class TrackNameUtilsTest { } /** - * Tests when the track_name_key is - * settings_recording_track_name_number_value. + * Tests when the track_name_key is settings_recording_track_name_number_value. */ @Test public void testTrackName_number() { diff --git a/src/main/java/de/dennisguse/opentracks/ChartValueSeries.java b/src/main/java/de/dennisguse/opentracks/ChartValueSeries.java index 369dd8800..e03dad8b6 100644 --- a/src/main/java/de/dennisguse/opentracks/ChartValueSeries.java +++ b/src/main/java/de/dennisguse/opentracks/ChartValueSeries.java @@ -25,16 +25,16 @@ import android.graphics.Path; import androidx.annotation.VisibleForTesting; -import de.dennisguse.opentracks.stats.ExtremityMonitor; - import java.text.NumberFormat; +import de.dennisguse.opentracks.stats.ExtremityMonitor; + /** * This class encapsulates the meta data for one series of the chart values. * * @author Sandor Dornbush */ -public class ChartValueSeries { +class ChartValueSeries { private static final float STROKE_WIDTH = 2f; @@ -68,8 +68,7 @@ public class ChartValueSeries { * @param fillColor the fill color * @param strokeColor the stroke color */ - public ChartValueSeries(Context context, int absoluteMin, int absoluteMax, int[] intervalValues, - int metricTitleId, int imperialTitleId, int fillColor, int strokeColor) { + ChartValueSeries(Context context, int absoluteMin, int absoluteMax, int[] intervalValues, int metricTitleId, int imperialTitleId, int fillColor, int strokeColor) { this.absoluteMin = absoluteMin; this.absoluteMax = absoluteMax; this.intervalValues = intervalValues; @@ -108,7 +107,7 @@ public class ChartValueSeries { /** * Returns true if the series is enabled. */ - public boolean isEnabled() { + boolean isEnabled() { return enabled; } @@ -117,14 +116,14 @@ public class ChartValueSeries { * * @param enabled true to enable */ - public void setEnabled(boolean enabled) { + void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Returns true if the series has data. */ - public boolean hasData() { + boolean hasData() { return extremityMonitor.hasData(); } @@ -133,14 +132,14 @@ public class ChartValueSeries { * * @param value the new value */ - public void update(double value) { + void update(double value) { extremityMonitor.update(value); } /** * Gets the path. */ - public Path getPath() { + Path getPath() { return path; } @@ -149,7 +148,7 @@ public class ChartValueSeries { * * @param canvas the canvas */ - public void drawPath(Canvas canvas) { + void drawPath(Canvas canvas) { canvas.drawPath(path, fillPaint); canvas.drawPath(path, strokePaint); } @@ -157,7 +156,7 @@ public class ChartValueSeries { /** * Updates the y axis dimension. */ - public void updateDimension() { + void updateDimension() { double min = hasData() ? extremityMonitor.getMin() : 0.0; double max = hasData() ? extremityMonitor.getMax() : 1.0; min = Math.max(min, absoluteMin); @@ -204,14 +203,15 @@ public class ChartValueSeries { /** * Gets the interval value. */ - public int getInterval() { + @VisibleForTesting + int getInterval() { return interval; } /** * Gets the min marker value. */ - public int getMinMarkerValue() { + int getMinMarkerValue() { return minMarkerValue; } @@ -226,28 +226,28 @@ public class ChartValueSeries { /** * Gets the title id. */ - public int getTitleId(boolean metricUnits) { + int getTitleId(boolean metricUnits) { return metricUnits ? metricTitleId : imperialTitleId; } /** * Gets the title paint. */ - public Paint getTitlePaint() { + Paint getTitlePaint() { return titlePaint; } /** * Gets the marker paint. */ - public Paint getMarkerPaint() { + Paint getMarkerPaint() { return markerPaint; } /** * Gets the largest marker. */ - public String getLargestMarker() { + String getLargestMarker() { String minMarker = numberFormat.format(getMinMarkerValue()); String maxMarker = numberFormat.format(getMaxMarkerValue()); return minMarker.length() >= maxMarker.length() ? minMarker : maxMarker; @@ -258,7 +258,7 @@ public class ChartValueSeries { * * @param value the value */ - public String formatMarker(int value) { + String formatMarker(int value) { return numberFormat.format(value); } } diff --git a/src/main/java/de/dennisguse/opentracks/ChartView.java b/src/main/java/de/dennisguse/opentracks/ChartView.java index c9219cfe7..f2c646fd5 100644 --- a/src/main/java/de/dennisguse/opentracks/ChartView.java +++ b/src/main/java/de/dennisguse/opentracks/ChartView.java @@ -565,7 +565,7 @@ public class ChartView extends View { * @param canvas the canvas */ private void drawSeriesTitles(Canvas canvas) { - int[] titleDimensions = getTitleDimenions(); + int[] titleDimensions = getTitleDimensions(); int lines = titleDimensions[0]; int lineHeight = titleDimensions[1]; int count = 0; @@ -583,10 +583,10 @@ public class ChartView extends View { } /** - * Gets the title dimensions. Returns an array of 2 integers, first element is - * the number of lines and the second element is the line height. + * Gets the title dimensions. + * Returns an array of 2 integers, first element is the number of lines and the second element is the line height. */ - private int[] getTitleDimenions() { + private int[] getTitleDimensions() { int lines = 0; int lineHeight = 0; for (int i = 0; i < series.length; i++) { @@ -763,8 +763,7 @@ public class ChartView extends View { } /** - * Updates paths. The path needs to be updated any time after the data or the - * dimensions change. + * Updates paths. The path needs to be updated any time after the data or the dimensions change. */ private void updatePaths() { synchronized (chartData) { @@ -862,7 +861,7 @@ public class ChartView extends View { } leftBorder = (int) (density * BORDER + markerLength); - int[] titleDimensions = getTitleDimenions(); + int[] titleDimensions = getTitleDimensions(); topBorder = (int) (density * BORDER + titleDimensions[0] * (titleDimensions[1] + spacer)); Rect xAxisLabelRect = getRect(axisPaint, getXAxisLabel()); // border + x axis marker + spacer + .5 x axis label diff --git a/src/main/java/de/dennisguse/opentracks/Constants.java b/src/main/java/de/dennisguse/opentracks/Constants.java deleted file mode 100644 index 960701f5f..000000000 --- a/src/main/java/de/dennisguse/opentracks/Constants.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2008 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; - -/** - * Common constants. - * - * @author Leif Hendrik Wilden - */ -public class Constants { - - /** - * Maximum number of waypoints that will be loaded at one time. - */ - public static final int MAX_LOADED_WAYPOINTS_POINTS = 10000; - - private Constants() { - } -} diff --git a/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java index db122a1f4..e890bbd84 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerDetailActivity.java @@ -25,13 +25,12 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.viewpager.widget.ViewPager; +import java.util.ArrayList; + import de.dennisguse.opentracks.content.ContentProviderUtils; import de.dennisguse.opentracks.content.Waypoint; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller; import de.dennisguse.opentracks.fragments.MarkerDetailFragment; -import de.dennisguse.opentracks.R; - -import java.util.ArrayList; /** * An activity to display marker detail info. @@ -41,6 +40,7 @@ import java.util.ArrayList; public class MarkerDetailActivity extends AbstractActivity implements DeleteMarkerCaller { public static final String EXTRA_MARKER_ID = "marker_id"; + private static final String TAG = MarkerDetailActivity.class.getSimpleName(); private ArrayList markerIds; @@ -108,7 +108,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark */ private class MarkerDetailPagerAdapter extends FragmentStatePagerAdapter { - public MarkerDetailPagerAdapter(FragmentManager fragmentManager) { + MarkerDetailPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); } diff --git a/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java index 2b5dcf1b2..371f3c4b7 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerEditActivity.java @@ -41,6 +41,7 @@ public class MarkerEditActivity extends AbstractActivity { public static final String EXTRA_TRACK_ID = "track_id"; public static final String EXTRA_MARKER_ID = "marker_id"; + private static final String TAG = MarkerEditActivity.class.getSimpleName(); private long trackId; private long markerId; @@ -127,8 +128,7 @@ public class MarkerEditActivity extends AbstractActivity { if (newMarker) { statisticsSection.setVisibility(View.GONE); waypointSection.setVisibility(View.VISIBLE); - int nextWaypointNumber = trackId == -1L ? -1 - : ContentProviderUtils.Factory.get(this).getNextWaypointNumber(trackId, WaypointType.WAYPOINT); + int nextWaypointNumber = trackId == -1L ? -1 : ContentProviderUtils.Factory.get(this).getNextWaypointNumber(trackId, WaypointType.WAYPOINT); if (nextWaypointNumber == -1) { nextWaypointNumber = 0; } diff --git a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java index a0f11f5ad..d20790663 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java @@ -65,8 +65,11 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY, WaypointsColumns.TYPE, WaypointsColumns.TIME, WaypointsColumns.PHOTOURL, WaypointsColumns.LATITUDE, WaypointsColumns.LONGITUDE}; + private ContentProviderUtils contentProviderUtils; + private SharedPreferences sharedPreferences; + private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT; /* diff --git a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java index e63ebe788..c15cebd1b 100644 --- a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java @@ -87,16 +87,25 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa private static final String PHOTO_URL_FIELD = "photoUrl"; private static final String MARKER_LATITUDE_FIELD = "latitude"; private static final String MARKER_LONGITUDE_FIELD = "longitude"; - private static final String TRACK_ID_FIELD = "trackId"; private static final String MARKER_ID_FIELD = "markerId"; + private ContentProviderUtils contentProviderUtils; + private SharedPreferences sharedPreferences; + private TrackRecordingServiceConnection trackRecordingServiceConnection; + private SearchEngine searchEngine; + private ArrayAdapter> arrayAdapter; + private boolean metricUnits = true; + private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + + private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT; + // Callback when an item is selected in the contextual action mode private ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() { @Override @@ -132,9 +141,8 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa return handleContextItem(itemId, positions); } }; - private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT; - private final OnSharedPreferenceChangeListener - sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { + + private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (key == null || key.equals(PreferencesUtils.getKey(SearchListActivity.this, R.string.stats_units_key))) { @@ -171,12 +179,11 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa @NonNull @Override public View getView(int position, View convertView, @NonNull android.view.ViewGroup parent) { - View view; + View view = convertView; if (convertView == null) { view = getLayoutInflater().inflate(R.layout.list_item, parent, false); - } else { - view = convertView; } + Map resultMap = getItem(position); boolean isRecording = (boolean) resultMap.get(IS_RECORDING_FIELD); boolean isPaused = (boolean) resultMap.get(IS_PAUSED_FIELD); @@ -207,13 +214,11 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa Map item = arrayAdapter.getItem(position); Long trackId = (Long) item.get(TRACK_ID_FIELD); Long markerId = (Long) item.get(MARKER_ID_FIELD); - Intent intent; + Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackDetailActivity.class); if (markerId != null) { - intent = IntentUtils.newIntent(SearchListActivity.this, TrackDetailActivity.class) - .putExtra(TrackDetailActivity.EXTRA_MARKER_ID, markerId); + intent = intent.putExtra(TrackDetailActivity.EXTRA_MARKER_ID, markerId); } else { - intent = IntentUtils.newIntent(SearchListActivity.this, TrackDetailActivity.class) - .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId); + intent = intent.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId); } startActivity(intent); } @@ -391,13 +396,11 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa //TODO Replace use of map, but rather provide Track or Waypoint directly. ArrayList> output = new ArrayList<>(scoredResults.size()); for (ScoredResult result : scoredResults) { - Map resultMap = new HashMap<>(); if (result.track != null) { - prepareTrackForDisplay(result.track, resultMap); + output.add(prepareTrackForDisplay(result.track)); } else { - prepareMarkerForDisplay(result.waypoint, resultMap); + output.add(prepareMarkerForDisplay(result.waypoint)); } - output.add(resultMap); } return output; } @@ -405,11 +408,12 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa /** * Prepares a marker for display by filling in a result map. * - * @param waypoint the marker - * @param resultMap the result map + * @param waypoint the marker + * @return the result map */ - @Deprecated - private void prepareMarkerForDisplay(Waypoint waypoint, Map resultMap) { + private Map prepareMarkerForDisplay(Waypoint waypoint) { + Map resultMap = new HashMap<>(); + //TODO: It may be more appropriate to obtain the track name as a join in the retrieval phase of the search. String trackName = null; long trackId = waypoint.getTrackId(); @@ -440,17 +444,20 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa resultMap.put(MARKER_LATITUDE_FIELD, waypoint.getLocation().getLatitude()); resultMap.put(MARKER_LONGITUDE_FIELD, waypoint.getLocation().getLongitude()); + + return resultMap; } /** * Prepares a track for display by filling in a result map. * - * @param track the track - * @param resultMap the result map + * @param track the track + * @return the result map */ - @Deprecated - private void prepareTrackForDisplay(Track track, Map resultMap) { - TripStatistics tripStatitics = track.getTripStatistics(); + private Map prepareTrackForDisplay(Track track) { + Map resultMap = new HashMap<>(); + + TripStatistics tripStatistics = track.getTripStatistics(); String icon = track.getIcon(); String category = icon != null && !icon.equals("") ? null : track.getCategory(); @@ -459,15 +466,17 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa resultMap.put(ICON_ID_FIELD, TrackIconUtils.getIconDrawable(icon)); resultMap.put(ICON_CONTENT_DESCRIPTION_ID_FIELD, R.string.image_track); resultMap.put(NAME_FIELD, track.getName()); - resultMap.put(TOTAL_TIME_FIELD, StringUtils.formatElapsedTime(tripStatitics.getTotalTime())); - resultMap.put(TOTAL_DISTANCE_FIELD, StringUtils.formatDistance(this, tripStatitics.getTotalDistance(), metricUnits)); + resultMap.put(TOTAL_TIME_FIELD, StringUtils.formatElapsedTime(tripStatistics.getTotalTime())); + resultMap.put(TOTAL_DISTANCE_FIELD, StringUtils.formatDistance(this, tripStatistics.getTotalDistance(), metricUnits)); resultMap.put(MARKER_COUNT_FIELD, contentProviderUtils.getWaypointCount(track.getId())); - resultMap.put(START_TIME_FIELD, tripStatitics.getStartTime()); + resultMap.put(START_TIME_FIELD, tripStatistics.getStartTime()); resultMap.put(CATEGORY_FIELD, category); resultMap.put(DESCRIPTION_FIELD, track.getDescription()); resultMap.put(PHOTO_URL_FIELD, null); resultMap.put(TRACK_ID_FIELD, track.getId()); resultMap.put(MARKER_ID_FIELD, null); + + return resultMap; } @Override diff --git a/src/main/java/de/dennisguse/opentracks/Startup.java b/src/main/java/de/dennisguse/opentracks/Startup.java index 58d67a367..5476f6d53 100644 --- a/src/main/java/de/dennisguse/opentracks/Startup.java +++ b/src/main/java/de/dennisguse/opentracks/Startup.java @@ -6,6 +6,12 @@ import android.util.Log; import de.dennisguse.opentracks.util.PreferencesUtils; +/** + * Code that is executed when the application starts. + *

    + * NOTE: How often actual application startup happens depends on the OS. + * Not every start of an activity will trigger this. + */ public class Startup extends Application { private final static String TAG = Startup.class.getSimpleName(); diff --git a/src/main/java/de/dennisguse/opentracks/TabsAdapter.java b/src/main/java/de/dennisguse/opentracks/TabsAdapter.java index 10c4e6859..e46ba7949 100644 --- a/src/main/java/de/dennisguse/opentracks/TabsAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/TabsAdapter.java @@ -97,9 +97,8 @@ public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabCh @Override public void onPageSelected(int position) { /* - * Unfortunately when TabHost changes the current tab, it kindly also takes - * care of putting focus on it when not in touch mode. The jerk. This hack - * tries to prevent this from pulling focus out of our ViewPager. + * Unfortunately when TabHost changes the current tab, it kindly also takes care of putting focus on it when not in touch mode. + * The jerk. This hack tries to prevent this from pulling focus out of our ViewPager. */ TabWidget tabWidget = tabHost.getTabWidget(); int oldFocusability = tabWidget.getDescendantFocusability(); @@ -122,15 +121,14 @@ public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabCh private final Class clss; private final Bundle bundle; - public TabInfo(Class clss, Bundle bunlde) { + TabInfo(Class clss, Bundle bundle) { this.clss = clss; - this.bundle = bunlde; + this.bundle = bundle; } } /** - * A dummy {@link TabContentFactory} that creates an empty view to satisfy the - * {@link TabHost} API. + * A dummy {@link TabContentFactory} that creates an empty view to satisfy the {@link TabHost} API. * * @author Jimmy Shih */ @@ -138,7 +136,7 @@ public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabCh private final Context context; - public DummyTabFactory(Context context) { + DummyTabFactory(Context context) { this.context = context; } diff --git a/src/main/java/de/dennisguse/opentracks/TrackController.java b/src/main/java/de/dennisguse/opentracks/TrackController.java index c1e187e74..bfa404e13 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackController.java +++ b/src/main/java/de/dennisguse/opentracks/TrackController.java @@ -27,7 +27,6 @@ import de.dennisguse.opentracks.services.ITrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.UnitConversions; -import de.dennisguse.opentracks.R; /** * Track controller for record, pause, resume, and stop. @@ -67,7 +66,7 @@ public class TrackController { } }; - public TrackController(Activity activity, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, OnClickListener recordListener, OnClickListener stopListener) { + TrackController(Activity activity, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, OnClickListener recordListener, OnClickListener stopListener) { this.activity = activity; this.trackRecordingServiceConnection = trackRecordingServiceConnection; this.alwaysShow = alwaysShow; @@ -121,21 +120,21 @@ public class TrackController { } } - public void onResume(boolean recording, boolean paused) { + void onResume(boolean recording, boolean paused) { isResumed = true; update(recording, paused); } - public void onPause() { + void onPause() { isResumed = false; handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable); } - public void hide() { + void hide() { containerView.setVisibility(View.GONE); } - public void show() { + void show() { containerView.setVisibility(View.VISIBLE); } diff --git a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java index 260cd5c56..a8c1d3fcf 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java @@ -71,7 +71,9 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA public static final String EXTRA_TRACK_ID = "track_id"; public static final String EXTRA_MARKER_ID = "marker_id"; + private static final String TAG = TrackDetailActivity.class.getSimpleName(); + private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key"; private static final String PHOTO_URI_KEY = "photo_uri_key"; private static final String HAS_PHOTO_KEY = "has_photo_key"; @@ -101,8 +103,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA private final Runnable bindChangedCallback = new Runnable() { @Override public void run() { - // After binding changes (is available), update the total time in - // trackController. + // After binding changes (is available), update the total time in trackController. runOnUiThread(new Runnable() { @Override public void run() { @@ -153,12 +154,14 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA }); } }; + private MenuItem insertMarkerMenuItem; private MenuItem insertPhotoMenuItem; private MenuItem markerListMenuItem; private MenuItem shareMenuItem; private MenuItem voiceFrequencyMenuItem; private MenuItem splitFrequencyMenuItem; + private final OnClickListener recordListener = new OnClickListener() { @Override public void onClick(View v) { diff --git a/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java b/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java index c8b84a8ad..48e560d7b 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackEditActivity.java @@ -37,8 +37,7 @@ import de.dennisguse.opentracks.util.TrackRecordingServiceConnectionUtils; import de.dennisguse.opentracks.util.TrackUtils; /** - * An activity that let's the user see and edit the user editable track meta - * data such as track name, activity type, and track description. + * An activity that let's the user see and edit the user editable track meta data such as track name, activity type, and track description. * * @author Leif Hendrik Wilden */ @@ -48,6 +47,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit public static final String EXTRA_NEW_TRACK = "new_track"; private static final String TAG = TrackEditActivity.class.getSimpleName(); + private static final String ICON_VALUE_KEY = "icon_value_key"; private TrackRecordingServiceConnection trackRecordingServiceConnection; @@ -55,7 +55,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit private Track track; private String iconValue; - private EditText name; + private EditText nameEditText; private AutoCompleteTextView activityType; private Spinner activityTypeIcon; private EditText description; @@ -80,14 +80,13 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit return; } - name = findViewById(R.id.track_edit_name); - name.setText(track.getName()); + nameEditText = findViewById(R.id.track_edit_name); + nameEditText.setText(track.getName()); activityType = findViewById(R.id.track_edit_activity_type); activityType.setText(track.getCategory()); - ArrayAdapter adapter = ArrayAdapter.createFromResource( - this, R.array.activity_types, android.R.layout.simple_dropdown_item_1line); + ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.activity_types, android.R.layout.simple_dropdown_item_1line); activityType.setAdapter(adapter); activityType.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -139,11 +138,11 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit description = findViewById(R.id.track_edit_description); description.setText(track.getDescription()); - Button save = findViewById(R.id.track_edit_save); - save.setOnClickListener(new View.OnClickListener() { + Button saveButton = findViewById(R.id.track_edit_save); + saveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - TrackUtils.updateTrack(TrackEditActivity.this, track, name.getText().toString(), + TrackUtils.updateTrack(TrackEditActivity.this, track, nameEditText.getText().toString(), activityType.getText().toString(), description.getText().toString(), contentProviderUtils); finish(); diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 9b377ebab..3a7438cf8 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -76,9 +76,11 @@ import de.dennisguse.opentracks.util.TrackUtils; public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller { private static final String TAG = TrackListActivity.class.getSimpleName(); + private static final String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.NAME, TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME, TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON}; + // The following are set in onCreate private ContentProviderUtils contentProviderUtils; private SharedPreferences sharedPreferences; @@ -86,6 +88,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe private TrackController trackController; private ListView listView; private ResourceCursorAdapter resourceCursorAdapter; + private final LoaderCallbacks loaderCallbacks = new LoaderCallbacks() { @Override public Loader onCreateLoader(int arg0, Bundle arg1) { @@ -103,9 +106,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe resourceCursorAdapter.swapCursor(null); } }; + // Preferences private boolean metricUnits = true; private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + // Callback when an item is selected in the contextual action mode private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() { @@ -126,7 +131,9 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe return handleContextItem(itemId, ids); } }; + private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT; + /* * Note that sharedPreferenceChangeListener cannot be an anonymous inner class. * Anonymous inner class will get garbage collected. @@ -165,11 +172,13 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe } } }; + // Menu items private MenuItem searchMenuItem; private MenuItem startGpsMenuItem; private MenuItem aggregatedStatisticsMenuItem; private MenuItem deleteAllMenuItem; + private final OnClickListener stopListener = new OnClickListener() { @Override public void onClick(View v) { @@ -178,15 +187,17 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe TrackListActivity.this, trackRecordingServiceConnection, true); } }; + private boolean startGps = false; // true to start gps + private boolean startNewRecording = false; // true to start a new recording + // Callback when the trackRecordingServiceConnection binding changes. private final Runnable bindChangedCallback = new Runnable() { @Override public void run() { /* - * After binding changes (e.g., becomes available), update the total time - * in trackController. + * After binding changes (e.g., becomes available), update the total time in trackController. */ runOnUiThread(new Runnable() { @Override @@ -212,8 +223,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe Intent intent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class) .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId); startActivity(intent); - Toast.makeText( - TrackListActivity.this, R.string.track_list_record_success, Toast.LENGTH_SHORT) + Toast.makeText(TrackListActivity.this, R.string.track_list_record_success, Toast.LENGTH_SHORT) .show(); } if (startGps) { @@ -222,6 +232,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe } } }; + private final OnClickListener recordListener = new OnClickListener() { public void onClick(View v) { if (recordingTrackId == PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { @@ -255,14 +266,17 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe trackController = new TrackController(this, trackRecordingServiceConnection, true, recordListener, stopListener); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); + // Show trackController when search dialog is dismissed SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE); - searchManager.setOnDismissListener(new SearchManager.OnDismissListener() { - @Override - public void onDismiss() { - trackController.show(); - } - }); + if (searchManager != null) { + searchManager.setOnDismissListener(new SearchManager.OnDismissListener() { + @Override + public void onDismiss() { + trackController.show(); + } + }); + } listView = findViewById(R.id.track_list); listView.setEmptyView(findViewById(R.id.track_list_empty_view)); @@ -274,6 +288,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe startActivity(newIntent); } }); + resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) { @Override public void bindView(View view, Context context, Cursor cursor) { @@ -395,7 +410,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe switch (item.getItemId()) { case R.id.track_list_start_gps: LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + if (locationManager != null && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); } else { diff --git a/src/main/java/de/dennisguse/opentracks/android/ContentResolverWrapper.java b/src/main/java/de/dennisguse/opentracks/android/ContentResolverWrapper.java index cdfe66ac6..3a71bf0bc 100644 --- a/src/main/java/de/dennisguse/opentracks/android/ContentResolverWrapper.java +++ b/src/main/java/de/dennisguse/opentracks/android/ContentResolverWrapper.java @@ -8,6 +8,9 @@ import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +/** + * Wraps a {@link ContentResolver} and provides access as {@link IContentResolver}. + */ public class ContentResolverWrapper implements IContentResolver { private ContentResolver contentResolver; diff --git a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtils.java index e5ace81e6..778c1a142 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtils.java @@ -35,6 +35,11 @@ import de.dennisguse.opentracks.content.Waypoint.WaypointType; */ public interface ContentProviderUtils { + /** + * Maximum number of waypoints that will be loaded at one time. + */ + int MAX_LOADED_WAYPOINTS_POINTS = 10000; + /** * The authority (the first part of the URI) for the app's content provider. */ @@ -56,7 +61,8 @@ public interface ContentProviderUtils { }; /** - * Clears a track. Removes waypoints and trackpoints. Only keeps the track id. + * Clears a track: removes waypoints and trackpoints. + * Only keeps the track id. * * @param trackId the track id */ @@ -82,20 +88,19 @@ public interface ContentProviderUtils { void deleteTrack(Context context, long trackId); /** - * Gets all the tracks. If no track exists, an empty list is returned. - *

    - * Note that the returned tracks do not have any track points attached. + * Gets all the tracks. + * If no track exists, an empty list is returned. + * NOTE: the returned tracks do not have any track points attached. */ List getAllTracks(); /** - * Gets the last track. Returns null if doesn't exist. + * Gets the last track or null. */ Track getLastTrack(); /** - * Gets a track by a track id. Returns null if not found. - *

    + * Gets a track by a track id or null * Note that the returned track doesn't have any track points attached. * * @param trackId the track id. @@ -103,8 +108,8 @@ public interface ContentProviderUtils { Track getTrack(long trackId); /** - * Gets a track cursor. The caller owns the returned cursor and is responsible - * for closing it. + * Gets a track cursor. + * The caller owns the returned cursor and is responsible for closing it. * * @param selection the selection. Can be null * @param selectionArgs the selection arguments. Can be null @@ -114,8 +119,7 @@ public interface ContentProviderUtils { /** * Inserts a track. - *

    - * Note: This doesn't insert any track points. + * NOTE: This doesn't insert any track points. * * @param track the track * @return the content provider URI of the inserted track. @@ -124,8 +128,7 @@ public interface ContentProviderUtils { /** * Updates a track. - *

    - * Note: This doesn't update any track points. + * NOTE: This doesn't update any track points. * * @param track the track */ @@ -139,19 +142,19 @@ public interface ContentProviderUtils { Waypoint createWaypoint(Cursor cursor); /** - * Deletes a waypoint. If deleting a statistics waypoint, this will also - * correct the next statistics waypoint after the deleted one to reflect the - * deletion. The generator is used to update the next statistics waypoint. + * Deletes a waypoint. + * If deleting a statistics waypoint, this will also correct the next statistics waypoint after the deleted one to reflect the 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 */ void deleteWaypoint(Context context, long waypointId, DescriptionGenerator descriptionGenerator); /** - * Gets the first waypoint id for a track. The first waypoint is special as it - * contains the stats for the track. Returns -1L if it doesn't exist. + * Gets the first waypoint id for a track. + * The first waypoint is special as it contains the stats for the track. + * Returns -1L if it doesn't exist. * * @param trackId the track id */ @@ -166,8 +169,8 @@ public interface ContentProviderUtils { 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 @@ -175,15 +178,16 @@ public interface ContentProviderUtils { int getNextWaypointNumber(long trackId, WaypointType waypointType); /** - * Gets a waypoint from a waypoint id. Returns null if not found. + * Gets a waypoint from a waypoint id. + * Returns null if not found. * * @param waypointId the waypoint id */ Waypoint getWaypoint(long waypointId); /** - * Gets a waypoint cursor. The caller owns the returned cursor and is - * responsible for closing it. + * Gets a waypoint cursor. + * he caller owns the returned cursor and is responsible for closing it. * * @param selection the selection. Can be null * @param selectionArgs the selection arguments. Can be null @@ -194,13 +198,12 @@ public interface ContentProviderUtils { Cursor getWaypointCursor(String selection, String[] selectionArgs, String sortOrder, int maxWaypoints); /** - * Gets a waypoint cursor for a track. The caller owns the returned cursor and - * is responsible for closing it. + * Gets a waypoint cursor for a track. + * The caller owns the returned cursor and is responsible for closing it. * * @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 */ Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints); @@ -220,7 +223,8 @@ public interface ContentProviderUtils { Uri insertWaypoint(Waypoint waypoint); /** - * Updates a waypoint. Returns true if successful. + * Updates a waypoint. + * Returns true if successful. * * @param waypoint the waypoint */ @@ -245,14 +249,16 @@ public interface ContentProviderUtils { Location createTrackPoint(Cursor cursor); /** - * Gets the first location id for a track. Returns -1L if it doesn't exist. + * Gets the first location id for a track. + * Returns -1L if it doesn't exist. * * @param trackId the track id */ long getFirstTrackPointId(long trackId); /** - * Gets the last location id for a track. Returns -1L if it doesn't exist. + * Gets the last location id for a track. + * Returns -1L if it doesn't exist. * * @param trackId the track id */ @@ -268,28 +274,23 @@ public interface ContentProviderUtils { long getTrackPointId(long trackId, Location location); /** - * 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 */ Location getFirstValidTrackPoint(long trackId); /** - * Gets the last valid location for a track. Returns null if it doesn't exist. + * Gets the last valid location for a track. + * Returns null if it doesn't exist. * * @param trackId the track id */ Location getLastValidTrackPoint(long trackId); /** - * Gets the last valid location. - */ - Location getLastValidTrackPoint(); - - /** - * Creates a location cursor. The caller owns the returned cursor and is - * responsible for closing it. + * Creates a location cursor. The caller owns the returned cursor and is responsible for closing it. * * @param trackId the track id * @param startTrackPointId the starting track point id. -1L to ignore @@ -299,20 +300,15 @@ public interface ContentProviderUtils { Cursor getTrackPointCursor(long trackId, long startTrackPointId, int maxLocations, boolean descending); /** - * Creates a new read-only iterator over a given track's points. It provides a - * lightweight way of iterating over long tracks without failing due to the - * underlying cursor limitations. Since it's a read-only iterator, - * {@link Iterator#remove()} always throws - * {@link UnsupportedOperationException}. Each call to - * {@link LocationIterator#next()} may advance to the next DB record, and if - * so, the iterator calls {@link LocationFactory#createLocation()} and - * populates it with information retrieved from the record. When done with - * iteration, {@link LocationIterator#close()} must be called. + * Creates a new read-only iterator over a given track's points. + * It provides a lightweight way of iterating over long tracks without failing due to the underlying cursor limitations. + * Since it's a read-only iterator, {@link Iterator#remove()} always throws {@link UnsupportedOperationException}. + * Each call to {@link LocationIterator#next()} may advance to the next DB record, and if so, the iterator calls {@link LocationFactory#createLocation()} and populates it with information retrieved from the record. + * When done with iteration, {@link LocationIterator#close()} must be called. * * @param trackId the track id * @param startTrackPointId the starting track point id. -1L to ignore - * @param descending true to sort the result in descending order (latest - * location first) + * @param descending true to sort the result in descending order (latest location first) * @param locationFactory the location factory */ LocationIterator getTrackPointLocationIterator(long trackId, long startTrackPointId, boolean descending, LocationFactory locationFactory); @@ -327,10 +323,9 @@ public interface ContentProviderUtils { Uri insertTrackPoint(Location location, long trackId); /** - * A lightweight wrapper around the original {@link Cursor} with a method to - * clean up. + * A lightweight wrapper around the original {@link Cursor} with a method to clean up. */ - interface LocationIterator extends Iterator { + interface LocationIterator extends Iterator, AutoCloseable { /** * Gets the most recently retrieved track point id by {@link #next()}. @@ -349,8 +344,8 @@ public interface ContentProviderUtils { interface LocationFactory { /** - * Creates a new {@link Location}. An implementation can create new - * instances or reuse existing instances for optimization. + * Creates a new {@link Location}. + * An implementation can create new instances or reuse existing instances for optimization. */ Location createLocation(); } @@ -358,6 +353,8 @@ public interface ContentProviderUtils { /** * A factory which can produce instances of {@link ContentProviderUtils}, and can be overridden for testing. */ + //TODO Is this still used? From a quick glance, it doesn't looks like it; probably a left over from testing. + @Deprecated class Factory { private static Factory instance = new Factory(); @@ -379,8 +376,8 @@ public interface ContentProviderUtils { } /** - * Overrides the factory instance for testing. Don't forget to set it back - * to the original value after testing. + * Overrides the factory instance for testing. + * Don't forget to set it back to the original value after testing. * * @param factory the factory */ @@ -394,7 +391,7 @@ public interface ContentProviderUtils { * * @param context the context */ - protected ContentProviderUtils newForContext(Context context) { + private ContentProviderUtils newForContext(Context context) { return new ContentProviderUtilsImpl(context.getContentResolver()); } } diff --git a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java index f0536470e..a8c18a37d 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java +++ b/src/main/java/de/dennisguse/opentracks/content/ContentProviderUtilsImpl.java @@ -842,14 +842,6 @@ public class ContentProviderUtilsImpl implements ContentProviderUtils { return findTrackPointBy(selection, selectionArgs); } - @Override - public Location getLastValidTrackPoint() { - String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + ") from " - + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.LATITUDE + "<=" - + MAX_LATITUDE + ")"; - return findTrackPointBy(selection, null); - } - @Override public Cursor getTrackPointCursor(long trackId, long startTrackPointId, int maxLocations, boolean descending) { if (trackId < 0) { diff --git a/src/main/java/de/dennisguse/opentracks/content/CustomContentProvider.java b/src/main/java/de/dennisguse/opentracks/content/CustomContentProvider.java index 76148eee9..e670b990d 100644 --- a/src/main/java/de/dennisguse/opentracks/content/CustomContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/CustomContentProvider.java @@ -35,8 +35,7 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; /** - * A {@link ContentProvider} that handles access to track points, tracks, and - * waypoints tables. + * A {@link ContentProvider} that handles access to track points, tracks, and waypoints tables. * * @author Leif Hendrik Wilden */ @@ -44,10 +43,14 @@ public abstract class CustomContentProvider extends ContentProvider { @VisibleForTesting static final int DATABASE_VERSION = 23; + @VisibleForTesting static final String DATABASE_NAME = "database.db"; + private static final String TAG = CustomContentProvider.class.getSimpleName(); + private final UriMatcher uriMatcher; + private SQLiteDatabase db; public CustomContentProvider() { diff --git a/src/main/java/de/dennisguse/opentracks/content/DataSource.java b/src/main/java/de/dennisguse/opentracks/content/DataSource.java index d10d17c09..ac1ec0154 100644 --- a/src/main/java/de/dennisguse/opentracks/content/DataSource.java +++ b/src/main/java/de/dennisguse/opentracks/content/DataSource.java @@ -30,12 +30,12 @@ import de.dennisguse.opentracks.util.PreferencesUtils; * * @author Rodrigo Damazio */ -public class DataSource { +class DataSource { private final ContentResolver contentResolver; private final SharedPreferences sharedPreferences; - public DataSource(Context context) { + DataSource(Context context) { contentResolver = context.getContentResolver(); sharedPreferences = PreferencesUtils.getSharedPreferences(context); } @@ -46,7 +46,7 @@ public class DataSource { * @param uri the uri * @param observer the observer */ - public void registerContentObserver(Uri uri, ContentObserver observer) { + void registerContentObserver(Uri uri, ContentObserver observer) { contentResolver.registerContentObserver(uri, false, observer); } @@ -55,7 +55,7 @@ public class DataSource { * * @param observer the observer */ - public void unregisterContentObserver(ContentObserver observer) { + void unregisterContentObserver(ContentObserver observer) { contentResolver.unregisterContentObserver(observer); } @@ -64,7 +64,7 @@ public class DataSource { * * @param listener the listener */ - public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { + void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { sharedPreferences.registerOnSharedPreferenceChangeListener(listener); } @@ -73,8 +73,7 @@ public class DataSource { * * @param listener the listener */ - public void unregisterOnSharedPreferenceChangeListener( - OnSharedPreferenceChangeListener listener) { + void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener); } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/content/DataSourceManager.java b/src/main/java/de/dennisguse/opentracks/content/DataSourceManager.java index d798e4e36..d6ef40a6b 100644 --- a/src/main/java/de/dennisguse/opentracks/content/DataSourceManager.java +++ b/src/main/java/de/dennisguse/opentracks/content/DataSourceManager.java @@ -26,17 +26,19 @@ import java.util.EnumSet; import java.util.Set; /** - * Data source manager. Creates observers/listeners and manages their - * registration with {@link DataSource}. The observers/listeners calls - * {@link DataSourceListener} when data changes. + * Creates observers/listeners and manages their registration with {@link DataSource}. + * The observers/listeners calls {@link DataSourceListener} when data changes. * * @author Rodrigo Damazio */ -public class DataSourceManager { +class DataSourceManager { private static final String TAG = DataSourceManager.class.getSimpleName(); + private final DataSource dataSource; + private final DataSourceListener dataSourceListener; + // Registered listeners private final Set registeredListeners = EnumSet.noneOf(TrackDataType.class); private final Handler handler; @@ -45,7 +47,7 @@ public class DataSourceManager { private final TrackPointsTableObserver trackPointsTableObserver; private final PreferenceListener preferenceListener; - public DataSourceManager(DataSource dataSource, DataSourceListener dataSourceListener) { + DataSourceManager(DataSource dataSource, DataSourceListener dataSourceListener) { this.dataSource = dataSource; this.dataSourceListener = dataSourceListener; @@ -61,7 +63,7 @@ public class DataSourceManager { * * @param listeners the listeners */ - public void updateListeners(EnumSet listeners) { + void updateListeners(EnumSet listeners) { EnumSet neededListeners = EnumSet.copyOf(listeners); /* @@ -156,7 +158,7 @@ public class DataSourceManager { /** * Unregisters all listeners with data source. */ - public void unregisterAllListeners() { + void unregisterAllListeners() { for (TrackDataType trackDataType : TrackDataType.values()) { unregisterListener(trackDataType); } @@ -169,7 +171,7 @@ public class DataSourceManager { */ private class TracksTableObserver extends ContentObserver { - public TracksTableObserver() { + TracksTableObserver() { super(handler); } @@ -186,7 +188,7 @@ public class DataSourceManager { */ private class WaypointsTableObserver extends ContentObserver { - public WaypointsTableObserver() { + WaypointsTableObserver() { super(handler); } @@ -203,7 +205,7 @@ public class DataSourceManager { */ private class TrackPointsTableObserver extends ContentObserver { - public TrackPointsTableObserver() { + TrackPointsTableObserver() { super(handler); } diff --git a/src/main/java/de/dennisguse/opentracks/content/DescriptionGenerator.java b/src/main/java/de/dennisguse/opentracks/content/DescriptionGenerator.java index ee046ee01..14b673375 100644 --- a/src/main/java/de/dennisguse/opentracks/content/DescriptionGenerator.java +++ b/src/main/java/de/dennisguse/opentracks/content/DescriptionGenerator.java @@ -18,8 +18,7 @@ package de.dennisguse.opentracks.content; import de.dennisguse.opentracks.stats.TripStatistics; /** - * An interface for an object that can generate descriptions of track and - * waypoint. + * An interface for an object that can generate descriptions of track and waypoint. * * @author Sandor Dornbush */ diff --git a/src/main/java/de/dennisguse/opentracks/content/DescriptionGeneratorImpl.java b/src/main/java/de/dennisguse/opentracks/content/DescriptionGeneratorImpl.java index 95cc1f924..7d9abe1fc 100644 --- a/src/main/java/de/dennisguse/opentracks/content/DescriptionGeneratorImpl.java +++ b/src/main/java/de/dennisguse/opentracks/content/DescriptionGeneratorImpl.java @@ -115,8 +115,7 @@ public class DescriptionGeneratorImpl implements DescriptionGenerator { writeSpeed(stats.getMaxSpeed(), builder, R.string.description_max_speed, lineBreak); // Average pace - writePace( - stats.getAverageSpeed(), builder, R.string.description_average_pace_in_minute, lineBreak); + writePace(stats.getAverageSpeed(), builder, R.string.description_average_pace_in_minute, lineBreak); // Average moving pace writePace(stats.getAverageMovingSpeed(), builder, @@ -132,8 +131,7 @@ public class DescriptionGeneratorImpl implements DescriptionGenerator { writeElevation(stats.getMinElevation(), builder, R.string.description_min_elevation, lineBreak); // Elevation gain - writeElevation( - stats.getTotalElevationGain(), builder, R.string.description_elevation_gain, lineBreak); + writeElevation(stats.getTotalElevationGain(), builder, R.string.description_elevation_gain, lineBreak); // Max grade writeGrade(stats.getMaxGrade(), builder, R.string.description_max_grade, lineBreak); diff --git a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java index 24771de7d..5a5f0d4cb 100644 --- a/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java +++ b/src/main/java/de/dennisguse/opentracks/content/SearchEngine.java @@ -23,6 +23,7 @@ import androidx.annotation.NonNull; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; +import java.util.List; import java.util.Locale; import java.util.SortedSet; import java.util.TreeSet; @@ -97,34 +98,35 @@ public class SearchEngine { /** * Oldest timestamp for which we rank based on time (2000-01-01 00:00:00.000) */ - private static final long OLDEST_ALLOWED_TIMESTAMP = 946692000000L; + public static final long OLDEST_ALLOWED_TIMESTAMP = 946692000000L; + /** * Comparador for scored results. */ - private static final Comparator SCORED_RESULT_COMPARATOR = - new Comparator() { - @Override - public int compare(ScoredResult r1, ScoredResult r2) { - // Score ordering. - int scoreDiff = Double.compare(r2.score, r1.score); - if (scoreDiff != 0) { - return scoreDiff; - } + private static final Comparator SCORED_RESULT_COMPARATOR = new Comparator() { + @Override + public int compare(ScoredResult r1, ScoredResult r2) { + // Score ordering. + int scoreDiff = Double.compare(r2.score, r1.score); + if (scoreDiff != 0) { + return scoreDiff; + } - // Make tracks come before waypoints. - if (r1.waypoint != null && r2.track != null) { - return 1; - } else if (r1.track != null && r2.waypoint != null) { - return -1; - } + // Make tracks come before waypoints. + if (r1.waypoint != null && r2.track != null) { + return 1; + } else if (r1.track != null && r2.waypoint != null) { + return -1; + } + + // Finally, use arbitrary ordering, by ID. + long id1 = r1.track != null ? r1.track.getId() : r1.waypoint.getId(); + long id2 = r2.track != null ? r2.track.getId() : r2.waypoint.getId(); + long idDiff = id2 - id1; + return Long.signum(idDiff); + } + }; - // Finally, use arbitrary ordering, by ID. - long id1 = r1.track != null ? r1.track.getId() : r1.waypoint.getId(); - long id2 = r2.track != null ? r2.track.getId() : r2.waypoint.getId(); - long idDiff = id2 - id1; - return Long.signum(idDiff); - } - }; private final ContentProviderUtils providerUtils; public SearchEngine(ContentProviderUtils providerUtils) { @@ -134,6 +136,7 @@ public class SearchEngine { /** * Squashes a number by calculating 1 / log (1 + x). */ + //TODO Why is this done? private static double squash(double x) { return 1.0 / Math.log1p(x); } @@ -145,15 +148,10 @@ public class SearchEngine { * @return a set of results, sorted according to their score */ public SortedSet search(SearchQuery query) { - ArrayList tracks = new ArrayList<>(); - ArrayList waypoints = new ArrayList<>(); TreeSet scoredResults = new TreeSet<>(SCORED_RESULT_COMPARATOR); - retrieveTracks(query, tracks); - retrieveWaypoints(query, waypoints); - - scoreTrackResults(tracks, query, scoredResults); - scoreWaypointResults(waypoints, query, scoredResults); + scoreTrackResults(retrieveTracks(query), query, scoredResults); + scoreWaypointResults(retrieveWaypoints(query), query, scoredResults); return scoredResults; } @@ -161,18 +159,19 @@ public class SearchEngine { /** * Retrieves tracks matching the given query from the database. * - * @param query the query to retrieve for - * @param tracks list to fill with the resulting tracks + * @param query the query to retrieve for */ - private void retrieveTracks(SearchQuery query, ArrayList tracks) { + private List retrieveTracks(SearchQuery query) { + ArrayList tracks = new ArrayList<>(); + String queryLikeSelection = "%" + query.textQuery + "%"; String[] trackSelectionArgs = new String[]{ queryLikeSelection, queryLikeSelection, - queryLikeSelection}; + queryLikeSelection + }; - try (Cursor cursor = providerUtils.getTrackCursor( - TRACK_SELECTION_QUERY, trackSelectionArgs, TRACK_SELECTION_ORDER)) { + try (Cursor cursor = providerUtils.getTrackCursor(TRACK_SELECTION_QUERY, trackSelectionArgs, TRACK_SELECTION_ORDER)) { if (cursor != null) { tracks.ensureCapacity(cursor.getCount()); while (cursor.moveToNext()) { @@ -180,22 +179,26 @@ public class SearchEngine { } } } + + return tracks; } /** * Retrieves waypoints matching the given query from the database. * - * @param query the query to retrieve for - * @param waypoints list to fill with the resulting waypoints + * @param query the query to retrieve for */ - private void retrieveWaypoints(SearchQuery query, ArrayList waypoints) { + private List retrieveWaypoints(SearchQuery query) { + ArrayList waypoints = new ArrayList<>(); + String queryLikeSelection2 = "%" + query.textQuery + "%"; String[] waypointSelectionArgs = new String[]{ queryLikeSelection2, queryLikeSelection2, - queryLikeSelection2}; - try (Cursor cursor = providerUtils.getWaypointCursor(WAYPOINT_SELECTION_QUERY, waypointSelectionArgs, - WAYPOINT_SELECTION_ORDER, MAX_SCORED_WAYPOINTS)) { + queryLikeSelection2 + }; + + try (Cursor cursor = providerUtils.getWaypointCursor(WAYPOINT_SELECTION_QUERY, waypointSelectionArgs, WAYPOINT_SELECTION_ORDER, MAX_SCORED_WAYPOINTS)) { if (cursor != null) { waypoints.ensureCapacity(cursor.getCount()); while (cursor.moveToNext()) { @@ -206,6 +209,8 @@ public class SearchEngine { } } } + + return waypoints; } /** @@ -238,7 +243,6 @@ public class SearchEngine { score *= getTitleBoost(query, track.getName(), track.getDescription(), track.getCategory()); TripStatistics statistics = track.getTripStatistics(); - // TODO: Also boost for proximity to the currently-centered position on the map. score *= getDistanceBoost(query, statistics.getMeanLatitude(), statistics.getMeanLongitude()); long meanTimestamp = (statistics.getStartTime() + statistics.getStopTime()) / 2L; @@ -281,7 +285,6 @@ public class SearchEngine { Location location = waypoint.getLocation(); score *= getTitleBoost(query, waypoint.getName(), waypoint.getDescription(), waypoint.getCategory()); - // TODO: Also boost for proximity to the currently-centered position on the map. score *= getDistanceBoost(query, location.getLatitude(), location.getLongitude()); score *= getTimeBoost(query, location.getTime()); @@ -302,8 +305,7 @@ public class SearchEngine { * @param category the category of the track or waypoint * @return the total boost to be applied to the result */ - private double getTitleBoost(SearchQuery query, - String name, String description, String category) { + private double getTitleBoost(SearchQuery query, String name, String description, String category) { // Title boost: track name > description > category. double boost = 1.0; if (name.toLowerCase(Locale.getDefault()).contains(query.textQuery)) { @@ -332,8 +334,7 @@ public class SearchEngine { } // Score recent tracks higher. - long timeAgoHours = (long) ((query.currentTimestamp - timestamp) * UnitConversions.MS_TO_S - * UnitConversions.S_TO_MIN * UnitConversions.MIN_TO_HR); + long timeAgoHours = (long) ((query.currentTimestamp - timestamp) * UnitConversions.MS_TO_S * UnitConversions.S_TO_MIN * UnitConversions.MIN_TO_HR); if (timeAgoHours > 0L) { return squash(timeAgoHours); } else { @@ -364,6 +365,7 @@ public class SearchEngine { // Score tracks close to the current location higher. double distanceKm = distanceResults[0] * UnitConversions.M_TO_KM; + if (distanceKm > 0.0) { // Use the inverse of the amortized distance. return squash(distanceKm); @@ -377,13 +379,12 @@ public class SearchEngine { * Description of a search query, along with all contextual data needed to execute it. */ public static class SearchQuery { - public final String textQuery; - public final Location currentLocation; - public final long currentTrackId; - public final long currentTimestamp; + final String textQuery; + final Location currentLocation; + final long currentTrackId; + final long currentTimestamp; - public SearchQuery(String textQuery, Location currentLocation, long currentTrackId, - long currentTimestamp) { + public SearchQuery(String textQuery, Location currentLocation, long currentTrackId, long currentTimestamp) { this.textQuery = textQuery.toLowerCase(Locale.getDefault()); this.currentLocation = currentLocation; this.currentTrackId = currentTrackId; @@ -397,7 +398,7 @@ public class SearchEngine { public static class ScoredResult { public final Track track; public final Waypoint waypoint; - public final double score; + final double score; ScoredResult(Track track, double score) { this.track = track; diff --git a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java index acd9ec3ed..7b470e1fd 100644 --- a/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java +++ b/src/main/java/de/dennisguse/opentracks/content/ShareContentProvider.java @@ -27,9 +27,9 @@ import de.dennisguse.opentracks.io.file.exporter.TrackExporter; /** * A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files. * The actual content of the virtual files is generated by using the functionality defined in {@link CustomContentProvider}. - *

    + * * Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}. - *

    + * * Explanation: * Although a request is handled by a {@link android.content.ContentProvider} (with temporarily granted permission), Android's security infrastructure prevents forwarding queries to non-exported {@link android.content.ContentProvider}. * Thus, if {@link ShareContentProvider} and {@link CustomContentProvider} would be two different instances, the data would not be accessible to external apps. diff --git a/src/main/java/de/dennisguse/opentracks/content/Track.java b/src/main/java/de/dennisguse/opentracks/content/Track.java index 7dd5e7d47..db449fc64 100644 --- a/src/main/java/de/dennisguse/opentracks/content/Track.java +++ b/src/main/java/de/dennisguse/opentracks/content/Track.java @@ -20,9 +20,10 @@ import android.location.Location; import android.os.Parcel; import android.os.Parcelable; -import de.dennisguse.opentracks.stats.TripStatistics; - import java.util.ArrayList; +import java.util.List; + +import de.dennisguse.opentracks.stats.TripStatistics; /** * A track. @@ -43,22 +44,26 @@ public class Track implements Parcelable { return new Track[size]; } }; + private long id = -1L; private String name = ""; private String description = ""; private String category = ""; private long startId = -1L; private long stopId = -1L; + /* - * The number of location points (present even if the points themselves are - * not loaded) + * The number of location points (present even if the points themselves are not loaded) */ private int numberOfPoints = 0; private String icon = ""; + + @Deprecated //TODO Is this still used or a left over from Google Drive integration? private long modifiedTime = -1L; private TripStatistics tripStatistics = new TripStatistics(); + // Location points (which may not have been loaded) - private ArrayList locations = new ArrayList<>(); + private List locations = new ArrayList<>(); public Track() { } @@ -190,7 +195,7 @@ public class Track implements Parcelable { locations.add(location); } - public ArrayList getLocations() { + public List getLocations() { return locations; } diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java index 5fc581466..3806bf456 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataHub.java @@ -35,24 +35,25 @@ import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.PreferencesUtils; /** - * Track data hub. Receives data from {@link DataSource} and distributes it to - * {@link TrackDataListener} after some processing. + * Track data hub. Receives data from {@link DataSource} and distributes it to {@link TrackDataListener} after some processing. * * @author Rodrigo Damazio */ public class TrackDataHub implements DataSourceListener { /** - * Target number of track points displayed by the map overlay. We may display - * more than this number of points. + * Target number of track points displayed by the map overlay. + * We may display more than this number of points. */ - public static final int TARGET_DISPLAYED_TRACK_POINTS = 5000; + static final int TARGET_DISPLAYED_TRACK_POINTS = 5000; + /** * Maximum number of waypoints to displayed. */ @VisibleForTesting - static final int MAX_DISPLAYED_WAYPOINTS = 128; + private static final int MAX_DISPLAYED_WAYPOINTS = 128; private static final String TAG = TrackDataHub.class.getSimpleName(); + private final Context context; private final TrackDataManager trackDataManager; private final ContentProviderUtils contentProviderUtils; @@ -87,8 +88,7 @@ public class TrackDataHub implements DataSourceListener { * @param targetNumPoints the target number of points */ @VisibleForTesting - TrackDataHub(Context context, TrackDataManager trackDataManager, - ContentProviderUtils contentProviderUtils, int targetNumPoints) { + private TrackDataHub(Context context, TrackDataManager trackDataManager, ContentProviderUtils contentProviderUtils, int targetNumPoints) { this.context = context; this.trackDataManager = trackDataManager; this.contentProviderUtils = contentProviderUtils; @@ -96,17 +96,11 @@ public class TrackDataHub implements DataSourceListener { resetSamplingState(); } - /** - * Creates a new instance. - */ public synchronized static TrackDataHub newInstance(Context context) { return new TrackDataHub(context, new TrackDataManager(), ContentProviderUtils.Factory.get( context), TARGET_DISPLAYED_TRACK_POINTS); } - /** - * Starts. - */ public void start() { if (started) { Log.i(TAG, "TrackDataHub already started, ignoring start."); @@ -131,9 +125,6 @@ public class TrackDataHub implements DataSourceListener { }); } - /** - * Stops. - */ public void stop() { if (!started) { Log.i(TAG, "TrackDataHub not started, ignoring stop."); @@ -151,11 +142,6 @@ public class TrackDataHub implements DataSourceListener { dataSourceManager = null; } - /** - * Loads a track. - * - * @param trackId the track id - */ public void loadTrack(final long trackId) { runInHandlerThread(new Runnable() { @Override @@ -222,8 +208,7 @@ public class TrackDataHub implements DataSourceListener { * Returns true if the selected track is recording. */ public boolean isSelectedTrackRecording() { - return selectedTrackId == recordingTrackId - && recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; + return selectedTrackId == recordingTrackId && recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; } /** @@ -258,8 +243,7 @@ public class TrackDataHub implements DataSourceListener { runInHandlerThread(new Runnable() { @Override public void run() { - notifyTrackPointsTableUpdate( - true, trackDataManager.getListeners(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE), + notifyTrackPointsTableUpdate(true, trackDataManager.getListeners(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE), trackDataManager.getListeners(TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE)); } }); @@ -270,47 +254,36 @@ public class TrackDataHub implements DataSourceListener { runInHandlerThread(new Runnable() { @Override public void run() { - if (key == null - || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_id_key))) { + if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_id_key))) { recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key); } - if (key == null - || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_paused_key))) { - recordingTrackPaused = PreferencesUtils.getBoolean( - context, R.string.recording_track_paused_key, - PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); + if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_paused_key))) { + recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); } - if (key == null - || key.equals(PreferencesUtils.getKey(context, R.string.stats_units_key))) { + if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.stats_units_key))) { metricUnits = PreferencesUtils.isMetricUnits(context); if (key != null) { - for (TrackDataListener trackDataListener : - trackDataManager.getListeners(TrackDataType.PREFERENCE)) { + for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) { if (trackDataListener.onMetricUnitsChanged(metricUnits)) { loadDataForListener(trackDataListener); } } } } - if (key == null - || key.equals(PreferencesUtils.getKey(context, R.string.stats_rate_key))) { + if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.stats_rate_key))) { reportSpeed = PreferencesUtils.isReportSpeed(context); if (key != null) { - for (TrackDataListener trackDataListener : - trackDataManager.getListeners(TrackDataType.PREFERENCE)) { + for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) { if (trackDataListener.onReportSpeedChanged(reportSpeed)) { loadDataForListener(trackDataListener); } } } } - if (key == null - || key.equals(PreferencesUtils.getKey(context, R.string.recording_gps_accuracy_key))) { - recordingGpsAccuracy = PreferencesUtils.getInt(context, R.string.recording_gps_accuracy_key, - PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT); + if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_gps_accuracy_key))) { + recordingGpsAccuracy = PreferencesUtils.getInt(context, R.string.recording_gps_accuracy_key, PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT); if (key != null) { - for (TrackDataListener trackDataListener : - trackDataManager.getListeners(TrackDataType.PREFERENCE)) { + for (TrackDataListener trackDataListener : trackDataManager.getListeners(TrackDataType.PREFERENCE)) { if (trackDataListener.onRecordingGpsAccuracy(recordingGpsAccuracy)) { loadDataForListener(trackDataListener); } @@ -359,7 +332,7 @@ public class TrackDataHub implements DataSourceListener { } /** - * Loads data for a listener. To be run in the {@link #handler} thread. + * Loads data for a listener; to be run in the {@link #handler} thread. * * @param trackDataListener the track data listener. */ @@ -386,8 +359,7 @@ public class TrackDataHub implements DataSourceListener { if (isOnlyListener) { resetSamplingState(); } - Set sampledOutListeners = hasSampledOut ? trackDataListeners - : Collections.emptySet(); + Set sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.emptySet(); notifyTrackPointsTableUpdate(isOnlyListener, trackDataListeners, sampledOutListeners); } @@ -397,7 +369,7 @@ public class TrackDataHub implements DataSourceListener { } /** - * Notifies track table update. To be run in the {@link #handler} thread. + * Notifies track table update; to be run in the {@link #handler} thread. * * @param trackDataListeners the track data listeners to notify */ @@ -412,9 +384,8 @@ public class TrackDataHub implements DataSourceListener { } /** - * Notifies waypoint table update. Currently, reloads all the waypoints up to - * {@link #MAX_DISPLAYED_WAYPOINTS}. To be run in the {@link #handler} - * thread. + * Notifies waypoint table update. + * Currently, reloads all the waypoints up to {@link #MAX_DISPLAYED_WAYPOINTS}. To be run in the {@link #handler} thread. * * @param trackDataListeners the track data listeners to notify */ @@ -448,18 +419,17 @@ public class TrackDataHub implements DataSourceListener { } /** - * Notifies track points table update. To be run in the {@link #handler} - * thread. + * Notifies track points table update; to be run in the {@link #handler} thread. * * @param updateSamplingState true to update the sampling state * @param sampledInListeners the sampled-in listeners * @param sampledOutListeners the sampled-out listeners */ - private void notifyTrackPointsTableUpdate(boolean updateSamplingState, - Set sampledInListeners, Set sampledOutListeners) { + private void notifyTrackPointsTableUpdate(boolean updateSamplingState, Set sampledInListeners, Set sampledOutListeners) { if (sampledInListeners.isEmpty() && sampledOutListeners.isEmpty()) { return; } + if (updateSamplingState && numLoadedPoints >= targetNumPoints) { // Reload and resample the track at a lower frequency. Log.i(TAG, "Resampling track after " + numLoadedPoints + " points."); @@ -477,11 +447,8 @@ public class TrackDataHub implements DataSourceListener { long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId); int samplingFrequency = -1; boolean includeNextPoint = false; - LocationIterator locationIterator = null; - try { - locationIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, - localLastSeenLocationId + 1, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY); + try (LocationIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, localLastSeenLocationId + 1, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY)) { while (locationIterator.hasNext()) { Location location = locationIterator.next(); @@ -509,8 +476,7 @@ public class TrackDataHub implements DataSourceListener { } } else { // Also include the last point if the selected track is not recording. - if (includeNextPoint || (localNumLoadedPoints % samplingFrequency == 0) - || (locationId == lastTrackPointId && !isSelectedTrackRecording())) { + if (includeNextPoint || (localNumLoadedPoints % samplingFrequency == 0) || (locationId == lastTrackPointId && !isSelectedTrackRecording())) { includeNextPoint = false; for (TrackDataListener trackDataListener : sampledInListeners) { trackDataListener.onSampledInTrackPoint(location); @@ -525,10 +491,6 @@ public class TrackDataHub implements DataSourceListener { localNumLoadedPoints++; localLastSeenLocationId = locationId; } - } finally { - if (locationIterator != null) { - locationIterator.close(); - } } if (updateSamplingState) { @@ -555,7 +517,7 @@ public class TrackDataHub implements DataSourceListener { * Creates a {@link DataSource}. */ @VisibleForTesting - protected DataSource newDataSource() { + private DataSource newDataSource() { return new DataSource(context); } @@ -565,7 +527,7 @@ public class TrackDataHub implements DataSourceListener { * @param runnable the runnable */ @VisibleForTesting - protected void runInHandlerThread(Runnable runnable) { + private void runInHandlerThread(Runnable runnable) { if (handler == null) { // Use a Throwable to ensure the stack trace is logged. Log.d(TAG, "handler is null.", new Throwable()); diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataListener.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataListener.java index 9155f2a74..fa461cfcd 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataListener.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataListener.java @@ -57,10 +57,8 @@ public interface TrackDataListener { void onSegmentSplit(Location location); /** - * Called when finish sending new track points. This gets called after every - * batch of calls to {@link #onSampledInTrackPoint(Location)}, - * {@link #onSampledOutTrackPoint(Location)} and - * {@link #onSegmentSplit(Location)}. + * Called when finish sending new track points. + * This gets called after every batch of calls to {@link #onSampledInTrackPoint(Location)}, {@link #onSampledOutTrackPoint(Location)} and {@link #onSegmentSplit(Location)}. */ void onNewTrackPointsDone(); @@ -77,9 +75,8 @@ public interface TrackDataListener { void onNewWaypoint(Waypoint waypoint); /** - * Called when finish sending new waypoints. This gets called after every - * batch of calls to {@link #clearWaypoints()} and - * {@link #onNewWaypoint(Waypoint)}. + * Called when finish sending new waypoints. + * This gets called after every batch of calls to {@link #clearWaypoints()} and {@link #onNewWaypoint(Waypoint)}. */ void onNewWaypointsDone(); diff --git a/src/main/java/de/dennisguse/opentracks/content/TrackDataManager.java b/src/main/java/de/dennisguse/opentracks/content/TrackDataManager.java index 4bf474cbb..24486de35 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TrackDataManager.java +++ b/src/main/java/de/dennisguse/opentracks/content/TrackDataManager.java @@ -26,24 +26,19 @@ import java.util.Map; import java.util.Set; /** - * Manages register/unregister {@link TrackDataListener} and keeping the state - * for each registered listener. + * Manages register/unregister {@link TrackDataListener} and keeping the state for each registered listener. * * @author Rodrigo Damazio */ -public class TrackDataManager { +class TrackDataManager { private static final String TAG = TrackDataManager.class.getSimpleName(); - // Map of listener to its track data types - private final Map> - listenerToTypesMap = new HashMap<>(); + private final Map> listenerToTypesMap = new HashMap<>(); - // Map of track data type to listeners - private final Map> - typeToListenersMap = new EnumMap<>(TrackDataType.class); + private final Map> typeToListenersMap = new EnumMap<>(TrackDataType.class); - public TrackDataManager() { + TrackDataManager() { for (TrackDataType trackDataType : TrackDataType.values()) { typeToListenersMap.put(trackDataType, new LinkedHashSet()); } @@ -55,8 +50,7 @@ public class TrackDataManager { * @param listener the listener * @param trackDataTypes the track data types the listener is interested */ - public void registerListener( - TrackDataListener listener, EnumSet trackDataTypes) { + void registerListener(TrackDataListener listener, EnumSet trackDataTypes) { if (listenerToTypesMap.containsKey(listener)) { Log.w(TAG, "Tried to register a listener that is already registered. Ignore."); return; @@ -72,7 +66,7 @@ public class TrackDataManager { * * @param listener the listener */ - public void unregisterListener(TrackDataListener listener) { + void unregisterListener(TrackDataListener listener) { EnumSet removedTypes = listenerToTypesMap.remove(listener); if (removedTypes == null) { Log.w(TAG, "Tried to unregister a listener that is not registered. Ignore."); @@ -88,7 +82,7 @@ public class TrackDataManager { /** * Gets the number of {@link TrackDataListener}. */ - public int getNumberOfListeners() { + int getNumberOfListeners() { return listenerToTypesMap.size(); } @@ -97,7 +91,7 @@ public class TrackDataManager { * * @param listener the listener */ - public EnumSet getTrackDataTypes(TrackDataListener listener) { + EnumSet getTrackDataTypes(TrackDataListener listener) { return listenerToTypesMap.get(listener); } @@ -106,14 +100,14 @@ public class TrackDataManager { * * @param type the type */ - public Set getListeners(TrackDataType type) { + Set getListeners(TrackDataType type) { return typeToListenersMap.get(type); } /** * Gets all the registered {@link TrackDataType}. */ - public EnumSet getRegisteredTrackDataTypes() { + EnumSet getRegisteredTrackDataTypes() { EnumSet types = EnumSet.noneOf(TrackDataType.class); for (EnumSet value : listenerToTypesMap.values()) { types.addAll(value); diff --git a/src/main/java/de/dennisguse/opentracks/content/TracksColumns.java b/src/main/java/de/dennisguse/opentracks/content/TracksColumns.java index 308181a37..7542aaf1a 100644 --- a/src/main/java/de/dennisguse/opentracks/content/TracksColumns.java +++ b/src/main/java/de/dennisguse/opentracks/content/TracksColumns.java @@ -27,25 +27,9 @@ import android.provider.BaseColumns; public interface TracksColumns extends BaseColumns { String TABLE_NAME = "tracks"; - - /** - * Tracks provider uri. - */ Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/tracks"); - - /** - * Track content type. - */ String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.track"; - - /** - * Track id content type. - */ String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.track"; - - /** - * Tracks table default sort order. - */ String DEFAULT_SORT_ORDER = "_id"; // Columns diff --git a/src/main/java/de/dennisguse/opentracks/content/Waypoint.java b/src/main/java/de/dennisguse/opentracks/content/Waypoint.java index a1d5cf638..4aa9cc1d2 100644 --- a/src/main/java/de/dennisguse/opentracks/content/Waypoint.java +++ b/src/main/java/de/dennisguse/opentracks/content/Waypoint.java @@ -42,6 +42,7 @@ public final class Waypoint implements Parcelable { return new Waypoint[size]; } }; + private long id = -1L; private String name = ""; private String description = ""; @@ -60,9 +61,7 @@ public final class Waypoint implements Parcelable { public Waypoint() { } - public Waypoint(String name, String description, String category, String icon, long trackId, - WaypointType type, double length, long duration, long startId, long stopId, Location location, - TripStatistics tripStatistics, String photoUrl) { + public Waypoint(String name, String description, String category, String icon, long trackId, WaypointType type, double length, long duration, long startId, long stopId, Location location, TripStatistics tripStatistics, String photoUrl) { this.name = name; this.description = description; this.category = category; diff --git a/src/main/java/de/dennisguse/opentracks/content/WaypointCreationRequest.java b/src/main/java/de/dennisguse/opentracks/content/WaypointCreationRequest.java index c865b7473..d5584009f 100644 --- a/src/main/java/de/dennisguse/opentracks/content/WaypointCreationRequest.java +++ b/src/main/java/de/dennisguse/opentracks/content/WaypointCreationRequest.java @@ -36,8 +36,10 @@ public class WaypointCreationRequest implements Parcelable { public static final Creator CREATOR = new Creator(); private WaypointType type; + // true if this marker contains the track statistics private boolean isTrackStatistics; + private String name; private String category; private String description; diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java index f9f5938b9..6113a6eb3 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java @@ -29,7 +29,11 @@ import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import java.util.ArrayList; +import java.util.EnumSet; + import de.dennisguse.opentracks.ChartView; +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.TrackDetailActivity; import de.dennisguse.opentracks.content.SensorDataSetLocation; import de.dennisguse.opentracks.content.Track; @@ -43,10 +47,6 @@ import de.dennisguse.opentracks.stats.TripStatisticsUpdater; import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.UnitConversions; -import de.dennisguse.opentracks.R; - -import java.util.ArrayList; -import java.util.EnumSet; /** * A fragment to display track chart to the user. @@ -79,8 +79,7 @@ public class ChartFragment extends Fragment implements TrackDataListener { private ZoomControls zoomControls; /** - * A runnable that will enable/disable zoom controls and orange pointer as - * appropriate and redraw. + * A runnable that will enable/disable zoom controls and orange pointer as appropriate and redraw. */ private final Runnable updateChart = new Runnable() { @Override @@ -101,15 +100,13 @@ public class ChartFragment extends Fragment implements TrackDataListener { super.onCreate(savedInstanceState); /* - * Create a chartView here to store data thus won't need to reload all the - * data on every onStart or onResume. + * Create a chartView here to store data thus won't need to reload all the data on every onStart or onResume. */ chartView = new ChartView(getActivity()); } @Override - public View onCreateView( - @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.chart, container, false); zoomControls = view.findViewById(R.id.chart_zoom_controls); zoomControls.setOnZoomInClickListener(new View.OnClickListener() { @@ -131,8 +128,7 @@ public class ChartFragment extends Fragment implements TrackDataListener { public void onStart() { super.onStart(); ViewGroup layout = getActivity().findViewById(R.id.chart_view_layout); - LayoutParams layoutParams = new LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); layout.addView(chartView, layoutParams); } @@ -350,9 +346,9 @@ public class ChartFragment extends Fragment implements TrackDataListener { chartShow[index] = value; chartView.setChartValueSeriesEnabled(index, value); return true; - } else { - return false; } + + return false; } /** diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeImageAdapter.java b/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeImageAdapter.java index 3397ee849..f01157a37 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeImageAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeImageAdapter.java @@ -41,7 +41,7 @@ public class ChooseActivityTypeImageAdapter extends BaseAdapter { private final int padding; private int selected = -1; - public ChooseActivityTypeImageAdapter(Context context, List imageIds, int width, int height, int padding) { + ChooseActivityTypeImageAdapter(Context context, List imageIds, int width, int height, int padding) { this.context = context; this.imageIds = imageIds; this.width = width; diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java index ae56f8923..75e0b5d39 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ConfirmDeleteDialogFragment.java @@ -21,8 +21,8 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import de.dennisguse.opentracks.util.DialogUtils; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.util.DialogUtils; /** * A DialogFragment to confirm delete. @@ -38,8 +38,7 @@ public class ConfirmDeleteDialogFragment extends AbstractDialogFragment { /** * Create a new instance. * - * @param trackIds list of track ids to delete. To delete all, set to size 1 - * with trackIds[0] == -1L + * @param trackIds list of track ids to delete. To delete all, set to size 1 with trackIds[0] == -1L */ public static ConfirmDeleteDialogFragment newInstance(long[] trackIds) { Bundle bundle = new Bundle(); @@ -65,10 +64,8 @@ public class ConfirmDeleteDialogFragment extends AbstractDialogFragment { final long[] trackIds = getArguments().getLongArray(KEY_TRACK_IDS); int titleId; int messageId; - titleId = trackIds.length > 1 ? R.string.generic_delete_selected_confirm_title - : R.string.track_delete_one_confirm_title; - messageId = trackIds.length > 1 ? R.string.track_delete_multiple_confirm_message - : R.string.track_delete_one_confirm_message; + titleId = trackIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.track_delete_one_confirm_title; + messageId = trackIds.length > 1 ? R.string.track_delete_multiple_confirm_message : R.string.track_delete_one_confirm_message; return DialogUtils.createConfirmationDialog( getActivity(), titleId, getString(messageId), new DialogInterface.OnClickListener() { @Override diff --git a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java index 334443675..ebcb8c6d6 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/DeleteMarkerDialogFragment.java @@ -23,10 +23,10 @@ import android.os.Bundle; import androidx.fragment.app.FragmentActivity; +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.content.ContentProviderUtils; import de.dennisguse.opentracks.content.DescriptionGeneratorImpl; import de.dennisguse.opentracks.util.DialogUtils; -import de.dennisguse.opentracks.R; /** * A DialogFragment to delete marker. @@ -68,10 +68,8 @@ public class DeleteMarkerDialogFragment extends AbstractDialogFragment { titleId = R.string.generic_delete_all_confirm_title; messageId = R.string.marker_delete_all_confirm_message; } else { - titleId = markerIds.length > 1 ? R.string.generic_delete_selected_confirm_title - : R.string.marker_delete_one_confirm_title; - messageId = markerIds.length > 1 ? R.string.marker_delete_multiple_confirm_message - : R.string.marker_delete_one_confirm_message; + titleId = markerIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.marker_delete_one_confirm_title; + messageId = markerIds.length > 1 ? R.string.marker_delete_multiple_confirm_message : R.string.marker_delete_one_confirm_message; } return DialogUtils.createConfirmationDialog( fragmentActivity, titleId, getString(messageId), new DialogInterface.OnClickListener() { diff --git a/src/main/java/de/dennisguse/opentracks/fragments/FileTypeDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/FileTypeDialogFragment.java index d93176317..d0dc8a1ea 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/FileTypeDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/FileTypeDialogFragment.java @@ -96,7 +96,7 @@ public class FileTypeDialogFragment extends AbstractDialogFragment { onDismissed(); } - protected void onDismissed() { + private void onDismissed() { dismiss(); caller.onDismissed(); } diff --git a/src/main/java/de/dennisguse/opentracks/fragments/FrequencyDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/FrequencyDialogFragment.java index 07c032325..0b760dbba 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/FrequencyDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/FrequencyDialogFragment.java @@ -23,9 +23,9 @@ import android.os.Bundle; import androidx.fragment.app.FragmentActivity; +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; -import de.dennisguse.opentracks.R; /** * A DialogFragment to configure frequency. @@ -82,8 +82,8 @@ public class FrequencyDialogFragment extends AbstractDialogFragment { } /** - * Gets the list index for a frequency value. Returns 0 if the value is not on - * the list. + * Gets the list index for a frequency value. + * Returns 0 if the value is not on the list. */ private int getListIndex(int frequencyValue) { String[] values = getResources().getStringArray(R.array.frequency_values); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java index 4b5a60d9e..e63ea87b9 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java @@ -69,6 +69,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { private Location lastLocation = null; private TripStatistics lastTripStatistics = null; private SensorDataSet sensorDataSet = null; + private final Runnable updateUIeachSecond = new Runnable() { public void run() { if (isResumed() && isSelectedTrackRecording()) { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java index cb06ffb76..9c7ea6bd2 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportActivity.java @@ -38,8 +38,8 @@ import de.dennisguse.opentracks.util.DialogUtils; import de.dennisguse.opentracks.util.FileUtils; /** - * An activity for saving tracks to the external storage. If saving a specific - * track, option to save it to a temp directory and play the track afterward. + * An activity for saving tracks to the external storage. + * If saving a specific track, option to save it to a temp directory and play the track afterward. * * @author Rodrigo Damazio */ @@ -53,13 +53,11 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr private String directoryDisplayName; private ExportAsyncTask exportAsyncTask; + private ProgressDialog progressDialog; - // the number of tracks successfully saved - private int successCount; - - // the number of tracks to save - private int totalCount; + private int processedTrackCount; + private int totalTrackCount; @Override public void onCreate(Bundle savedInstanceState) { @@ -144,8 +142,8 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr int titleId; String message; String totalTracks = getResources() - .getQuantityString(R.plurals.tracks, totalCount, totalCount); - if (successCount == totalCount) { + .getQuantityString(R.plurals.tracks, totalTrackCount, totalTrackCount); + if (processedTrackCount == totalTrackCount) { iconId = R.drawable.ic_dialog_success; titleId = R.string.generic_success_title; message = getString( @@ -153,7 +151,7 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr } else { iconId = android.R.drawable.ic_dialog_alert; titleId = R.string.generic_error_title; - message = getString(R.string.export_external_storage_error, successCount, totalTracks, + message = getString(R.string.export_external_storage_error, processedTrackCount, totalTracks, directoryDisplayName); } AlertDialog.Builder builder = new AlertDialog.Builder(this).setCancelable(true) @@ -192,8 +190,8 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr * @param aTotalCount the number of tracks to save */ public void onAsyncTaskCompleted(int aSuccessCount, int aTotalCount) { - successCount = aSuccessCount; - totalCount = aTotalCount; + processedTrackCount = aSuccessCount; + totalTrackCount = aTotalCount; removeDialog(DIALOG_PROGRESS_ID); showDialog(DIALOG_RESULT_ID); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java index efec1e9c0..f47ee3671 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/ExportAsyncTask.java @@ -52,17 +52,10 @@ public class ExportAsyncTask extends AsyncTask { private ExportActivity exportActivity; private WakeLock wakeLock; - // true if the AsyncTask has completed private boolean completed; - // the number of tracks successfully saved - private int successCount; - - // the number of tracks to save - private int totalCount; - - // the last successfully saved path - private String savedPath; + private int processedTrackCount; + private int totalTrackCount; /** * Creates an AsyncTask. @@ -79,9 +72,8 @@ public class ExportAsyncTask extends AsyncTask { contentProviderUtils = ContentProviderUtils.Factory.get(context); completed = false; - successCount = 0; - totalCount = 0; - savedPath = null; + processedTrackCount = 0; + totalTrackCount = 0; } /** @@ -92,7 +84,7 @@ public class ExportAsyncTask extends AsyncTask { public void setActivity(ExportActivity exportActivity) { this.exportActivity = exportActivity; if (completed && exportActivity != null) { - exportActivity.onAsyncTaskCompleted(successCount, totalCount); + exportActivity.onAsyncTaskCompleted(processedTrackCount, totalTrackCount); } } @@ -132,7 +124,7 @@ public class ExportAsyncTask extends AsyncTask { protected void onPostExecute(Boolean result) { completed = true; if (exportActivity != null) { - exportActivity.onAsyncTaskCompleted(successCount, totalCount); + exportActivity.onAsyncTaskCompleted(processedTrackCount, totalTrackCount); } } @@ -140,7 +132,7 @@ public class ExportAsyncTask extends AsyncTask { protected void onCancelled() { completed = true; if (exportActivity != null) { - exportActivity.onAsyncTaskCompleted(successCount, totalCount); + exportActivity.onAsyncTaskCompleted(processedTrackCount, totalTrackCount); } } @@ -172,7 +164,6 @@ public class ExportAsyncTask extends AsyncTask { try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { if (trackExporter.writeTrack(fileOutputStream)) { - savedPath = file.getAbsolutePath(); return true; } else { if (!file.delete()) { @@ -198,17 +189,17 @@ public class ExportAsyncTask extends AsyncTask { if (cursor == null) { return false; } - totalCount = cursor.getCount(); - for (int i = 0; i < totalCount; i++) { + totalTrackCount = cursor.getCount(); + for (int i = 0; i < totalTrackCount; i++) { if (isCancelled()) { return false; } cursor.moveToPosition(i); Track track = contentProviderUtils.createTrack(cursor); if (track != null && saveTracks(new Track[]{track})) { - successCount++; + processedTrackCount++; } - publishProgress(i + 1, totalCount); + publishProgress(i + 1, totalTrackCount); } return true; } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java index 01efac787..161f0a66b 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/FileTrackExporter.java @@ -22,7 +22,6 @@ import android.util.Log; import java.io.OutputStream; -import de.dennisguse.opentracks.Constants; import de.dennisguse.opentracks.content.ContentProviderUtils; import de.dennisguse.opentracks.content.ContentProviderUtils.LocationIterator; import de.dennisguse.opentracks.content.SensorDataSetLocation; @@ -89,17 +88,13 @@ public class FileTrackExporter implements TrackExporter { */ private void writeWaypoints(Track track) throws InterruptedException { /* - * TODO: Stream through the waypoints in chunks. I am leaving the number of - * waypoints very high which should not be a problem because we don't try to - * load them into objects all at the same time. + * TODO: Stream through the waypoints in chunks. + * I am leaving the number of waypoints very high which should not be a problem, because we don't try to load them into objects all at the same time. */ boolean hasWaypoints = false; - try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)) { + try (Cursor cursor = contentProviderUtils.getWaypointCursor(track.getId(), -1L, ContentProviderUtils.MAX_LOADED_WAYPOINTS_POINTS)) { if (cursor != null && cursor.moveToFirst()) { - /* - * Yes, this will skip the first waypoint and that is intentional as the - * first waypoint holds the stats for the track. - */ + // Intentionally skip first waypoint (contains statistics). while (cursor.moveToNext()) { if (Thread.interrupted()) { throw new InterruptedException(); @@ -127,10 +122,8 @@ public class FileTrackExporter implements TrackExporter { boolean isLastLocationValid = false; TrackWriterLocationFactory locationFactory = new TrackWriterLocationFactory(); int locationNumber = 0; - LocationIterator locationIterator = null; - try { - locationIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L, false, locationFactory); + try (LocationIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L, false, locationFactory)) { while (locationIterator.hasNext()) { if (Thread.interrupted()) { @@ -188,10 +181,6 @@ public class FileTrackExporter implements TrackExporter { trackWriter.writeBeginTrack(track, null); trackWriter.writeEndTrack(track, null); } - } finally { - if (locationIterator != null) { - locationIterator.close(); - } } } @@ -224,7 +213,7 @@ public class FileTrackExporter implements TrackExporter { return currentLocation; } - public void swapLocations() { + void swapLocations() { Location tempLocation = lastLocation; lastLocation = currentLocation; currentLocation = tempLocation; diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GpxTrackWriter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GpxTrackWriter.java index 3de5d477e..818d141c7 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GpxTrackWriter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GpxTrackWriter.java @@ -32,7 +32,7 @@ import de.dennisguse.opentracks.util.StringUtils; * * @author Sandor Dornbush */ -//TODO Can we export Sensor.Data in GPX? +//TODO Can we export SensorData in GPX? public class GpxTrackWriter implements TrackWriter { private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US); @@ -188,7 +188,6 @@ public class GpxTrackWriter implements TrackWriter { * @param location the location */ private String formatLocation(Location location) { - return "lat=\"" + COORDINATE_FORMAT.format(location.getLatitude()) + "\" lon=\"" - + COORDINATE_FORMAT.format(location.getLongitude()) + "\""; + return "lat=\"" + COORDINATE_FORMAT.format(location.getLatitude()) + "\" lon=\"" + COORDINATE_FORMAT.format(location.getLongitude()) + "\""; } } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java index 690ffcad9..81bf97ea0 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java @@ -55,23 +55,26 @@ import de.dennisguse.opentracks.util.TrackIconUtils; import de.dennisguse.opentracks.util.UnitConversions; /** - * Abstract class for various file track importers like {@link GpxFileTrackImporter} and - * {@link KmlFileTrackImporter}. + * Abstract class for file track importers. * * @author Jimmy Shih */ abstract class AbstractFileTrackImporter extends DefaultHandler implements TrackImporter { private static final String TAG = AbstractFileTrackImporter.class.getSimpleName(); + // The maximum number of buffered locations for bulk-insertion private static final int MAX_BUFFERED_LOCATIONS = 512; private final Context context; private final long importTrackId; private final ContentProviderUtils contentProviderUtils; private final int recordingDistanceInterval; + private final List trackIds; private final List waypoints; + // The current element content + //TODO Should be made private and getter be used by child classes. protected String content; protected String name; protected String description; @@ -82,25 +85,24 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track protected String time; protected String waypointType; protected String photoUrl; + // The current track data private TrackData trackData; + // The SAX locator to get the current line information private Locator locator; + /** * Constructor. * * @param context the context - * @param importTrackId the track id to import to. -1L to import to a new - * track. + * @param importTrackId the track id to import to. -1L to import to a new track. */ - AbstractFileTrackImporter( - Context context, long importTrackId, ContentProviderUtils contentProviderUtils) { + AbstractFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) { this.context = context; this.importTrackId = importTrackId; this.contentProviderUtils = contentProviderUtils; - this.recordingDistanceInterval = PreferencesUtils.getInt(context, - R.string.recording_distance_interval_key, - PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT); + this.recordingDistanceInterval = PreferencesUtils.getInt(context, R.string.recording_distance_interval_key, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT); trackIds = new ArrayList<>(); waypoints = new ArrayList<>(); } @@ -116,11 +118,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track if (content == null) { content = newContent; } else { - /* - * In 99% of the cases, a single call to this method will be made for each - * sequence of characters we're interested in, so we'll rarely be - * concatenating strings, thus not justifying the use of a StringBuilder. - */ + // In 99% of the cases, a single call to this method will be made for each sequence of characters we're interested in, so we'll rarely be concatenating strings, thus not justifying the use of a StringBuilder. content += newContent; } } @@ -164,15 +162,10 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track int waypointPosition = -1; Waypoint waypoint = null; Location location = null; - TripStatisticsUpdater trackTripStatisticstrackUpdater = new TripStatisticsUpdater( - track.getTripStatistics().getStartTime()); - TripStatisticsUpdater markerTripStatisticsUpdater = new TripStatisticsUpdater( - track.getTripStatistics().getStartTime()); - LocationIterator locationIterator = null; + TripStatisticsUpdater trackTripStatisticstrackUpdater = new TripStatisticsUpdater(track.getTripStatistics().getStartTime()); + TripStatisticsUpdater markerTripStatisticsUpdater = new TripStatisticsUpdater(track.getTripStatistics().getStartTime()); - try { - locationIterator = contentProviderUtils.getTrackPointLocationIterator( - track.getId(), -1L, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY); + try (LocationIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), -1L, false, ContentProviderUtils.DEFAULT_LOCATION_FACTORY)) { while (true) { if (waypoint == null) { @@ -198,7 +191,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track waypoint = null; } else { // The waypoint location time matches the track point time - if (!LocationUtils.isValidLocation(location)) { // Invalid location, load the next location location = null; @@ -206,8 +198,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } // Valid location - if (location.getLatitude() == waypoint.getLocation().getLatitude() - && location.getLongitude() == waypoint.getLocation().getLongitude()) { + if (location.getLatitude() == waypoint.getLocation().getLatitude() && location.getLongitude() == waypoint.getLocation().getLongitude()) { // Get tripStatistics, description, and icon TripStatistics tripStatistics; @@ -216,8 +207,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track if (waypoint.getType() == WaypointType.STATISTICS) { tripStatistics = markerTripStatisticsUpdater.getTripStatistics(); markerTripStatisticsUpdater = new TripStatisticsUpdater(location.getTime()); - waypointDescription = new DescriptionGeneratorImpl(context) - .generateWaypointDescription(tripStatistics); + waypointDescription = new DescriptionGeneratorImpl(context).generateWaypointDescription(tripStatistics); icon = context.getString(R.string.marker_statistics_icon_url); } else { tripStatistics = null; @@ -230,9 +220,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track long duration = trackTripStatisticstrackUpdater.getTripStatistics().getTotalTime(); // Insert waypoint - Waypoint newWaypoint = new Waypoint(waypoint.getName(), waypointDescription, - waypoint.getCategory(), icon, track.getId(), waypoint.getType(), length, duration, - -1L, -1L, location, tripStatistics, waypoint.getPhotoUrl()); + Waypoint newWaypoint = new Waypoint(waypoint.getName(), waypointDescription, waypoint.getCategory(), icon, track.getId(), waypoint.getType(), length, duration, -1L, -1L, location, tripStatistics, waypoint.getPhotoUrl()); contentProviderUtils.insertWaypoint(newWaypoint); } @@ -240,10 +228,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track waypoint = null; } } - } finally { - if (locationIterator != null) { - locationIterator.close(); - } } } @@ -258,8 +242,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements 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)); + throw new SAXException(createErrorMessage("Cannot import more than one track to an existing track " + importTrackId)); } trackId = importTrackId; contentProviderUtils.clearTrack(context, trackId); @@ -299,13 +282,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track protected void onTrackSegmentStart() { trackData.numberOfSegments++; - /* - * If not the first segment, add a pause separator if there is at least one - * location in the last segment. - */ + //If not the first segment, add a pause separator if there is at least one location in the last segment. if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment != null) { - insertLocation(createLocation(TrackRecordingService.PAUSE_LATITUDE, 0.0, 0.0, - trackData.lastLocationInCurrentSegment.getTime())); + insertLocation(createLocation(TrackRecordingService.PAUSE_LATITUDE, 0.0, 0.0, trackData.lastLocationInCurrentSegment.getTime())); } trackData.lastLocationInCurrentSegment = null; } @@ -362,10 +341,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } else { /* - * We don't have a speed and bearing in GPX, make something up from the - * last two points. GPS points tend to have some inherent imprecision, - * speed and bearing will likely be off, so the statistics for things - * like max speed will also be off. + * We don't have a speed and bearing in GPX, make something up from the last two points. + * GPS points tend to have some inherent imprecision, speed and bearing will likely be off, so the statistics for things like max speed will also be off. */ double duration = timeDifference * UnitConversions.MS_TO_S; double speed = trackData.lastLocationInCurrentSegment.distanceTo(location) / duration; @@ -379,10 +356,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track } if (trackData.numberOfSegments > 1 && trackData.lastLocationInCurrentSegment == null) { - /* - * If not the first segment, add a resume separator before adding the - * first location. - */ + // If not the first segment, add a resume separator before adding the first location. insertLocation( createLocation(TrackRecordingService.RESUME_LATITUDE, 0.0, 0.0, location.getTime())); } @@ -441,17 +415,14 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track latitudeValue = Double.parseDouble(latitude); longitudeValue = Double.parseDouble(longitude); } catch (NumberFormatException e) { - throw new SAXException(createErrorMessage(String.format( - Locale.US, "Unable to parse latitude longitude: %s %s", latitude, longitude)), e); + throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse latitude longitude: %s %s", latitude, longitude)), e); } Double altitudeValue = null; if (altitude != null) { try { altitudeValue = Double.parseDouble(altitude); } catch (NumberFormatException e) { - throw new SAXException( - createErrorMessage(String.format(Locale.US, "Unable to parse altitude: %s", altitude)), - e); + throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude: %s", altitude)), e); } } @@ -462,8 +433,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track try { timeValue = StringUtils.getTime(time); } catch (IllegalArgumentException e) { - throw new SAXException( - createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e); + throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e); } } return createLocation(latitudeValue, longitudeValue, altitudeValue, timeValue); @@ -477,8 +447,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track * @param altitudeValue the altitude value * @param timeValue the time value */ - private Location createLocation( - double latitudeValue, double longitudeValue, Double altitudeValue, long timeValue) { + private Location createLocation(double latitudeValue, double longitudeValue, Double altitudeValue, long timeValue) { Location location = new Location(LocationManager.GPS_PROVIDER); location.setLatitude(latitudeValue); location.setLongitude(longitudeValue); @@ -501,8 +470,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track */ private void insertLocation(Location location) { if (trackData.tripStatisticsUpdater == null) { - trackData.tripStatisticsUpdater = new TripStatisticsUpdater( - location.getTime() != -1L ? location.getTime() : trackData.importTime); + trackData.tripStatisticsUpdater = new TripStatisticsUpdater(location.getTime() != -1L ? location.getTime() : trackData.importTime); } trackData.tripStatisticsUpdater.addLocation(location, recordingDistanceInterval); @@ -524,8 +492,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track if (data.numBufferedLocations <= 0) { return; } - contentProviderUtils.bulkInsertTrackPoint( - data.bufferedLocations, data.numBufferedLocations, data.track.getId()); + contentProviderUtils.bulkInsertTrackPoint(data.bufferedLocations, data.numBufferedLocations, data.track.getId()); data.numBufferedLocations = 0; if (data.track.getStartId() == -1L) { data.track.setStartId(contentProviderUtils.getFirstTrackPointId(data.track.getId())); @@ -541,20 +508,16 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track private void insertFirstWaypoint(Track track) { String waypointName = context.getString(R.string.marker_split_name_format, 0); String waypointCategory = ""; - TripStatisticsUpdater updater = new TripStatisticsUpdater( - track.getTripStatistics().getStartTime()); + TripStatisticsUpdater updater = new TripStatisticsUpdater(track.getTripStatistics().getStartTime()); TripStatistics tripStatistics = updater.getTripStatistics(); - String waypointDescription = new DescriptionGeneratorImpl(context).generateWaypointDescription( - tripStatistics); + String waypointDescription = new DescriptionGeneratorImpl(context).generateWaypointDescription(tripStatistics); String icon = context.getString(R.string.marker_statistics_icon_url); double length = 0.0; long duration = 0L; Location waypointLocation = new Location(""); waypointLocation.setLatitude(100); waypointLocation.setLongitude(180); - Waypoint waypoint = new Waypoint(waypointName, waypointDescription, waypointCategory, icon, - track.getId(), WaypointType.STATISTICS, length, duration, -1L, -1L, waypointLocation, - tripStatistics, ""); + Waypoint waypoint = new Waypoint(waypointName, waypointDescription, waypointCategory, icon, track.getId(), WaypointType.STATISTICS, length, duration, -1L, -1L, waypointLocation, tripStatistics, ""); contentProviderUtils.insertWaypoint(waypoint); } @@ -573,17 +536,13 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track * @author Jimmy Shih */ private class TrackData { - // The current track Track track = new Track(); // The number of segments processed for the current track int numberOfSegments = 0; - /* - * The last location in the current segment. Null if the current segment - * doesn't have a last location. - */ + // The last location in the current segment; Null if the current segment doesn't have a last location Location lastLocationInCurrentSegment; // The number of locations processed for the current track diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporter.java index a911a3c9f..2d4ee49a1 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/GpxFileTrackImporter.java @@ -64,8 +64,7 @@ public class GpxFileTrackImporter extends AbstractFileTrackImporter { } @Override - public void startElement(String uri, String localName, String tag, Attributes attributes) - throws SAXException { + public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException { switch (tag) { case TAG_WAYPOINT: onWaypointStart(attributes); @@ -185,7 +184,6 @@ public class GpxFileTrackImporter extends AbstractFileTrackImporter { * On waypoint end. */ private void onWaypointEnd() throws SAXException { - addWaypoint(WaypointType.STATISTICS.name().equals(waypointType) ? WaypointType.STATISTICS - : WaypointType.WAYPOINT); + addWaypoint(WaypointType.STATISTICS.name().equals(waypointType) ? WaypointType.STATISTICS : WaypointType.WAYPOINT); } } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportActivity.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportActivity.java index ae579c8b8..57c1d4486 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportActivity.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportActivity.java @@ -56,11 +56,9 @@ public class ImportActivity extends FragmentActivity implements FileTypeDialogFr // the path on the external storage to import private String directoryDisplayName; - // the number of files successfully imported - private int successCount; + private int importedTrackCount; - // the number of files to import - private int totalCount; + private int totalTrackCount; @Override public void onCreate(Bundle savedInstanceState) { @@ -144,9 +142,9 @@ public class ImportActivity extends FragmentActivity implements FileTypeDialogFr int titleId; String message; String totalFiles = getResources() - .getQuantityString(R.plurals.files, totalCount, totalCount); - if (successCount == totalCount) { - if (totalCount == 0) { + .getQuantityString(R.plurals.files, totalTrackCount, totalTrackCount); + if (importedTrackCount == totalTrackCount) { + if (totalTrackCount == 0) { iconId = android.R.drawable.ic_dialog_info; titleId = R.string.import_no_file_title; message = getString(R.string.import_no_file, directoryDisplayName); @@ -159,7 +157,7 @@ public class ImportActivity extends FragmentActivity implements FileTypeDialogFr iconId = android.R.drawable.ic_dialog_alert; titleId = R.string.generic_error_title; message = getString( - R.string.import_error, successCount, totalFiles, directoryDisplayName); + R.string.import_error, importedTrackCount, totalFiles, directoryDisplayName); } final Dialog dialog = new AlertDialog.Builder(this).setCancelable(true).setIcon(iconId) .setMessage(message).setOnCancelListener(new DialogInterface.OnCancelListener() { @@ -195,8 +193,8 @@ public class ImportActivity extends FragmentActivity implements FileTypeDialogFr * @param aTotalCount the number of files to import */ public void onAsyncTaskCompleted(int aSuccessCount, int aTotalCount) { - successCount = aSuccessCount; - totalCount = aTotalCount; + importedTrackCount = aSuccessCount; + totalTrackCount = aTotalCount; removeDialog(DIALOG_PROGRESS_ID); showDialog(DIALOG_RESULT_ID); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java index 09aad24e8..bd3d75524 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportAsyncTask.java @@ -53,11 +53,9 @@ public class ImportAsyncTask extends AsyncTask { // true if the AsyncTask has completed private boolean completed; - // the number of files successfully imported - private int successCount; + private int importTrackCount; - // the number of files to import - private int totalCount; + private int totalTrackCount; // the last successfully imported track id private long trackId; @@ -76,8 +74,8 @@ public class ImportAsyncTask extends AsyncTask { context = importActivity.getApplicationContext(); completed = false; - successCount = 0; - totalCount = 0; + importTrackCount = 0; + totalTrackCount = 0; trackId = -1L; } @@ -89,7 +87,7 @@ public class ImportAsyncTask extends AsyncTask { public void setActivity(ImportActivity importActivity) { this.importActivity = importActivity; if (completed && importActivity != null) { - importActivity.onAsyncTaskCompleted(successCount, totalCount); + importActivity.onAsyncTaskCompleted(importTrackCount, totalTrackCount); } } @@ -112,20 +110,20 @@ public class ImportAsyncTask extends AsyncTask { } List files = getFiles(); - totalCount = files.size(); - if (totalCount == 0) { + totalTrackCount = files.size(); + if (totalTrackCount == 0) { return true; } - for (int i = 0; i < totalCount; i++) { + for (int i = 0; i < totalTrackCount; i++) { if (isCancelled()) { // If cancelled, return true to show the number of files imported return true; } if (importFile(files.get(i))) { - successCount++; + importTrackCount++; } - publishProgress(i + 1, totalCount); + publishProgress(i + 1, totalTrackCount); } return true; } finally { @@ -146,7 +144,7 @@ public class ImportAsyncTask extends AsyncTask { protected void onPostExecute(Boolean result) { completed = true; if (importActivity != null) { - importActivity.onAsyncTaskCompleted(successCount, totalCount); + importActivity.onAsyncTaskCompleted(importTrackCount, totalTrackCount); } } @@ -154,7 +152,7 @@ public class ImportAsyncTask extends AsyncTask { protected void onCancelled() { completed = true; if (importActivity != null) { - importActivity.onAsyncTaskCompleted(successCount, totalCount); + importActivity.onAsyncTaskCompleted(importTrackCount, totalTrackCount); } } @@ -190,9 +188,9 @@ public class ImportAsyncTask extends AsyncTask { } /** - * Gets a list of files. If importAll is true, returns a list of the files - * under the path directory. If importAll is false, returns a list containing - * just the path file. + * Gets a list of files. + * If importAll is true, returns a list of the files under the path directory. + * If importAll is false, returns a list containing just the path file. */ private List getFiles() { List files = new ArrayList<>(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporter.java index 8def3ba97..ae28a6c41 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmlFileTrackImporter.java @@ -22,16 +22,16 @@ import android.net.Uri; import androidx.annotation.VisibleForTesting; -import de.dennisguse.opentracks.content.ContentProviderUtils; -import de.dennisguse.opentracks.content.SensorDataSetLocation; -import de.dennisguse.opentracks.content.Waypoint.WaypointType; -import de.dennisguse.opentracks.content.sensor.SensorDataSet; - import org.xml.sax.Attributes; import org.xml.sax.SAXException; import java.util.ArrayList; +import de.dennisguse.opentracks.content.ContentProviderUtils; +import de.dennisguse.opentracks.content.SensorDataSetLocation; +import de.dennisguse.opentracks.content.Waypoint.WaypointType; +import de.dennisguse.opentracks.content.sensor.SensorDataSet; + /** * Imports a KML file. * @@ -82,8 +82,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { } @VisibleForTesting - KmlFileTrackImporter( - Context context, long importTrackId, ContentProviderUtils contentProviderUtils) { + KmlFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) { super(context, importTrackId, contentProviderUtils); } @@ -93,11 +92,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { switch (tag) { case TAG_PLACEMARK: case TAG_PHOTO_OVERLAY: - /* - * Note that a track is contained in a Placemark, calling onWaypointStart - * will clear various track variables like name, category, and - * description. - */ + // Note that a track is contained in a Placemark, calling onWaypointStart will clear various track variables like name, category, and description. onWaypointStart(); break; case TAG_GX_MULTI_TRACK: @@ -118,13 +113,11 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { @Override 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 if (tag.equals(TAG_KML)) { onFileEnd(); } else if (tag.equals(TAG_PLACEMARK) || tag.equals(TAG_PHOTO_OVERLAY)) { - /* - * Note that a track is contained in a Placemark, calling onWaypointend is - * save since waypointType is not set for a track. - */ + // Note that a track is contained in a Placemark, calling onWaypointend is save since waypointType is not set for a track. onWaypointEnd(); } else if (localName.equals(TAG_COORDINATES)) { onWaypointLocationEnd(); @@ -187,19 +180,23 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter { */ private void onWaypointEnd() throws SAXException { // Add a waypoint if the waypointType matches - WaypointType type = null; - if (WAYPOINT_STYLE.equals(waypointType)) { - type = WaypointType.WAYPOINT; - } else if (STATISTICS_STYLE.equals(waypointType)) { - type = WaypointType.STATISTICS; - } - if (type == null) { - return; + WaypointType type; + switch (waypointType) { + case WAYPOINT_STYLE: + type = WaypointType.WAYPOINT; + break; + case STATISTICS_STYLE: + type = WaypointType.STATISTICS; + break; + default: + return; } + if (photoUrl != null) { Uri uri = Uri.parse(photoUrl); photoUrl = getPhotoUrl(uri.getLastPathSegment()); } + addWaypoint(type); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java index afe048a0e..6eca37946 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KmzTrackImporter.java @@ -20,10 +20,6 @@ import android.content.Context; import android.net.Uri; import android.util.Log; -import de.dennisguse.opentracks.content.ContentProviderUtils; -import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter; -import de.dennisguse.opentracks.util.FileUtils; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -33,6 +29,11 @@ import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import de.dennisguse.opentracks.content.ContentProviderUtils; +import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter; +import de.dennisguse.opentracks.util.FileUtils; +import de.dennisguse.opentracks.util.PreferencesUtils; + /** * Imports a KMZ file. * @@ -41,6 +42,7 @@ import java.util.zip.ZipInputStream; public class KmzTrackImporter implements TrackImporter { private static final String TAG = KmzTrackImporter.class.getSimpleName(); + private static final int BUFFER_SIZE = 4096; private final Context context; @@ -50,22 +52,19 @@ public class KmzTrackImporter implements TrackImporter { * Constructor. * * @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 importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported. */ - public KmzTrackImporter(Context context, long importTrackId) { + KmzTrackImporter(Context context, long importTrackId) { this.context = context; this.importTrackId = importTrackId; } @Override public long importFile(InputStream inputStream) { - ZipInputStream zipInputStream = null; long trackId = importTrackId; - try { + try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { ZipEntry zipEntry; - zipInputStream = new ZipInputStream(inputStream); while ((zipEntry = zipInputStream.getNextEntry()) != null) { if (Thread.interrupted()) { Log.d(TAG, "Thread interrupted"); @@ -93,14 +92,6 @@ public class KmzTrackImporter implements TrackImporter { Log.e(TAG, "Unable to import file", e); cleanImport(trackId); return -1L; - } finally { - if (zipInputStream != null) { - try { - zipInputStream.close(); - } catch (IOException e) { - Log.e(TAG, "Unable to close zip input stream", e); - } - } } } @@ -110,7 +101,7 @@ public class KmzTrackImporter implements TrackImporter { * @param trackId the trackId */ private void cleanImport(long trackId) { - if (trackId != -1L) { + if (trackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { ContentProviderUtils contentProviderUtils = ContentProviderUtils.Factory.get(context); contentProviderUtils.deleteTrack(context, trackId); } @@ -169,19 +160,17 @@ public class KmzTrackImporter implements TrackImporter { * @param fileName the file name */ private void readImageFile(ZipInputStream zipInputStream, String fileName) throws IOException { - FileOutputStream fileOutputStream = null; - try { - if (importTrackId == -1L) { - return; - } - if (fileName.equals("")) { - return; - } - File dir = FileUtils.getPhotoDir(importTrackId); - FileUtils.ensureDirectoryExists(dir); + if (importTrackId == -1L) { + return; + } + if (fileName.equals("")) { + return; + } + File dir = FileUtils.getPhotoDir(importTrackId); + FileUtils.ensureDirectoryExists(dir); + File file = new File(dir, fileName); - File file = new File(dir, fileName); - fileOutputStream = new FileOutputStream(file); + try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { byte[] buffer = new byte[BUFFER_SIZE]; int count; while ((count = zipInputStream.read(buffer)) != -1) { @@ -189,10 +178,6 @@ public class KmzTrackImporter implements TrackImporter { } FileUtils.updateMediaScanner(context, Uri.fromFile(file)); - } finally { - if (fileOutputStream != null) { - fileOutputStream.close(); - } } } } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index d8b183fb4..100ff0928 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -28,7 +28,7 @@ public interface TrackImporter { * Import a file. * * @param inputStream the file's input stream - * @return the imported track id or -1L. + * @return the imported track id or RECORDING_TRACK_ID_DEFAULT. */ long importFile(InputStream inputStream); } diff --git a/src/main/java/de/dennisguse/opentracks/services/AbsoluteLocationListenerPolicy.java b/src/main/java/de/dennisguse/opentracks/services/AbsoluteLocationListenerPolicy.java index 33d0b561d..bd1460f8b 100644 --- a/src/main/java/de/dennisguse/opentracks/services/AbsoluteLocationListenerPolicy.java +++ b/src/main/java/de/dennisguse/opentracks/services/AbsoluteLocationListenerPolicy.java @@ -17,8 +17,7 @@ package de.dennisguse.opentracks.services; /** - * This is a simple location listener policy that will always dictate the same - * polling interval. + * This is a simple location listener policy that will always dictate the same polling interval. * * @author Sandor Dornbush */ @@ -41,7 +40,7 @@ public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy { } @Override - public int getMinDistance() { + public int getMinDistance_m() { return 0; } diff --git a/src/main/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicy.java b/src/main/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicy.java index 457d75418..3174d5582 100644 --- a/src/main/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicy.java +++ b/src/main/java/de/dennisguse/opentracks/services/AdaptiveLocationListenerPolicy.java @@ -17,53 +17,48 @@ package de.dennisguse.opentracks.services; /** - * A {@link LocationListenerPolicy} that will change based on how long the user - * has been stationary. This policy will dictate a policy based on a min, max - * and idle time. The policy will dictate an interval bounded by min and max, - * and is half of the idle time. + * A {@link LocationListenerPolicy} that will change based on how long the user has been stationary. + * This policy will dictate a policy based on a min, max and idle time. + * The policy will dictate an interval bounded by min and max, and is half of the idle time. * * @author Sandor Dornbush */ public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy { - private final long minInterval; - private final long maxInterval; - private final int minDistance; + private final long minInterval_ms; + private final long maxInterval_ms; + private final int minDistance_m; // The time the user has been idle at the current location, in milliseconds. private long idleTime; /** - * Creates a policy that will be bounded by the given minInterval and - * maxInterval. + * Creates a policy that will be bounded by the given minInterval_ms and maxInterval_ms. * - * @param minInterval the smallest interval this policy will dictate, in - * milliseconds - * @param maxInterval the largest interval this policy will dictate, in - * milliseconds - * @param minDistance the minimum distance in meters + * @param minInterval_ms the smallest interval this policy will dictate + * @param maxInterval_ms the largest interval this policy will dictate + * @param minDistance_m the minimum distance */ - public AdaptiveLocationListenerPolicy(long minInterval, long maxInterval, int minDistance) { - this.minInterval = minInterval; - this.maxInterval = maxInterval; - this.minDistance = minDistance; + public AdaptiveLocationListenerPolicy(long minInterval_ms, long maxInterval_ms, int minDistance_m) { + this.minInterval_ms = minInterval_ms; + this.maxInterval_ms = maxInterval_ms; + this.minDistance_m = minDistance_m; } /* - * Returns an interval half of the idle time, but bounded by minInteval and - * maxInterval. + * Returns an interval half of the idle time, but bounded by minInterval_ms and maxInterval_ms. */ @Override public long getDesiredPollingInterval() { - long desiredInterval = idleTime / 2; + long desiredInterval_ms = idleTime / 2; // Round to second to avoid setting the interval too often - desiredInterval = (desiredInterval / 1000) * 1000; - return Math.max(Math.min(maxInterval, desiredInterval), minInterval); + desiredInterval_ms = (desiredInterval_ms / 1000) * 1000; + return Math.max(Math.min(maxInterval_ms, desiredInterval_ms), minInterval_ms); } @Override - public int getMinDistance() { - return minDistance; + public int getMinDistance_m() { + return minDistance_m; } @Override diff --git a/src/main/java/de/dennisguse/opentracks/services/ControlRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/ControlRecordingService.java index 7272d477f..3f868f655 100644 --- a/src/main/java/de/dennisguse/opentracks/services/ControlRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/ControlRecordingService.java @@ -30,12 +30,10 @@ import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.widgets.TrackWidgetProvider; /** - * A service to control starting and stopping of a recording. This service, - * through the AndroidManifest.xml, is configured to only allow components of - * the same application to invoke it. Thus this service can be used my the - * app widget, {@link TrackWidgetProvider}, but not by other applications. This - * application delegates starting and stopping a recording to - * {@link TrackRecordingService} using RPC calls. + * A service to control starting and stopping of a recording. + * This service, through the AndroidManifest.xml, is configured to only allow components of the same application to invoke it. + * Thus this service can be used by the app widget, {@link TrackWidgetProvider}, but not by other applications. + * This application delegates starting and stopping a recording to {@link TrackRecordingService} using RPC calls. * * @author Jimmy Shih */ @@ -60,9 +58,8 @@ public class ControlRecordingService extends IntentService implements ServiceCon } @VisibleForTesting - @Nullable @Override - public IBinder onBind(Intent intent) { + public IBinder onBind(@Nullable Intent intent) { return new LocalBinder(); } @@ -104,8 +101,7 @@ public class ControlRecordingService extends IntentService implements ServiceCon } /** - * Notifies all threads that connection to {@link TrackRecordingService} is - * available. + * Notifies all threads that connection to {@link TrackRecordingService} is available. */ private synchronized void notifyConnected() { connected = true; @@ -120,7 +116,6 @@ public class ControlRecordingService extends IntentService implements ServiceCon try { wait(); } catch (InterruptedException e) { - // can safely ignore } } @@ -133,7 +128,7 @@ public class ControlRecordingService extends IntentService implements ServiceCon } @VisibleForTesting - public class LocalBinder extends Binder { + class LocalBinder extends Binder { ControlRecordingService getService() { return ControlRecordingService.this; } diff --git a/src/main/java/de/dennisguse/opentracks/services/ITrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/ITrackRecordingService.java index 01411ecd6..862c90514 100644 --- a/src/main/java/de/dennisguse/opentracks/services/ITrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/ITrackRecordingService.java @@ -17,9 +17,10 @@ package de.dennisguse.opentracks.services; import android.location.Location; +import androidx.annotation.VisibleForTesting; + import de.dennisguse.opentracks.content.WaypointCreationRequest; import de.dennisguse.opentracks.content.sensor.SensorDataSet; -import de.dennisguse.opentracks.content.sensor.SensorState; /** * App's service. @@ -97,6 +98,7 @@ public interface ITrackRecordingService { * * @param location the track point to be inserted */ + @VisibleForTesting void insertTrackPoint(Location location); /** @@ -105,11 +107,4 @@ public interface ITrackRecordingService { * @return SensorDataSet object. */ SensorDataSet getSensorData(); - - /** - * Gets the current sensor manager state. - *

    - * return a Sensor.SensorState enum value. - */ - SensorState getSensorState(); } diff --git a/src/main/java/de/dennisguse/opentracks/services/LocationListenerPolicy.java b/src/main/java/de/dennisguse/opentracks/services/LocationListenerPolicy.java index e2fd9969f..0158dc79d 100644 --- a/src/main/java/de/dennisguse/opentracks/services/LocationListenerPolicy.java +++ b/src/main/java/de/dennisguse/opentracks/services/LocationListenerPolicy.java @@ -17,9 +17,7 @@ package de.dennisguse.opentracks.services; /** - * This is an interface for classes that will manage the location listener - * policy. Different policy options are: {@link AbsoluteLocationListenerPolicy} - * and {@link AdaptiveLocationListenerPolicy}. + * This is an interface for classes that will manage the location listener policy. * * @author Sandor Dornbush */ @@ -35,13 +33,12 @@ public interface LocationListenerPolicy { /** * Returns the minimum distance between updates. */ - int getMinDistance(); + int getMinDistance_m(); /** * Notifies the amount of time the user has been idle at his current location. * - * @param idleTime the time that the user has been idle at his current - * location + * @param idleTime the time that the user has been idle at his current location */ void updateIdleTime(long idleTime); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 10439eaa3..668e01bd3 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -57,7 +57,6 @@ import de.dennisguse.opentracks.content.Waypoint; import de.dennisguse.opentracks.content.Waypoint.WaypointType; import de.dennisguse.opentracks.content.WaypointCreationRequest; import de.dennisguse.opentracks.content.sensor.SensorDataSet; -import de.dennisguse.opentracks.content.sensor.SensorState; import de.dennisguse.opentracks.services.sensors.RemoteSensorManager; import de.dennisguse.opentracks.services.sensors.RemoteSensorManagerFactory; import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory; @@ -947,7 +946,7 @@ public class TrackRecordingService extends Service { } try { long interval = locationListenerPolicy.getDesiredPollingInterval(); - locationManagerConnector.requestLocationUpdates(interval, locationListenerPolicy.getMinDistance(), locationListener); + locationManagerConnector.requestLocationUpdates(interval, locationListenerPolicy.getMinDistance_m(), locationListener); currentRecordingInterval = interval; } catch (RuntimeException e) { Log.e(TAG, "Could not register location listener.", e); @@ -1116,15 +1115,6 @@ public class TrackRecordingService extends Service { return trackRecordingService.remoteSensorManager.getSensorDataSet(); } - @Override - public SensorState getSensorState() { - if (trackRecordingService.remoteSensorManager == null) { - Log.d(TAG, "remoteSensorManager is null."); - return SensorState.NONE; - } - return trackRecordingService.remoteSensorManager.getSensorState(); - } - /** * Detaches from the track recording service. Clears the reference to the * outer class to minimize the leak. diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java index e0572e840..86b76ffca 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java @@ -25,12 +25,13 @@ import android.os.IBinder.DeathRecipient; import android.os.RemoteException; import android.util.Log; -import de.dennisguse.opentracks.util.TrackRecordingServiceConnectionUtils; import de.dennisguse.opentracks.BuildConfig; +import de.dennisguse.opentracks.util.TrackRecordingServiceConnectionUtils; /** - * Wrapper for the track recording service. This handles service - * start/bind/unbind/stop. The service must be started before it can be bound. + * Wrapper for the track recording service. + * This handles service start/bind/unbind/stop. + * The service must be started before it can be bound. * Returns the service if it is started and bound. * * @author Rodrigo Damazio @@ -38,8 +39,10 @@ import de.dennisguse.opentracks.BuildConfig; public class TrackRecordingServiceConnection { private static final String TAG = TrackRecordingServiceConnection.class.getSimpleName(); + private final Context context; private final Runnable callback; + private ITrackRecordingService trackRecordingService; private final DeathRecipient deathRecipient = new DeathRecipient() { @Override @@ -48,6 +51,7 @@ public class TrackRecordingServiceConnection { setTrackRecordingService(null); } }; + private final ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { @@ -130,8 +134,7 @@ public class TrackRecordingServiceConnection { return; } - if (!startIfNeeded - && !TrackRecordingServiceConnectionUtils.isRecordingServiceRunning(context)) { + if (!startIfNeeded && !TrackRecordingServiceConnectionUtils.isRecordingServiceRunning(context)) { Log.d(TAG, "Service is not started. Not binding it."); return; } diff --git a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothConnectionManager.java b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothConnectionManager.java index 560f2ac58..3f534773b 100644 --- a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothConnectionManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothConnectionManager.java @@ -30,11 +30,11 @@ import android.util.Log; import androidx.annotation.NonNull; +import java.util.UUID; + import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorState; -import java.util.UUID; - /** * Manages connection to Bluetooth LE heart rate monitor. * TODO: shutdown connection. @@ -42,16 +42,20 @@ import java.util.UUID; public class BluetoothConnectionManager { // Message types sent to handler - public static final int MESSAGE_DEVICE_NAME = 1; - public static final int MESSAGE_READ = 2; - public static final String KEY_DEVICE_NAME = "device_name"; + static final int MESSAGE_DEVICE_NAME = 1; + static final int MESSAGE_READ = 2; + + static final String KEY_DEVICE_NAME = "device_name"; + private static final UUID HEART_RATE_SERVICE_UUID = new UUID(0x180D00001000L, 0x800000805f9b34fbL); private static final UUID HEART_RATE_MEASUREMENT_CHAR_UUID = new UUID(0x2A3700001000L, 0x800000805f9b34fbL); private static final UUID CLIENT_CHARACTERISTIC_CONFIG_UUID = new UUID(0x290200001000L, 0x800000805f9b34fbL); + private static final String TAG = BluetoothConnectionManager.class.getSimpleName(); private final Context context; private final Handler handler; + private SensorState sensorState; private BluetoothGattCallback connectCallback = new BluetoothGattCallback() { @@ -100,7 +104,7 @@ public class BluetoothConnectionManager { * * @param handler a handler for sending messages back to the UI activity */ - public BluetoothConnectionManager(Context context, Handler handler) { + BluetoothConnectionManager(Context context, Handler handler) { this.context = context; this.handler = handler; this.sensorState = SensorState.NONE; @@ -109,7 +113,7 @@ public class BluetoothConnectionManager { /** * Gets the sensor state. */ - public synchronized SensorState getSensorState() { + synchronized SensorState getSensorState() { return sensorState; } diff --git a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothLEUtils.java b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothLEUtils.java index c024c0e45..163e6fc7e 100644 --- a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothLEUtils.java +++ b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothLEUtils.java @@ -2,12 +2,12 @@ package de.dennisguse.opentracks.services.sensors; import android.bluetooth.BluetoothGattCharacteristic; -public final class BluetoothLEUtils { +final class BluetoothLEUtils { private BluetoothLEUtils() { } - public static int parseHeartRate(BluetoothGattCharacteristic characteristic) { + static int parseHeartRate(BluetoothGattCharacteristic characteristic) { //DOCUMENTATION https://www.bluetooth.com/specifications/gatt/characteristics/ byte[] raw = characteristic.getValue(); int index = ((raw[0] & 0x1) == 1) ? 2 : 1; diff --git a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothRemoteSensorManager.java b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothRemoteSensorManager.java index c93815aaf..4052fa083 100644 --- a/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothRemoteSensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/sensors/BluetoothRemoteSensorManager.java @@ -34,7 +34,6 @@ import de.dennisguse.opentracks.util.UnitConversions; /** * Bluetooth sensor manager. - *

    * TODO: Handle a BluetoothGatt.STATE_DISCONNECTED * * @author Sandor Dornbush @@ -42,10 +41,15 @@ import de.dennisguse.opentracks.util.UnitConversions; public class BluetoothRemoteSensorManager extends RemoteSensorManager { private static final String TAG = BluetoothConnectionManager.class.getSimpleName(); + private static final BluetoothAdapter bluetoothAdapter = getDefaultBluetoothAdapter(); + private final Context context; + private final BluetoothConnectionManager bluetoothConnectionManager; + private SensorDataSet sensorDataSet = null; + // Handler that gets information back from the bluetoothConnectionManager private final Handler messageHandler = new Handler(Looper.getMainLooper()) { @Override @@ -71,7 +75,7 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager { /** * @param context the context */ - public BluetoothRemoteSensorManager(Context context) { + BluetoothRemoteSensorManager(Context context) { this.context = context; bluetoothConnectionManager = new BluetoothConnectionManager(context, messageHandler); } @@ -109,7 +113,6 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager { if (adapters.get(0) == null) { Log.w(TAG, "No bluetooth adapter found."); - return null; } return adapters.get(0); } @@ -125,6 +128,7 @@ public class BluetoothRemoteSensorManager extends RemoteSensorManager { Log.w(TAG, "Bluetooth not enabled."); return; } + String address = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT); if (PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(address)) { Log.w(TAG, "No bluetooth address."); diff --git a/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManager.java b/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManager.java index fe9614e88..fcc34a463 100644 --- a/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManager.java @@ -78,13 +78,10 @@ public abstract class RemoteSensorManager { setUpChannel(); } break; - case NONE: case DISCONNECTED: setUpChannel(); break; - default: - // CONNECTED or SENDING - break; + default: // NONE, CONNECTED or SENDING } } }; diff --git a/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManagerFactory.java b/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManagerFactory.java index cd7320284..10c2cc1ff 100644 --- a/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManagerFactory.java +++ b/src/main/java/de/dennisguse/opentracks/services/sensors/RemoteSensorManagerFactory.java @@ -26,6 +26,8 @@ import android.content.Context; public class RemoteSensorManagerFactory { private static RemoteSensorManager remoteSensorManagerSystem = null; + + //TODO Check if still needed? Is there a missing features? private static RemoteSensorManager remoteSensorManagerTemporary = null; private RemoteSensorManagerFactory() { @@ -70,7 +72,7 @@ public class RemoteSensorManagerFactory { /** * Releases the temp sensor manager. */ - public static void releaseSensorManagerTemporary() { + private static void releaseSensorManagerTemporary() { if (remoteSensorManagerTemporary != null) { remoteSensorManagerTemporary.stopSensor(); } diff --git a/src/main/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTask.java b/src/main/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTask.java index b6909fffc..e4d0c7ddb 100644 --- a/src/main/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTask.java +++ b/src/main/java/de/dennisguse/opentracks/services/tasks/AnnouncementPeriodicTask.java @@ -27,14 +27,14 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; +import java.util.Locale; + +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.stats.TripStatistics; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.UnitConversions; -import de.dennisguse.opentracks.R; - -import java.util.Locale; /** * This class will periodically announce the user's trip statistics. @@ -50,7 +50,9 @@ public class AnnouncementPeriodicTask implements PeriodicTask { static final float TTS_SPEECH_RATE = 0.9f; private static final String TAG = AnnouncementPeriodicTask.class.getSimpleName(); + private final Context context; + private final AudioManager audioManager; private final UtteranceProgressListener utteranceListener = new UtteranceProgressListener() { @Override @@ -69,13 +71,16 @@ public class AnnouncementPeriodicTask implements PeriodicTask { public void onError(String utteranceId) { } }; + private TextToSpeech tts; // Response from TTS after its initialization private int initStatus = TextToSpeech.ERROR; - // True if TTS engine is ready - private boolean ready = false; + + private boolean ttsReady = false; + // True if speech is allowed private boolean speechAllowed; + /** * Listener which updates {@link #speechAllowed} when the phone state changes. */ @@ -90,7 +95,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask { } }; - public AnnouncementPeriodicTask(Context context) { + AnnouncementPeriodicTask(Context context) { this.context = context; audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); } @@ -131,13 +136,13 @@ public class AnnouncementPeriodicTask implements PeriodicTask { } synchronized (this) { - if (!ready) { - ready = initStatus == TextToSpeech.SUCCESS; - if (ready) { + if (!ttsReady) { + ttsReady = initStatus == TextToSpeech.SUCCESS; + if (ttsReady) { onTtsReady(); } } - if (!ready) { + if (!ttsReady) { Log.i(TAG, "TTS not ready."); return; } @@ -170,9 +175,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask { Log.w(TAG, "Default locale not available, use English."); locale = Locale.ENGLISH; /* - * TODO: instead of using english, load the language if missing and show a - * toast if not supported. Not able to change the resource strings to - * English. + * TODO: instead of using english, load the language if missing and show a toast if not supported. + * Not able to change the resource strings to English. */ } tts.setLanguage(locale); @@ -189,8 +193,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask { * @param announcement the announcement */ private void speakAnnouncement(String announcement) { - int result = audioManager.requestAudioFocus( - null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); + int result = audioManager.requestAudioFocus(null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) { Log.w(TAG, "Failed to request audio focus."); } @@ -223,7 +226,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask { boolean metricUnits = PreferencesUtils.isMetricUnits(context); boolean reportSpeed = PreferencesUtils.isReportSpeed(context); double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM; - double speed = tripStatistics.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH; + double distancePerTime = tripStatistics.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH; if (distance == 0) { return context.getString(R.string.voice_total_distance_zero); @@ -231,26 +234,22 @@ public class AnnouncementPeriodicTask implements PeriodicTask { if (!metricUnits) { distance *= UnitConversions.KM_TO_MI; - speed *= UnitConversions.KM_TO_MI; + distancePerTime *= UnitConversions.KM_TO_MI; } String rate; if (reportSpeed) { - int speedId = metricUnits ? R.plurals.voiceSpeedKilometersPerHour - : R.plurals.voiceSpeedMilesPerHour; - rate = context.getResources().getQuantityString(speedId, getQuantityCount(speed), speed); + int speedId = metricUnits ? R.plurals.voiceSpeedKilometersPerHour : R.plurals.voiceSpeedMilesPerHour; + rate = context.getResources().getQuantityString(speedId, getQuantityCount(distancePerTime), distancePerTime); } else { - speed = speed == 0 ? 0.0 : 1 / speed; + double timePerDistance = distancePerTime == 0 ? 0.0 : 1 / distancePerTime; int paceId = metricUnits ? R.string.voice_pace_per_kilometer : R.string.voice_pace_per_mile; - long time = Math.round( - speed * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS); + long time = Math.round(timePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS); rate = context.getString(paceId, getAnnounceTime(time)); } - int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers - : R.plurals.voiceTotalDistanceMiles; - String totalDistance = context.getResources() - .getQuantityString(totalDistanceId, getQuantityCount(distance), distance); + int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers : R.plurals.voiceTotalDistanceMiles; + String totalDistance = context.getResources().getQuantityString(totalDistanceId, getQuantityCount(distance), distance); return context.getString(R.string.voice_template, totalDistance, getAnnounceTime(tripStatistics.getMovingTime()), rate); @@ -264,8 +263,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask { */ @VisibleForTesting protected void listenToPhoneState(PhoneStateListener listener, int events) { - TelephonyManager telephony = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); + TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (telephony != null) { telephony.listen(listener, events); } @@ -297,15 +295,13 @@ public class AnnouncementPeriodicTask implements PeriodicTask { } /** - * Gets the plural count to be used by getQuantityString. getQuantityString - * only supports integer quantities, not a double quantity like "2.2". + * Gets the plural count to be used by getQuantityString. + * getQuantityString only supports integer quantities, not a double quantity like "2.2". *

    - * As a temporary workaround, we convert a double quantity to an integer - * quantity. If the double quantity is exactly 0, 1, or 2, then we can return - * these integer quantities. Otherwise, we cast the double quantity to an - * integer quantity. However, we need to make sure that if the casted value is - * 0, 1, or 2, we don't return those, instead, return the next biggest integer - * 3. + * As a temporary workaround, we convert a double quantity to an integer quantity. + * If the double quantity is exactly 0, 1, or 2, then we can return these integer quantities. + * Otherwise, we cast the double quantity to an integer quantity. + * However, we need to make sure that if the casted value is 0, 1, or 2, we don't return those, instead, return the next biggest integer 3. * * @param d the double value */ @@ -317,6 +313,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask { } else if (d == 2) { return 2; } else { + //TODO This seems weird; why not use Math.round(d) or Math.ceil()? int count = (int) d; return count < 3 ? 3 : count; } diff --git a/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTask.java b/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTask.java index 83b540a39..64395614e 100644 --- a/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTask.java +++ b/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTask.java @@ -24,6 +24,7 @@ import de.dennisguse.opentracks.services.TrackRecordingService; * @author Sandor Dornbush */ public interface PeriodicTask { + /** * Sets up this task for subsequent calls to the run method. */ diff --git a/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTaskExecutor.java b/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTaskExecutor.java index 3c97362df..33ae873c1 100644 --- a/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTaskExecutor.java +++ b/src/main/java/de/dennisguse/opentracks/services/tasks/PeriodicTaskExecutor.java @@ -36,9 +36,10 @@ public class PeriodicTaskExecutor { private final PeriodicTaskFactory periodicTaskFactory; /** - * The task frequency. A positive value is a time frequency (minutes). A - * negative value is a distance frequency (km or mi). A zero value is to turn - * off periodic task. + * The task frequency. + * A positive value is a time frequency (minutes). + * A negative value is a distance frequency (km or mi). + * A zero value is to turn off periodic task. */ private int taskFrequency = PreferencesUtils.FREQUENCY_OFF; @@ -52,8 +53,7 @@ public class PeriodicTaskExecutor { // The next distance for the distance periodic task private double nextTaskDistance = Double.MAX_VALUE; - public PeriodicTaskExecutor( - TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) { + public PeriodicTaskExecutor(TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) { this.trackRecordingService = trackRecordingService; this.periodicTaskFactory = periodicTaskFactory; } @@ -67,11 +67,9 @@ public class PeriodicTaskExecutor { return; } - if (!isTimeFrequency()) { - if (timerTaskExecutor != null) { - timerTaskExecutor.shutdown(); - timerTaskExecutor = null; - } + if (!isTimeFrequency() && timerTaskExecutor != null) { + timerTaskExecutor.shutdown(); + timerTaskExecutor = null; } if (taskFrequency == PreferencesUtils.FREQUENCY_OFF) { Log.d(TAG, "Task frequency is off."); @@ -119,12 +117,13 @@ public class PeriodicTaskExecutor { if (!isDistanceFrequency() || periodicTask == null) { return; } + TripStatistics tripStatistics = trackRecordingService.getTripStatistics(); if (tripStatistics == null) { return; } - double distance = tripStatistics.getTotalDistance() - * UnitConversions.M_TO_KM; + + double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM; if (!metricUnits) { distance *= UnitConversions.KM_TO_MI; } @@ -159,8 +158,7 @@ public class PeriodicTaskExecutor { * Calculates the next distance for the distance periodic task. */ private void calculateNextTaskDistance() { - if (!trackRecordingService.isRecording() || trackRecordingService.isPaused() - || periodicTask == null) { + if (!trackRecordingService.isRecording() || trackRecordingService.isPaused() || periodicTask == null) { return; } @@ -175,11 +173,11 @@ public class PeriodicTaskExecutor { return; } - double distance = tripStatistics.getTotalDistance() - * UnitConversions.M_TO_KM; + double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM; if (!metricUnits) { distance *= UnitConversions.KM_TO_MI; } + // The index will be negative since the frequency is negative. int index = (int) (distance / taskFrequency); index -= 1; diff --git a/src/main/java/de/dennisguse/opentracks/services/tasks/TimerTaskExecutor.java b/src/main/java/de/dennisguse/opentracks/services/tasks/TimerTaskExecutor.java index c257e02a7..f5d53fd5c 100644 --- a/src/main/java/de/dennisguse/opentracks/services/tasks/TimerTaskExecutor.java +++ b/src/main/java/de/dennisguse/opentracks/services/tasks/TimerTaskExecutor.java @@ -16,19 +16,19 @@ package de.dennisguse.opentracks.services.tasks; -import de.dennisguse.opentracks.services.TrackRecordingService; -import de.dennisguse.opentracks.stats.TripStatistics; - import java.util.Date; import java.util.Timer; import java.util.TimerTask; +import de.dennisguse.opentracks.services.TrackRecordingService; +import de.dennisguse.opentracks.stats.TripStatistics; + /** * This class will periodically perform a task. * * @author Sandor Dornbush */ -public class TimerTaskExecutor { +class TimerTaskExecutor { private final PeriodicTask periodicTask; private final TrackRecordingService trackRecordingService; @@ -42,12 +42,12 @@ public class TimerTaskExecutor { } /** - * Schedules the periodic task at an interval. + * Schedules the periodic task in milliseconds. * - * @param interval the interval in milliseconds + * @param interval_ms the interval_ms */ - public void scheduleTask(long interval) { - if (interval <= 0) { + void scheduleTask(long interval_ms) { + if (interval_ms <= 0) { return; } @@ -69,14 +69,11 @@ public class TimerTaskExecutor { } }; timer = new Timer(TimerTaskExecutor.class.getSimpleName()); - long next = System.currentTimeMillis() + interval - (tripStatistics.getTotalTime() % interval); - timer.scheduleAtFixedRate(timerTask, new Date(next), interval); + long next = System.currentTimeMillis() + interval_ms - (tripStatistics.getTotalTime() % interval_ms); + timer.scheduleAtFixedRate(timerTask, new Date(next), interval_ms); } - /** - * Shuts down. - */ - public void shutdown() { + void shutdown() { if (timerTask != null) { timerTask.cancel(); timerTask = null; diff --git a/src/main/java/de/dennisguse/opentracks/settings/ActivityTypePreference.java b/src/main/java/de/dennisguse/opentracks/settings/ActivityTypePreference.java index ad6977d56..50757e7ea 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/ActivityTypePreference.java +++ b/src/main/java/de/dennisguse/opentracks/settings/ActivityTypePreference.java @@ -77,8 +77,7 @@ public class ActivityTypePreference extends DialogPreference { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { - String iconValue = TrackIconUtils.getIconValue( - getContext(), textView.getText().toString()); + String iconValue = TrackIconUtils.getIconValue(getContext(), textView.getText().toString()); TrackIconUtils.setIconSpinner(spinner, iconValue); } } @@ -136,7 +135,7 @@ public class ActivityTypePreference extends DialogPreference { * * @param activity the activity */ - public void setRecordingSettingsActivity(RecordingSettingsActivity activity) { + void setRecordingSettingsActivity(RecordingSettingsActivity activity) { recordingSettingsActivity = activity; } @@ -145,10 +144,9 @@ public class ActivityTypePreference extends DialogPreference { * * @param iconValue the icon value */ - public void updateValue(String iconValue) { + void updateValue(String iconValue) { TrackIconUtils.setIconSpinner(spinner, iconValue); - textView.setText( - recordingSettingsActivity.getString(TrackIconUtils.getIconActivityType(iconValue))); + textView.setText(recordingSettingsActivity.getString(TrackIconUtils.getIconActivityType(iconValue))); textView.clearFocus(); } } diff --git a/src/main/java/de/dennisguse/opentracks/settings/RecordingSettingsActivity.java b/src/main/java/de/dennisguse/opentracks/settings/RecordingSettingsActivity.java index 1278f6772..327d9ce75 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/RecordingSettingsActivity.java +++ b/src/main/java/de/dennisguse/opentracks/settings/RecordingSettingsActivity.java @@ -22,20 +22,19 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.UnitConversions; -import de.dennisguse.opentracks.R; /** * An activity for accessing recording settings. * * @author Jimmy Shih */ -public class RecordingSettingsActivity extends PreferenceActivity - implements ChooseActivityTypeCaller { +public class RecordingSettingsActivity extends PreferenceActivity implements ChooseActivityTypeCaller { private static final int DIALOG_CHOOSE_ACTIVITY = 0; @@ -51,13 +50,10 @@ public class RecordingSettingsActivity extends PreferenceActivity configFrequencyPreference(R.string.voice_frequency_key, metricUnits); configFrequencyPreference(R.string.split_frequency_key, metricUnits); configDefaultActivity(); - configListPreference(R.string.min_recording_interval_key, R.array.min_recording_interval_values, - metricUnits); + configListPreference(R.string.min_recording_interval_key, R.array.min_recording_interval_values, metricUnits); configListPreference(R.string.recording_distance_interval_key, R.array.recording_distance_interval_values, metricUnits); - configListPreference(R.string.max_recording_distance_key, R.array.max_recording_distance_values, - metricUnits); - configListPreference(R.string.recording_gps_accuracy_key, R.array.recording_gps_accuracy_values, - metricUnits); + configListPreference(R.string.max_recording_distance_key, R.array.max_recording_distance_values, metricUnits); + configListPreference(R.string.recording_gps_accuracy_key, R.array.recording_gps_accuracy_values, metricUnits); configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits); } @@ -80,31 +76,25 @@ public class RecordingSettingsActivity extends PreferenceActivity } private void configDefaultActivity() { - activityTypePreference = (ActivityTypePreference) findPreference( - getString(R.string.default_activity_key)); + activityTypePreference = (ActivityTypePreference) findPreference(getString(R.string.default_activity_key)); String defaultActivity = PreferencesUtils.getString( this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT); - activityTypePreference.setOnPreferenceChangeListener( - new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference pref, Object newValue) { - String stringValue = (String) newValue; - pref.setSummary(stringValue != null - && !stringValue.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? stringValue - : getString(R.string.value_unknown)); - return true; - } - }); - activityTypePreference.setSummary(defaultActivity != null - && !defaultActivity.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? defaultActivity - : getString(R.string.value_unknown)); + activityTypePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference pref, Object newValue) { + String stringValue = (String) newValue; + pref.setSummary(stringValue != null && !stringValue.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? stringValue : getString(R.string.value_unknown)); + return true; + } + }); + activityTypePreference.setSummary(defaultActivity != null && !defaultActivity.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? defaultActivity : getString(R.string.value_unknown)); activityTypePreference.setRecordingSettingsActivity(this); } private void configListPreference(int key, int valueArray, boolean metricUnits) { ListPreference preference = (ListPreference) findPreference(getString(key)); - @Deprecated + @Deprecated //TODO Can we make values an int array? String[] values = getResources().getStringArray(valueArray); String[] options = new String[values.length]; switch (key) { diff --git a/src/main/java/de/dennisguse/opentracks/settings/StatsSettingsActivity.java b/src/main/java/de/dennisguse/opentracks/settings/StatsSettingsActivity.java index 97890cd4a..ae6b7024b 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/StatsSettingsActivity.java +++ b/src/main/java/de/dennisguse/opentracks/settings/StatsSettingsActivity.java @@ -59,10 +59,7 @@ public class StatsSettingsActivity extends PreferenceActivity { listPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference pref, Object newValue) { - if (listener != null) { - listener.onPreferenceChange(pref, newValue); - } - return true; + return listener.onPreferenceChange(pref, newValue); } }); } diff --git a/src/main/java/de/dennisguse/opentracks/stats/DoubleBuffer.java b/src/main/java/de/dennisguse/opentracks/stats/DoubleBuffer.java index 3cbd26f59..c813b80b3 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/DoubleBuffer.java +++ b/src/main/java/de/dennisguse/opentracks/stats/DoubleBuffer.java @@ -19,9 +19,9 @@ package de.dennisguse.opentracks.stats; import androidx.annotation.NonNull; /** - * This class maintains a buffer of doubles. This buffer is a convenient class - * for storing a series of doubles and calculating information about them. This - * is a FIFO buffer. + * This class maintains a buffer of doubles. + * This buffer is a convenient class for storing a series of doubles and calculating information about them. + * This is a FIFO buffer. * * @author Sandor Dornbush */ @@ -29,8 +29,10 @@ public class DoubleBuffer { // The sliding buffer of doubles. private final double[] buffer; + // The location that the next write will occur at. private int index; + // True if the buffer is full private boolean isFull; @@ -39,7 +41,7 @@ public class DoubleBuffer { * * @param size the size */ - public DoubleBuffer(int size) { + DoubleBuffer(int size) { if (size < 1) { throw new IllegalArgumentException("The buffer size must be greater than 1."); } @@ -58,7 +60,7 @@ public class DoubleBuffer { /** * Returns true if the buffer is full. */ - public boolean isFull() { + boolean isFull() { return isFull; } @@ -78,8 +80,8 @@ public class DoubleBuffer { } /** - * Adds a double to the buffer. If the buffer is full the oldest element is - * overwritten. + * Adds a double to the buffer. + * If the buffer is full the oldest element is overwritten. * * @param value the double to add */ diff --git a/src/main/java/de/dennisguse/opentracks/stats/TripStatistics.java b/src/main/java/de/dennisguse/opentracks/stats/TripStatistics.java index d70e00fd9..3f25bbeaf 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/TripStatistics.java +++ b/src/main/java/de/dennisguse/opentracks/stats/TripStatistics.java @@ -35,6 +35,7 @@ public class TripStatistics implements Parcelable { * Creator of {@link TripStatistics} from parcels. */ public static final Creator CREATOR = new Creator(); + // The min and max latitude seen in this trip. private final ExtremityMonitor latitudeExtremities = new ExtremityMonitor(); // The min and max longitude seen in this trip. @@ -43,6 +44,7 @@ public class TripStatistics implements Parcelable { private final ExtremityMonitor elevationExtremities = new ExtremityMonitor(); // The min and max grade seen on this trip. private final ExtremityMonitor gradeExtremities = new ExtremityMonitor(); + // The trip start time. This is the system time, might not match the GPs time. private long startTime = -1L; // The trip stop time. This is the system time, might not match the GPS time. @@ -173,10 +175,9 @@ public class TripStatistics implements Parcelable { } /** - * Gets the total time in milliseconds that this track has been active. This - * statistic is only updated when a new point is added to the statistics, so - * it may be off. If you need to calculate the proper total time, use - * {@link #getStartTime} with the current time. + * Gets the total time in milliseconds that this track has been active. + * This statistic is only updated when a new point is added to the statistics, so it may be off. + * If you need to calculate the proper total time, use {@link #getStartTime} with the current time. */ public long getTotalTime() { return totalTime; @@ -217,16 +218,14 @@ public class TripStatistics implements Parcelable { } /** - * Gets the topmost position (highest latitude) of the track, in signed - * degrees. + * Gets the topmost position (highest latitude) of the track, in signed degrees. */ public double getTopDegrees() { return latitudeExtremities.getMax(); } /** - * Gets the topmost position (highest latitude) of the track, in signed - * millions of degrees. + * Gets the topmost position (highest latitude) of the track, in signed millions of degrees. */ public int getTop() { return (int) (latitudeExtremities.getMax() * 1E6); @@ -241,40 +240,35 @@ public class TripStatistics implements Parcelable { } /** - * Gets the bottommost position (lowest latitude) of the track, in signed - * millions of degrees. + * Gets the bottommost position (lowest latitude) of the track, in signed millions of degrees. */ public int getBottom() { return (int) (latitudeExtremities.getMin() * 1E6); } /** - * Gets the leftmost position (lowest longitude) of the track, in signed - * degrees. + * Gets the leftmost position (lowest longitude) of the track, in signed degrees. */ public double getLeftDegrees() { return longitudeExtremities.getMin(); } /** - * Gets the leftmost position (lowest longitude) of the track, in signed - * millions of degrees. + * Gets the leftmost position (lowest longitude) of the track, in signed millions of degrees. */ public int getLeft() { return (int) (longitudeExtremities.getMin() * 1E6); } /** - * Gets the rightmost position (highest longitude) of the track, in signed - * degrees. + * Gets the rightmost position (highest longitude) of the track, in signed degrees. */ public double getRightDegrees() { return longitudeExtremities.getMax(); } /** - * Gets the rightmost position (highest longitude) of the track, in signed - * millions of degrees. + * Gets the rightmost position (highest longitude) of the track, in signed millions of degrees. */ public int getRight() { return (int) (longitudeExtremities.getMax() * 1E6); @@ -327,9 +321,8 @@ public class TripStatistics implements Parcelable { } /** - * Gets the average speed in meters/second. This calculation only takes into - * account the displacement until the last point that was accounted for in - * statistics. + * Gets the average speed in meters/second. + * This calculation only takes into account the displacement until the last point that was accounted for in statistics. */ public double getAverageSpeed() { if (totalTime == 0L) { @@ -365,8 +358,8 @@ public class TripStatistics implements Parcelable { } /** - * Gets the minimum elevation. This is calculated from the smoothed elevation - * so this can actually be more than the current elevation. + * Gets the minimum elevation. + * This is calculated from the smoothed elevation, so this can actually be more than the current elevation. */ public double getMinElevation() { return elevationExtremities.getMin(); @@ -382,8 +375,8 @@ public class TripStatistics implements Parcelable { } /** - * Gets the maximum elevation. This is calculated from the smoothed elevation - * so this can actually be less than the current elevation. + * Gets the maximum elevation. + * This is calculated from the smoothed elevation, so this can actually be less than the current elevation. */ public double getMaxElevation() { return elevationExtremities.getMax(); @@ -408,8 +401,7 @@ public class TripStatistics implements Parcelable { } /** - * Gets the total elevation gain in meters. This is calculated as the sum of - * all positive differences in the smoothed elevation. + * Gets the total elevation gain in meters. This is calculated as the sum of all positive differences in the smoothed elevation. */ public double getTotalElevationGain() { return totalElevationGain; diff --git a/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java index ce2d39be1..ea3c38648 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/TripStatisticsUpdater.java @@ -27,9 +27,9 @@ import static de.dennisguse.opentracks.services.TrackRecordingService.MAX_NO_MOV import static de.dennisguse.opentracks.services.TrackRecordingService.PAUSE_LATITUDE; /** - * Updater for {@link TripStatistics}. For updating track trip statistics as new - * locations are added. Note that some of the locations represent pause/resume - * separator. + * Updater for {@link TripStatistics}. + * For updating track trip statistics as new locations are added. + * NOTE:Some of the locations represent pause/resume separator. * * @author Sandor Dornbush * @author Rodrigo Damazio @@ -45,28 +45,30 @@ public class TripStatisticsUpdater { * signal. */ @VisibleForTesting - static final int ELEVATION_SMOOTHING_FACTOR = 25; + private static final int ELEVATION_SMOOTHING_FACTOR = 25; /** * The number of run readings to smooth for calculating grade. */ @VisibleForTesting - static final int RUN_SMOOTHING_FACTOR = 25; + private static final int RUN_SMOOTHING_FACTOR = 25; /** * The number of speed reading to smooth to get a somewhat accurate signal. */ @VisibleForTesting - static final int SPEED_SMOOTHING_FACTOR = 25; + private static final int SPEED_SMOOTHING_FACTOR = 25; + private static final String TAG = TripStatisticsUpdater.class.getSimpleName(); /** - * Ignore any acceleration faster than this. Will ignore any speeds that imply - * acceleration greater than 2g's 2g = 19.6 m/s^2 = 0.0002 m/ms^2 = 0.02 - * m/(m*ms) + * Ignore any acceleration faster than this. + * Will ignore any speeds that imply acceleration greater than 2g's + * 2g = 19.6 m/s^2 = 0.0002 m/ms^2 = 0.02 m/(m*ms) */ private static final double MAX_ACCELERATION = 0.02; // The track's trip statistics private final TripStatistics tripStatistics; + // A buffer of the recent elevation readings (m) private final DoubleBuffer elevationBuffer = new DoubleBuffer(ELEVATION_SMOOTHING_FACTOR); // A buffer of the recent run readings (m) for calculating grade @@ -75,6 +77,7 @@ public class TripStatisticsUpdater { private final DoubleBuffer gradeBuffer = new DoubleBuffer(GRADE_SMOOTHING_FACTOR); // A buffer of the recent speed readings (m/s) for calculating max speed private final DoubleBuffer speedBuffer = new DoubleBuffer(SPEED_SMOOTHING_FACTOR); + // The current segment's trip statistics private TripStatistics currentSegment; // Current segment's last location. @@ -108,7 +111,8 @@ public class TripStatisticsUpdater { } /** - * Adds a location. TODO: This assume location has a valid time. + * Adds a location. + * TODO: This assume location has a valid time. * * @param location the location * @param minRecordingDistance the min recording distance @@ -119,8 +123,7 @@ public class TripStatisticsUpdater { if (!LocationUtils.isValidLocation(location)) { // Either pause or resume marker if (location.getLatitude() == PAUSE_LATITUDE) { - if (lastLocation != null && lastMovingLocation != null - && lastLocation != lastMovingLocation) { + if (lastLocation != null && lastMovingLocation != null && lastLocation != lastMovingLocation) { currentSegment.addTotalDistance(lastMovingLocation.distanceTo(lastLocation)); } tripStatistics.merge(currentSegment); @@ -134,11 +137,12 @@ public class TripStatisticsUpdater { speedBuffer.reset(); return; } + currentSegment.updateLatitudeExtremities(location.getLatitude()); currentSegment.updateLongitudeExtremities(location.getLongitude()); - double elevationDifference = location.hasAltitude() ? updateElevation(location.getAltitude()) - : 0.0; + //TODO Use Barometer to compute elevation gain. + double elevationDifference = location.hasAltitude() ? updateElevation(location.getAltitude()) : 0.0; if (lastLocation == null || lastMovingLocation == null) { lastLocation = location; @@ -147,8 +151,7 @@ public class TripStatisticsUpdater { } double movingDistance = lastMovingLocation.distanceTo(location); - if (movingDistance < minRecordingDistance - && (!location.hasSpeed() || location.getSpeed() < MAX_NO_MOVEMENT_SPEED)) { + if (movingDistance < minRecordingDistance && (!location.hasSpeed() || location.getSpeed() < MAX_NO_MOVEMENT_SPEED)) { speedBuffer.reset(); lastLocation = location; return; @@ -171,8 +174,7 @@ public class TripStatisticsUpdater { // Update max speed if (location.hasSpeed() && lastLocation.hasSpeed()) { - updateSpeed( - location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed()); + updateSpeed(location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed()); } lastLocation = location; @@ -180,9 +182,8 @@ public class TripStatisticsUpdater { } /** - * Gets the smoothed elevation over several readings. The elevation readings - * is noisy so the smoothed elevation is better than the raw elevation for - * many tasks. + * Gets the smoothed elevation over several readings. + * The elevation readings is noisy so the smoothed elevation is better than the raw elevation for many tasks. */ public double getSmoothedElevation() { return elevationBuffer.getAverage(); @@ -193,7 +194,7 @@ public class TripStatisticsUpdater { } /** - * Updates a speed reading. Assumes the user is moving. + * Updates a speed reading while assuming the user is moving. * * @param time the time * @param speed the speed @@ -201,7 +202,7 @@ public class TripStatisticsUpdater { * @param lastLocationSpeed the last location speed */ @VisibleForTesting - void updateSpeed(long time, double speed, long lastLocationTime, double lastLocationSpeed) { + private void updateSpeed(long time, double speed, long lastLocationTime, double lastLocationSpeed) { if (speed < MAX_NO_MOVEMENT_SPEED) { speedBuffer.reset(); } else if (isValidSpeed(time, speed, lastLocationTime, lastLocationSpeed)) { @@ -220,7 +221,7 @@ public class TripStatisticsUpdater { * @param elevation the elevation */ @VisibleForTesting - double updateElevation(double elevation) { + private double updateElevation(double elevation) { // Update elevation using the smoothed average double oldAverage = elevationBuffer.getAverage(); elevationBuffer.setNext(elevation); @@ -241,15 +242,12 @@ public class TripStatisticsUpdater { * @param rise the rise */ @VisibleForTesting - void updateGrade(double run, double rise) { + private void updateGrade(double run, double rise) { runBuffer.setNext(run); double smoothedRun = runBuffer.getAverage(); - /* - * With the error in the altitude measurement it is dangerous to divide by - * anything less than 5. - */ + // With the error in the altitude measurement, it is dangerous to divide by * anything less than 5. if (smoothedRun < 5.0) { return; } @@ -272,46 +270,31 @@ public class TripStatisticsUpdater { * @param lastLocationTime the last location time * @param lastLocationSpeed the last location speed */ - private boolean isValidSpeed( - long time, double speed, long lastLocationTime, double lastLocationSpeed) { - - /* - * There are a lot of noisy speed readings. Do the cheapest checks first, - * most expensive last. - */ + private boolean isValidSpeed(long time, double speed, long lastLocationTime, double lastLocationSpeed) { + // There are a lot of noisy speed readings. Do the cheapest checks first, most expensive last. if (speed == 0) { return false; } - /* - * The following code will ignore unlikely readings. 128 m/s seems to be an - * internal android error code. - */ + // The following code will ignore unlikely readings. 128 m/s seems to be an internal android error code. if (Math.abs(speed - 128) < 1) { return false; } - /* - * See if the speed seems physically likely. Ignore any speeds that imply - * acceleration greater than 2g. - */ + // See if the speed seems physically likely. Ignore any speeds that imply acceleration greater than 2g. long timeDifference = time - lastLocationTime; double speedDifference = Math.abs(lastLocationSpeed - speed); if (speedDifference > MAX_ACCELERATION * timeDifference) { return false; } - /* - * Only check if the speed buffer is full. Check that the speed is less than - * 10X the smoothed average and the speed difference doesn't imply 2g - * acceleration. - */ + // Only check if the speed buffer is full. Check that the speed is less than 10X the smoothed average and the speed difference doesn't imply 2g acceleration. if (speedBuffer.isFull()) { double average = speedBuffer.getAverage(); double diff = Math.abs(average - speed); return (speed < average * 10) && (diff < MAX_ACCELERATION * timeDifference); - } else { - return true; } + + return true; } } diff --git a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java index 69e08be60..ae94b6bb2 100644 --- a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java @@ -34,13 +34,13 @@ public class FileUtils { /** * Used to transfer picture from the camera. */ - public static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider"; + static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider"; /** * Our external storage directory. */ static final String SDCARD_TOP_DIR = "OpenTracks"; - static final String TRACK_PREFIX = "OpenTracks"; + private static final String TRACK_PREFIX = "OpenTracks"; /** * The maximum FAT32 path length. See the FAT32 spec at * http://msdn.microsoft.com/en-us/windows/hardware/gg463080 @@ -127,16 +127,14 @@ public class FileUtils { } /** - * Builds a filename with the given base name (prefix) and the given - * extension, possibly adding a suffix to ensure the file doesn't exist. + * Builds a filename with the given base name (prefix) and the given extension, possibly adding a suffix to ensure the file doesn't exist. * * @param directory the directory the file will live in * @param fileBaseName the prefix for the file name * @param extension the file's extension * @return the complete file name, without the directory */ - public static synchronized String buildUniqueFileName( - File directory, String fileBaseName, String extension) { + public static synchronized String buildUniqueFileName(File directory, String fileBaseName, String extension) { return buildUniqueFileName(directory, fileBaseName, extension, 0); } @@ -154,7 +152,8 @@ public class FileUtils { } /** - * Gets the extension from a file name. Returns null if there is no extension. + * Gets the extension from a file name. + * Returns null if there is no extension. * * @param fileName the file name */ @@ -173,8 +172,7 @@ public class FileUtils { } /** - * Builds a filename with the given base and the given extension, possibly - * adding a suffix to ensure the file doesn't exist. + * Builds a filename with the given base and the given extension, possibly adding a suffix to ensure the file doesn't exist. * * @param directory the directory the filename will be located in * @param base the base for the filename @@ -182,8 +180,7 @@ public class FileUtils { * @param suffix the first numeric suffix to try to use, or 0 for none * @return the complete filename, without the directory */ - private static String buildUniqueFileName( - File directory, String base, String extension, int suffix) { + private static String buildUniqueFileName(File directory, String base, String extension, int suffix) { String suffixName = ""; if (suffix > 0) { suffixName += "(" + suffix + ")"; @@ -201,10 +198,9 @@ public class FileUtils { } /** - * Sanitizes the name as a valid fat32 filename. For simplicity, fat32 - * filename characters may be any combination of letters, digits, or - * characters with code point values greater than 127. Replaces the invalid - * characters with "_" and collapses multiple "_" together. + * Sanitizes the name as a valid fat32 filename. + * For simplicity, fat32 filename characters may be any combination of letters, digits, or characters with code point values greater than 127. + * Replaces the invalid characters with "_" and collapses multiple "_" together. * * @param name name */ @@ -260,8 +256,7 @@ public class FileUtils { } /** - * Truncates the name if necessary so the filename path length (directory + - * name + suffix) meets the Fat32 path limit. + * Truncates the name if necessary so the filename path length (directory + name + suffix) meets the Fat32 path limit. * * @param directory directory * @param name name @@ -273,8 +268,8 @@ public class FileUtils { if (name.length() + requiredLength > MAX_FAT32_PATH_LENGTH) { int limit = MAX_FAT32_PATH_LENGTH - requiredLength; return name.substring(0, limit); - } else { - return name; } + + return name; } } diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java index fbe3f22f7..f4872c353 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java @@ -48,12 +48,13 @@ public class IntentUtils { private final static String TAG = IntentUtils.class.getSimpleName(); + private static final String JPEG_EXTENSION = "jpeg"; + private IntentUtils() { } /** - * Creates an intent with {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} and - * {@link Intent#FLAG_ACTIVITY_NEW_TASK}. + * Creates an intent with {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} and {@link Intent#FLAG_ACTIVITY_NEW_TASK}. * * @param context the context * @param cls the class @@ -62,12 +63,10 @@ public class IntentUtils { return new Intent(context, cls).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); } - private static final String JPEG_EXTENSION = "jpeg"; - /** * Creates an intent to share a track file with an app. * - * @param context the context + * @param context the context * @param trackIds the track ids */ public static Intent newShareFileIntent(Context context, long[] trackIds) { @@ -90,6 +89,14 @@ public class IntentUtils { showCoordinateOnMap(context, waypoint.getLocation().getLatitude(), waypoint.getLocation().getLongitude(), waypoint.getName()); } + /** + * Send intent to show coordinates on a map (needs an another app). + * + * @param context the context + * @param latitude the latitude + * @param longitude the longitude + * @param label the label + */ public static void showCoordinateOnMap(Context context, double latitude, double longitude, String label) { //SEE https://developer.android.com/guide/components/intents-common.html#Maps String uri = "geo:0,0?q=" + latitude + "," + longitude; diff --git a/src/main/java/de/dennisguse/opentracks/util/ListItemUtils.java b/src/main/java/de/dennisguse/opentracks/util/ListItemUtils.java index 3d6ac9baf..6483bf4e7 100644 --- a/src/main/java/de/dennisguse/opentracks/util/ListItemUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/ListItemUtils.java @@ -61,11 +61,7 @@ public class ListItemUtils { * @param description the description value * @param photoUrl the photo url */ - public static void setListItem(Activity activity, View view, boolean isRecording, - boolean isPaused, int iconId, int iconContentDescriptionId, String name, - String totalTime, String totalDistance, int markerCount, long startTime, - boolean useRelativeTime, String category, String description, String photoUrl) { - + public static void setListItem(Activity activity, View view, boolean isRecording, boolean isPaused, int iconId, int iconContentDescriptionId, String name, String totalTime, String totalDistance, int markerCount, long startTime, boolean useRelativeTime, String category, String description, String photoUrl) { // Set photo ImageView photo = view.findViewById(R.id.list_item_photo); ImageView textGradient = view.findViewById(R.id.list_item_text_gradient); @@ -134,17 +130,11 @@ public class ListItemUtils { setTextView(activity, timeTextView, dateTime[1], hasPhoto); // Set category and description - TextView categoryDescriptionTextView = view.findViewById( - R.id.list_item_category_description); - String categoryDescription = isRecording ? null - : StringUtils.getCategoryDescription(category, description); + TextView categoryDescriptionTextView = view.findViewById(R.id.list_item_category_description); + String categoryDescription = isRecording ? null : StringUtils.getCategoryDescription(category, description); - /* - * Place categoryDescription in either ownerTimeDistanceTextView or - * categoryDescriptionTextView - */ - if (timeDistanceTextView.getVisibility() == View.GONE - && markerCountIcon.getVisibility() == View.GONE) { + // Place categoryDescription in either ownerTimeDistanceTextView or categoryDescriptionTextView + if (timeDistanceTextView.getVisibility() == View.GONE && markerCountIcon.getVisibility() == View.GONE) { setTextView(activity, categoryDescriptionTextView, null, hasPhoto); // Match list_item_category_description in list_item.xml timeDistanceTextView.setSingleLine(false); @@ -158,8 +148,7 @@ public class ListItemUtils { // Adjust iconImageView layout gravity LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) iconImageView.getLayoutParams(); - params.gravity = timeDistanceTextView.getVisibility() == View.GONE - && markerCountIcon.getVisibility() == View.GONE ? Gravity.TOP : Gravity.CENTER_VERTICAL; + params.gravity = timeDistanceTextView.getVisibility() == View.GONE && markerCountIcon.getVisibility() == View.GONE ? Gravity.TOP : Gravity.CENTER_VERTICAL; } /** @@ -196,22 +185,17 @@ public class ListItemUtils { if (isRecording || time == 0L) { return new String[]{null, null}; } + boolean isToday = DateUtils.isToday(time); int timeFlags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL; - if (isToday) { - if (useRelativeTime) { - return new String[]{DateUtils.getRelativeTimeSpanString( - time, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE).toString(), null}; - } else { - return new String[]{DateUtils.formatDateTime(context, time, timeFlags), null}; - } + if (isToday && useRelativeTime) { + return new String[]{DateUtils.getRelativeTimeSpanString(time, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString(), null}; + } else if (isToday) { + return new String[]{DateUtils.formatDateTime(context, time, timeFlags), null}; } - return new String[]{DateUtils.formatDateTime( - context, time, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL), - DateUtils.formatDateTime(context, time, timeFlags)}; + return new String[]{DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL), DateUtils.formatDateTime(context, time, timeFlags)}; } /** @@ -225,14 +209,15 @@ public class ListItemUtils { public static void setTextView(Context context, TextView textView, String value, boolean addShadow) { if (value == null || value.length() == 0) { textView.setVisibility(View.GONE); + return; + } + + textView.setVisibility(View.VISIBLE); + textView.setText(value); + if (addShadow) { + textView.setShadowLayer(5, 0, 2, context.getResources().getColor(android.R.color.black)); } else { - textView.setVisibility(View.VISIBLE); - textView.setText(value); - if (addShadow) { - textView.setShadowLayer(5, 0, 2, context.getResources().getColor(android.R.color.black)); - } else { - textView.setShadowLayer(0, 0, 0, 0); - } + textView.setShadowLayer(0, 0, 0, 0); } } diff --git a/src/main/java/de/dennisguse/opentracks/util/LocationUtils.java b/src/main/java/de/dennisguse/opentracks/util/LocationUtils.java index b420b1830..af5362e5f 100644 --- a/src/main/java/de/dennisguse/opentracks/util/LocationUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/LocationUtils.java @@ -18,30 +18,30 @@ package de.dennisguse.opentracks.util; import android.location.Location; import android.util.Log; -import de.dennisguse.opentracks.content.Track; - import java.util.ArrayList; +import java.util.List; import java.util.Stack; +import de.dennisguse.opentracks.content.Track; + /** * Utility class for decimating tracks at a given level of precision. * * @author Leif Hendrik Wilden */ +//TODO Cleanup: rename variables public class LocationUtils { private static final String TAG = LocationUtils.class.getSimpleName(); // 1 minute in milliseconds - private static final long MAX_LOCATION_AGE_MS = (long) (UnitConversions.MIN_TO_S - * UnitConversions.S_TO_MS); + private static final long MAX_LOCATION_AGE_MS = (long) (UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS); private LocationUtils() { } /** - * Computes the distance on the two sphere between the point c0 and the line - * segment c1 to c2. + * Computes the distance on the two sphere between the point c0 and the line segment c1 to c2. * * @param c0 the first coordinate * @param c1 the beginning of the line segment @@ -64,31 +64,36 @@ public class LocationUtils { double s2s1lng = s2lng - s1lng; final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng) / (s2s1lat * s2s1lat + s2s1lng * s2s1lng); + if (u <= 0) { return c0.distanceTo(c1); } + if (u >= 1) { return c0.distanceTo(c2); } + Location sa = new Location(""); sa.setLatitude(c0.getLatitude() - c1.getLatitude()); sa.setLongitude(c0.getLongitude() - c1.getLongitude()); + Location sb = new Location(""); sb.setLatitude(u * (c2.getLatitude() - c1.getLatitude())); sb.setLongitude(u * (c2.getLongitude() - c1.getLongitude())); + return sa.distanceTo(sb); } /** - * Decimates the given locations for a given zoom level. This uses a - * Douglas-Peucker decimation algorithm. + * Decimates the given locations for a given zoom level. + * This uses a Douglas-Peucker decimation algorithm. * * @param tolerance in meters * @param locations input * @param decimated output */ - private static void decimate( - double tolerance, ArrayList locations, ArrayList decimated) { + //TODO What was it used for? Sharing data with other apps? + private static void decimate(double tolerance, List locations, List decimated) { final int n = locations.size(); if (n < 1) { return; @@ -153,16 +158,16 @@ public class LocationUtils { } /** - * Checks if a given location is a valid (i.e. physically possible) location - * on Earth. Note: The special separator locations (which have latitude = 100) - * will not qualify as valid. Neither will locations with lat=0 and lng=0 as - * these are most likely "bad" measurements which often cause trouble. + * Checks if a given location is a valid (i.e. physically possible) locationon Earth. + * Note: The special separator locations (which have latitude = 100) will not qualify as valid. + * Neither will locations with lat=0 and lng=0 as these are most likely "bad" measurements which often cause trouble. * * @param location the location to test * @return true if the location is a valid location. */ public static boolean isValidLocation(Location location) { - return location != null && Math.abs(location.getLatitude()) <= 90 + return location != null + && Math.abs(location.getLatitude()) <= 90 && Math.abs(location.getLongitude()) <= 180; } @@ -172,7 +177,6 @@ public class LocationUtils { * @param location the location */ public static boolean isLocationOld(Location location) { - return !LocationUtils.isValidLocation(location) - || (System.currentTimeMillis() - location.getTime() > MAX_LOCATION_AGE_MS); + return !LocationUtils.isValidLocation(location) || (System.currentTimeMillis() - location.getTime() > MAX_LOCATION_AGE_MS); } } diff --git a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java index e9f023edb..2bc1fb76f 100644 --- a/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/PreferencesUtils.java @@ -31,8 +31,8 @@ import de.dennisguse.opentracks.R; public class PreferencesUtils { /* - * Preferences values. The defaults need to match the defaults in the xml - * files. + * Preferences values. + * The defaults need to match the defaults in the xml files. */ public static final int AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT = 0; @@ -48,7 +48,10 @@ public class PreferencesUtils { public static final boolean CHART_SHOW_HEART_RATE_DEFAULT = true; public static final boolean CHART_SHOW_POWER_DEFAULT = true; public static final boolean CHART_SHOW_SPEED_DEFAULT = true; - public static final String CHART_X_AXIS_DEFAULT = "DISTANCE"; + @Deprecated + //NOTE: is at the moment still used to determine if a track is currently recorded; better ask the service directly. + //NOTE: This is also used to recover from a reboot, but this data should not be exposed to the whole application. + public static final long RECORDING_TRACK_ID_DEFAULT = -1L; public static final String DEFAULT_ACTIVITY_DEFAULT = ""; @@ -68,20 +71,16 @@ public class PreferencesUtils { public static final int RECORDING_GPS_ACCURACY_DEFAULT = 50; public static final int RECORDING_GPS_ACCURACY_EXCELLENT = 10; public static final int RECORDING_GPS_ACCURACY_POOR = 2000; - - @Deprecated //NOTE: is at the moment still used to determine if a track is currently recorded; better ask the service directly. - public static final long RECORDING_TRACK_ID_DEFAULT = -1L; + static final boolean STATS_SHOW_COORDINATE_DEFAULT = false; public static final boolean RECORDING_TRACK_PAUSED_DEFAULT = true; public static final int SPLIT_FREQUENCY_DEFAULT = 0; - - // Stats - public static final String STATS_RATE_DEFAULT = "SPEED"; - public static final boolean STATS_SHOW_COORDINATE_DEFAULT = false; - public static final boolean STATS_SHOW_ELEVATION_DEFAULT = false; + static final boolean STATS_SHOW_ELEVATION_DEFAULT = false; + static final String TRACK_NAME_DEFAULT = "DATE_ISO_8601"; + private static final String CHART_X_AXIS_DEFAULT = "DISTANCE"; public static final String STATS_UNITS_DEFAULT = "METRIC"; - - public static final String TRACK_NAME_DEFAULT = "DATE_ISO_8601"; + // Stats + private static final String STATS_RATE_DEFAULT = "SPEED"; public static final boolean SHOW_TRACKDETAIL_WHILE_RECORDING_ON_LOCKSCREEN = false; diff --git a/src/main/java/de/dennisguse/opentracks/util/StatsUtils.java b/src/main/java/de/dennisguse/opentracks/util/StatsUtils.java index 927350f06..dc36a3576 100644 --- a/src/main/java/de/dennisguse/opentracks/util/StatsUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/StatsUtils.java @@ -47,10 +47,8 @@ public class StatsUtils { * Sets the location values. * * @param context the context - * @param activity the activity for finding views. If null, the view cannot be - * null - * @param view the containing view for finding views. If null, the activity - * cannot be null + * @param activity the activity for finding views. If null, the view cannot be null + * @param view the containing view for finding views. If null, the activity cannot be null * @param location the location * @param isRecording true if recording */ @@ -96,19 +94,17 @@ public class StatsUtils { } public static void setSensorData(Context context, Activity activity, SensorDataSet sensorDataSet, boolean isRecording) { - { - // SensorDataSet: heart rate - int isVisible = View.VISIBLE; - if (!isRecording || PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT))) { - isVisible = View.INVISIBLE; - } - getView(activity, null, R.id.stats_sensor_container).setVisibility(isVisible); + // SensorDataSet: heart rate + int isVisible = View.VISIBLE; + if (!isRecording || PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT.equals(PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT))) { + isVisible = View.INVISIBLE; + } + getView(activity, null, R.id.stats_sensor_container).setVisibility(isVisible); - View viewValue = getView(activity, null, R.id.stats_sensor_heart_rate_value); - View viewSensor = getView(activity, null, R.id.stats_sensor_heart_rate_sensor); - if (isRecording) { - setHeartRateData(context, viewValue, viewSensor, sensorDataSet); - } + View viewValue = getView(activity, null, R.id.stats_sensor_heart_rate_value); + View viewSensor = getView(activity, null, R.id.stats_sensor_heart_rate_sensor); + if (isRecording) { + setHeartRateData(context, viewValue, viewSensor, sensorDataSet); } } @@ -126,13 +122,10 @@ public class StatsUtils { * Sets the trip statistics values. * * @param context the context - * @param activity the activity for finding views. If null, then view cannot - * be null - * @param view the containing view for finding views. If null, the activity - * cannot be null + * @param activity the activity for finding views. If null, then view cannot be null + * @param view the containing view for finding views. If null, the activity cannot be null * @param tripStatistics the trip statistics - * @param trackIconValue the track icon value or null to hide the track icon - * spinner + * @param trackIconValue the track icon value or null to hide the track icon spinner */ public static void setTripStatisticsValues(Context context, Activity activity, View view, TripStatistics tripStatistics, String trackIconValue) { boolean metricUnits = PreferencesUtils.isMetricUnits(context); @@ -265,8 +258,7 @@ public class StatsUtils { * @param grade the grade in fraction between 0 and 1 */ private static void setGradeValue(Context context, View view, int labelId, double grade) { - String value = Double.isNaN(grade) || Double.isInfinite(grade) ? null - : String.format(Locale.getDefault(), GRADE_FORMAT, Math.round(grade * 100)); + String value = Double.isNaN(grade) || Double.isInfinite(grade) ? null : String.format(Locale.getDefault(), GRADE_FORMAT, Math.round(grade * 100)); setItem(context, view, labelId, value, GRADE_PERCENTAGE); } @@ -279,8 +271,7 @@ public class StatsUtils { * @param coordinate the coordinate in degrees */ private static void setCoordinateValue(Context context, View view, int labelId, double coordinate) { - String value = Double.isNaN(coordinate) || Double.isInfinite(coordinate) ? null - : StringUtils.formatCoordinate(coordinate); + String value = Double.isNaN(coordinate) || Double.isInfinite(coordinate) ? null : StringUtils.formatCoordinate(coordinate); setItem(context, view, labelId, value, null); } diff --git a/src/main/java/de/dennisguse/opentracks/util/StringUtils.java b/src/main/java/de/dennisguse/opentracks/util/StringUtils.java index 89be70fa8..e3bfdcb32 100644 --- a/src/main/java/de/dennisguse/opentracks/util/StringUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/StringUtils.java @@ -17,13 +17,9 @@ package de.dennisguse.opentracks.util; import android.content.Context; import android.location.Location; -import android.text.Html; -import android.text.Spanned; import android.text.TextUtils; import android.text.format.DateUtils; -import de.dennisguse.opentracks.R; - import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; @@ -32,6 +28,8 @@ import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.dennisguse.opentracks.R; + /** * Various string manipulation methods. * @@ -41,18 +39,17 @@ import java.util.regex.Pattern; public class StringUtils { private static final String COORDINATE_DEGREE = "\u00B0"; - private static final SimpleDateFormat ISO_8601_DATE_TIME_FORMAT = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); - private static final SimpleDateFormat ISO_8601_BASE = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss", Locale.US); - private static final Pattern ISO_8601_EXTRAS = Pattern.compile( - "^(\\.\\d+)?(?:Z|([+-])(\\d{2}):(\\d{2}))?$"); + + private static final SimpleDateFormat ISO_8601_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); + private static final SimpleDateFormat ISO_8601_BASE = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); + private static final Pattern ISO_8601_EXTRAS = Pattern.compile("^(\\.\\d+)?(?:Z|([+-])(\\d{2}):(\\d{2}))?$"); static { ISO_8601_DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); ISO_8601_BASE.setTimeZone(TimeZone.getTimeZone("UTC")); } + private StringUtils() { } @@ -63,9 +60,8 @@ public class StringUtils { * @param time the time in milliseconds */ public static String formatDateTime(Context context, long time) { - return DateUtils.formatDateTime( - context, time, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE) + " " - + DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_TIME); + return DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE) + + " " + DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_TIME); } /** @@ -80,19 +76,20 @@ public class StringUtils { /** * Formats the elapsed timed in the form "MM:SS" or "H:MM:SS". + * TODO Remove as min API level is now 21; replace with DateUtils.formatElapsedTime(time * MS_TO_S). * * @param time the time in milliseconds */ public static String formatElapsedTime(long time) { + DateUtils.formatElapsedTime(1); /* - * TODO - * Temporary workaround for DateUtils.formatElapsedTime(time * MS_TO_S). In API - * level 17, it returns strings like "1:0:00" instead of "1:00:00", which - * breaks several unit tests. + * Temporary workaround for DateUtils.formatElapsedTime(time * MS_TO_S). + * In API level 17, it returns strings like "1:0:00" instead of "1:00:00", which breaks several unit tests. */ if (time < 0) { return "-"; } + long hours = 0; long minutes = 0; long elapsedSeconds = (long) (time * UnitConversions.MS_TO_S); @@ -135,6 +132,7 @@ public class StringUtils { if (Double.isNaN(distance) || Double.isInfinite(distance)) { return context.getString(R.string.value_unknown); } + if (metricUnits) { if (distance > 500.0) { distance *= UnitConversions.M_TO_KM; @@ -153,11 +151,11 @@ public class StringUtils { } } - public static String formatDecimal(double value) { + static String formatDecimal(double value) { return StringUtils.formatDecimal(value, 2); } - public static String formatDecimal(double value, int decimalPlaces) { + static String formatDecimal(double value, int decimalPlaces) { String result = String.format(Locale.getDefault(), "%1$,." + decimalPlaces + "f", value); return result.replaceAll("[0]*$", "").replaceAll("\\.$", ""); } @@ -172,14 +170,16 @@ public class StringUtils { } /** - * Gets the distance in an array of two strings. The first string is the - * distance. The second string is the unit. The first string is null if the - * distance is invalid. + * Gets the distance in an array of two strings. + * The first string is the distance. + * The second string is the unit. + * The first string is null if the distance is invalid. * * @param context the context * @param distance the distance * @param metricUnits true to use metric unit */ + //TODO Return Pair public static String[] getDistanceParts(Context context, double distance, boolean metricUnits) { String[] result = new String[2]; if (Double.isNaN(distance) || Double.isInfinite(distance)) { @@ -211,17 +211,18 @@ public class StringUtils { } /** - * Gets the speed in an array of two strings. The first string is the speed. - * The second string is the unit. The first string is null if speed is - * invalid. + * Gets the speed in an array of two strings. + * The first string is the speed. + * The second string is the unit. + * The first string is null if speed is invalid. * * @param context the context * @param speed the speed * @param metricUnits true to use metric unit * @param reportSpeed true to report speed */ - public static String[] getSpeedParts( - Context context, double speed, boolean metricUnits, boolean reportSpeed) { + //TODO Return Pair + public static String[] getSpeedParts(Context context, double speed, boolean metricUnits, boolean reportSpeed) { String[] result = new String[2]; int unitId; if (metricUnits) { @@ -268,7 +269,7 @@ public class StringUtils { * @param category the category * @param description the description */ - public static String getCategoryDescription(String category, String description) { + static String getCategoryDescription(String category, String description) { if (category == null || category.length() == 0) { return description; } @@ -282,9 +283,9 @@ public class StringUtils { } /** - * Formats the given text as a XML CDATA element. This includes adding the - * starting and ending CDATA tags. Please notice that this may result in - * multiple consecutive CDATA tags. + * Formats the given text as a XML CDATA element. + * This includes adding the starting and ending CDATA tags. + * NOTE: This may result in multiple consecutive CDATA tags. * * @param text the given text */ @@ -293,25 +294,23 @@ public class StringUtils { } /** - * Gets the time, in milliseconds, from an XML date time string as defined at - * http://www.w3.org/TR/xmlschema-2/#dateTime + * Gets the time, in milliseconds, from an XML date time string as defined at http://www.w3.org/TR/xmlschema-2/#dateTime * * @param xmlDateTime the XML date time string */ + //TODO Can this be replaced using java.time? public static long getTime(String xmlDateTime) { // Parse the date time base ParsePosition position = new ParsePosition(0); Date date = ISO_8601_BASE.parse(xmlDateTime, position); if (date == null) { - throw new IllegalArgumentException("Invalid XML dateTime value: " + xmlDateTime - + " (at position " + position.getErrorIndex() + ")"); + throw new IllegalArgumentException("Invalid XML dateTime value: " + xmlDateTime + " (at position " + position.getErrorIndex() + ")"); } // Parse the date time extras Matcher matcher = ISO_8601_EXTRAS.matcher(xmlDateTime.substring(position.getIndex())); if (!matcher.matches()) { - // This will match even an empty string as all groups are optional. Thus a - // non-match means invalid content. + // This will match even an empty string as all groups are optional. Thus a non-match means invalid content. throw new IllegalArgumentException("Invalid XML dateTime value: " + xmlDateTime); } @@ -354,9 +353,8 @@ public class StringUtils { } /** - * Gets the time as an array of three integers. Index 0 contains the number of - * seconds, index 1 contains the number of minutes, and index 2 contains the - * number of hours. + * Gets the time as an array of three integers. + * Index 0 contains the number of seconds, index 1 contains the number of minutes, and index 2 contains the number of hours. * * @param time the time in milliseconds * @return an array of 3 elements. @@ -379,22 +377,6 @@ public class StringUtils { return parts; } - /** - * Gets the html. - * - * @param context the context - * @param resId the string resource id - * @param formatArgs the string resource ids of the format arguments - */ - public static Spanned getHtml(Context context, int resId, Object... formatArgs) { - Object[] args = new Object[formatArgs.length]; - for (int i = 0; i < formatArgs.length; i++) { - String url = context.getString((Integer) formatArgs[i]); - args[i] = " " + url + " "; - } - return Html.fromHtml(context.getString(resId, args)); - } - /** * Gets the frequency display options. * @@ -409,9 +391,7 @@ public class StringUtils { if (value == PreferencesUtils.FREQUENCY_OFF) { options[i] = context.getString(R.string.value_off); } else if (value < 0) { - options[i] = context.getString( - metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile, - Math.abs(value)); + options[i] = context.getString(metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile, Math.abs(value)); } else { options[i] = context.getString(R.string.value_integer_minute, value); } diff --git a/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java b/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java index 7e904fcec..abfe82677 100644 --- a/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/TrackIconUtils.java @@ -33,12 +33,12 @@ import android.widget.Spinner; import androidx.annotation.NonNull; -import de.dennisguse.opentracks.R; - import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import de.dennisguse.opentracks.R; + /** * Utilities for track icon. * @@ -55,31 +55,16 @@ public class TrackIconUtils { private static final String SNOW_BOARDING = "SNOW_BOARDING"; private static final String WALK = "WALK"; - private static final int[] AIRPLANE_LIST = new int[]{R.string.activity_type_airplane, - R.string.activity_type_commercial_airplane, R.string.activity_type_rc_airplane}; - private static final int[] BIKE_LIST = new int[]{R.string.activity_type_biking, - R.string.activity_type_cycling, R.string.activity_type_dirt_bike, - R.string.activity_type_motor_bike, R.string.activity_type_mountain_biking, - R.string.activity_type_road_biking, R.string.activity_type_track_cycling}; - private static final int[] BOAT_LIST = new int[]{R.string.activity_type_boat, - R.string.activity_type_ferry, R.string.activity_type_motor_boating, - R.string.activity_type_rc_boat}; - private static final int[] DRIVE_LIST = new int[]{R.string.activity_type_atv, - R.string.activity_type_driving, R.string.activity_type_driving_bus, - R.string.activity_type_driving_car}; - private static final int[] RUN_LIST = new int[]{R.string.activity_type_running, - R.string.activity_type_street_running, R.string.activity_type_track_running, - R.string.activity_type_trail_running}; - private static final int[] SKI_LIST = new int[]{ - R.string.activity_type_cross_country_skiing, R.string.activity_type_skiing}; - private static final int[] SNOW_BOARDING_LIST = new int[]{ - R.string.activity_type_snow_boarding}; - private static final int[] WALK_LIST = new int[]{R.string.activity_type_hiking, - R.string.activity_type_off_trail_hiking, R.string.activity_type_speed_walking, - R.string.activity_type_trail_hiking, R.string.activity_type_walking}; + private static final int[] AIRPLANE_LIST = new int[]{R.string.activity_type_airplane, R.string.activity_type_commercial_airplane, R.string.activity_type_rc_airplane}; + private static final int[] BIKE_LIST = new int[]{R.string.activity_type_biking, R.string.activity_type_cycling, R.string.activity_type_dirt_bike, R.string.activity_type_motor_bike, R.string.activity_type_mountain_biking, R.string.activity_type_road_biking, R.string.activity_type_track_cycling}; + private static final int[] BOAT_LIST = new int[]{R.string.activity_type_boat, R.string.activity_type_ferry, R.string.activity_type_motor_boating, R.string.activity_type_rc_boat}; + private static final int[] DRIVE_LIST = new int[]{R.string.activity_type_atv, R.string.activity_type_driving, R.string.activity_type_driving_bus, R.string.activity_type_driving_car}; + private static final int[] RUN_LIST = new int[]{R.string.activity_type_running, R.string.activity_type_street_running, R.string.activity_type_track_running, R.string.activity_type_trail_running}; + private static final int[] SKI_LIST = new int[]{R.string.activity_type_cross_country_skiing, R.string.activity_type_skiing}; + private static final int[] SNOW_BOARDING_LIST = new int[]{R.string.activity_type_snow_boarding}; + private static final int[] WALK_LIST = new int[]{R.string.activity_type_hiking, R.string.activity_type_off_trail_hiking, R.string.activity_type_speed_walking, R.string.activity_type_trail_hiking, R.string.activity_type_walking}; - private static final LinkedHashMap> - MAP = new LinkedHashMap<>(); + private static final LinkedHashMap> MAP = new LinkedHashMap<>(); static { MAP.put(RUN, new Pair<>(R.string.activity_type_running, R.drawable.ic_track_run)); @@ -173,10 +158,8 @@ public class TrackIconUtils { adapter.notifyDataSetChanged(); } - public static ArrayAdapter getIconSpinnerAdapter( - final Context context, String iconValue) { - return new ArrayAdapter(context, android.R.layout.simple_spinner_item, - new StringBuilder[]{new StringBuilder(iconValue)}) { + public static ArrayAdapter getIconSpinnerAdapter(final Context context, String iconValue) { + return new ArrayAdapter(context, android.R.layout.simple_spinner_item, new StringBuilder[]{new StringBuilder(iconValue)}) { @NonNull @Override public View getView(int position, View convertView, @NonNull android.view.ViewGroup parent) { @@ -211,8 +194,7 @@ public class TrackIconUtils { * @param menu the menu */ public static void setMenuIconColor(Menu menu) { - int size = menu.size(); - for (int i = 0; i < size; i++) { + for (int i = 0; i < menu.size(); i++) { MenuItem menuitem = menu.getItem(i); setMenuIconColor(menuitem); } diff --git a/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java b/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java index 02cb22257..9a85fbb5b 100644 --- a/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/TrackNameUtils.java @@ -32,6 +32,7 @@ import de.dennisguse.opentracks.R; */ public class TrackNameUtils { + //TODO Could be available in java.time? @VisibleForTesting static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; diff --git a/src/main/java/de/dennisguse/opentracks/util/TrackRecordingServiceConnectionUtils.java b/src/main/java/de/dennisguse/opentracks/util/TrackRecordingServiceConnectionUtils.java index 57b1f73ad..2a01f185b 100644 --- a/src/main/java/de/dennisguse/opentracks/util/TrackRecordingServiceConnectionUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/TrackRecordingServiceConnectionUtils.java @@ -24,14 +24,14 @@ import android.content.Intent; import android.util.Log; import android.widget.Toast; +import java.util.List; + +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.TrackEditActivity; import de.dennisguse.opentracks.content.WaypointCreationRequest; import de.dennisguse.opentracks.services.ITrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; -import de.dennisguse.opentracks.R; - -import java.util.List; /** * Utilities for {@link TrackRecordingServiceConnection}. @@ -52,6 +52,11 @@ public class TrackRecordingServiceConnectionUtils { */ public static boolean isRecordingServiceRunning(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + if (activityManager == null) { + return false; + } + + //TODO This approach is deprecated as of API level 26 and should be replaced. List services = activityManager.getRunningServices(Integer.MAX_VALUE); for (RunningServiceInfo serviceInfo : services) { @@ -99,13 +104,12 @@ public class TrackRecordingServiceConnectionUtils { */ public static void stopRecording(Context context, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean showEditor) { ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound(); - if (trackRecordingService != null) { + if (trackRecordingService == null) { + resetRecordingState(context); + } else { try { if (showEditor) { - /* - * Need to remember the recordingTrackId before calling - * endCurrentTrack. endCurrentTrack sets the value to -1L. - */ + // Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L. long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key); trackRecordingService.endCurrentTrack(); if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { @@ -118,10 +122,9 @@ public class TrackRecordingServiceConnectionUtils { trackRecordingService.endCurrentTrack(); } } catch (Exception e) { + //TODO What exception are we catching here? Should be removed... Log.e(TAG, "Unable to stop recording.", e); } - } else { - resetRecordingState(context); } trackRecordingServiceConnection.unbindAndStop(); } @@ -130,8 +133,7 @@ public class TrackRecordingServiceConnectionUtils { * Resumes the track recording service connection. * * @param context the context - * @param trackRecordingServiceConnection the track recording service - * connection + * @param trackRecordingServiceConnection the track recording service connection */ public static void startConnection(Context context, TrackRecordingServiceConnection trackRecordingServiceConnection) { trackRecordingServiceConnection.bindIfStarted(); @@ -143,25 +145,19 @@ public class TrackRecordingServiceConnectionUtils { private static void resetRecordingState(Context context) { long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key); if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { - PreferencesUtils.setLong( - context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + PreferencesUtils.setLong(context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); } - boolean recordingTrackPaused = PreferencesUtils.getBoolean(context, - R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); + boolean recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); if (!recordingTrackPaused) { - PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, - PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); + PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); } } /** * Adds a marker. */ - public static long addMarker(Context context, - TrackRecordingServiceConnection trackRecordingServiceConnection, - WaypointCreationRequest waypointCreationRequest) { - ITrackRecordingService trackRecordingService = trackRecordingServiceConnection - .getServiceIfBound(); + public static long addMarker(Context context, TrackRecordingServiceConnection trackRecordingServiceConnection, WaypointCreationRequest waypointCreationRequest) { + ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound(); if (trackRecordingService == null) { Log.d(TAG, "Unable to add marker, no track recording service"); } else { @@ -175,6 +171,7 @@ public class TrackRecordingServiceConnectionUtils { Log.e(TAG, "Unable to add marker.", e); } } + Toast.makeText(context, R.string.marker_add_error, Toast.LENGTH_LONG).show(); return -1L; } diff --git a/src/main/java/de/dennisguse/opentracks/util/UnitConversions.java b/src/main/java/de/dennisguse/opentracks/util/UnitConversions.java index 7e586e816..e593bd6df 100644 --- a/src/main/java/de/dennisguse/opentracks/util/UnitConversions.java +++ b/src/main/java/de/dennisguse/opentracks/util/UnitConversions.java @@ -24,6 +24,7 @@ public class UnitConversions { // multiplication factor to convert seconds to milliseconds public static final double S_TO_MS = 1000.0; + // Time // 1 second in milliseconds public static final long ONE_SECOND = (long) UnitConversions.S_TO_MS; diff --git a/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetConfigActivity.java b/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetConfigActivity.java index 0839586e5..afbacfe74 100644 --- a/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetConfigActivity.java +++ b/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetConfigActivity.java @@ -24,13 +24,13 @@ import android.view.View; import android.widget.ArrayAdapter; import android.widget.Spinner; -import de.dennisguse.opentracks.util.PreferencesUtils; -import de.dennisguse.opentracks.R; - import java.util.ArrayList; import java.util.List; import java.util.Locale; +import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.util.PreferencesUtils; + /** * Activity to configure the track widget. * @@ -67,34 +67,22 @@ public class TrackWidgetConfigActivity extends Activity { addItem(list, R.string.stats_total_time); addItem(list, reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); addItem(list, R.string.stats_moving_time); - addItem(list, - reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); + addItem(list, reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); - configSpinner(item1, list, PreferencesUtils.getInt( - this, R.string.track_widget_item1, PreferencesUtils.TRACK_WIDGET_ITEM1_DEFAULT)); - configSpinner(item2, list, PreferencesUtils.getInt( - this, R.string.track_widget_item2, PreferencesUtils.TRACK_WIDGET_ITEM2_DEFAULT)); - configSpinner(item3, list, PreferencesUtils.getInt( - this, R.string.track_widget_item3, PreferencesUtils.TRACK_WIDGET_ITEM3_DEFAULT)); - configSpinner(item4, list, PreferencesUtils.getInt( - this, R.string.track_widget_item4, PreferencesUtils.TRACK_WIDGET_ITEM4_DEFAULT)); + configSpinner(item1, list, PreferencesUtils.getInt(this, R.string.track_widget_item1, PreferencesUtils.TRACK_WIDGET_ITEM1_DEFAULT)); + configSpinner(item2, list, PreferencesUtils.getInt(this, R.string.track_widget_item2, PreferencesUtils.TRACK_WIDGET_ITEM2_DEFAULT)); + configSpinner(item3, list, PreferencesUtils.getInt(this, R.string.track_widget_item3, PreferencesUtils.TRACK_WIDGET_ITEM3_DEFAULT)); + configSpinner(item4, list, PreferencesUtils.getInt(this, R.string.track_widget_item4, PreferencesUtils.TRACK_WIDGET_ITEM4_DEFAULT)); findViewById(R.id.track_widget_config_add).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - // Push widget update to surface with newly set prefix - AppWidgetManager appWidgetManager = AppWidgetManager.getInstance( - TrackWidgetConfigActivity.this); - TrackWidgetProvider.updateAppWidget( - TrackWidgetConfigActivity.this, appWidgetManager, appWidgetId, -1L); - PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item1, - item1.getSelectedItemPosition()); - PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item2, - item2.getSelectedItemPosition()); - PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item3, - item3.getSelectedItemPosition()); - PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item4, - item4.getSelectedItemPosition()); + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(TrackWidgetConfigActivity.this); + TrackWidgetProvider.updateAppWidget(TrackWidgetConfigActivity.this, appWidgetManager, appWidgetId, -1L); + PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item1, item1.getSelectedItemPosition()); + PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item2, item2.getSelectedItemPosition()); + PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item3, item3.getSelectedItemPosition()); + PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item4, item4.getSelectedItemPosition()); // Make sure we pass back the original appWidgetId Intent resultValue = new Intent(); @@ -113,9 +101,7 @@ public class TrackWidgetConfigActivity extends Activity { // Find the app widget id from the intent. Intent intent = getIntent(); Bundle extras = intent.getExtras(); - appWidgetId = extras != null ? extras.getInt( - AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) - : AppWidgetManager.INVALID_APPWIDGET_ID; + appWidgetId = extras != null ? extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) : AppWidgetManager.INVALID_APPWIDGET_ID; // If they gave us an intent without the widget id, just bail. if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { @@ -128,8 +114,7 @@ public class TrackWidgetConfigActivity extends Activity { } private void configSpinner(Spinner spinner, List list, int position) { - ArrayAdapter adapter = new ArrayAdapter<>( - this, android.R.layout.simple_spinner_item, list); + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, list); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); spinner.setSelection(position); diff --git a/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetProvider.java b/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetProvider.java index a6d079ed2..8660088c5 100644 --- a/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetProvider.java +++ b/src/main/java/de/dennisguse/opentracks/widgets/TrackWidgetProvider.java @@ -43,9 +43,7 @@ import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; /** - * A track widget to start/stop/pause/resume recording, launch the main activity, and - * display track statistics (total distance, total time, average speed, and - * moving time) for the recording track, the selected track or the last track. + * A track widget to start/stop/pause/resume recording, launch the main activity, and display track statistics (total distance, total time, average speed, and moving time) for the recording track, the selected track or the last track. * * @author Sandor Dornbush * @author Paul R. Saxman @@ -60,18 +58,10 @@ public class TrackWidgetProvider extends AppWidgetProvider { private static final int THREE_CELLS = 180; private static final int FOUR_CELLS = 250; - private static final int[] ITEM1_IDS = {R.id.track_widget_item1_label, - R.id.track_widget_item1_value, R.id.track_widget_item1_unit, - R.id.track_widget_item1_chronometer}; - private static final int[] ITEM2_IDS = {R.id.track_widget_item2_label, - R.id.track_widget_item2_value, R.id.track_widget_item2_unit, - R.id.track_widget_item2_chronometer}; - private static final int[] ITEM3_IDS = {R.id.track_widget_item3_label, - R.id.track_widget_item3_value, R.id.track_widget_item3_unit, - R.id.track_widget_item3_chronometer}; - private static final int[] ITEM4_IDS = {R.id.track_widget_item4_label, - R.id.track_widget_item4_value, R.id.track_widget_item4_unit, - R.id.track_widget_item4_chronometer}; + private static final int[] ITEM1_IDS = {R.id.track_widget_item1_label, R.id.track_widget_item1_value, R.id.track_widget_item1_unit, R.id.track_widget_item1_chronometer}; + private static final int[] ITEM2_IDS = {R.id.track_widget_item2_label, R.id.track_widget_item2_value, R.id.track_widget_item2_unit, R.id.track_widget_item2_chronometer}; + private static final int[] ITEM3_IDS = {R.id.track_widget_item3_label, R.id.track_widget_item3_value, R.id.track_widget_item3_unit, R.id.track_widget_item3_chronometer}; + private static final int[] ITEM4_IDS = {R.id.track_widget_item4_label, R.id.track_widget_item4_value, R.id.track_widget_item4_unit, R.id.track_widget_item4_chronometer}; /** * Updates an app widget. @@ -81,8 +71,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param appWidgetId the app widget id * @param trackId the track id. -1L to not specify one */ - public static void updateAppWidget( - Context context, AppWidgetManager appWidgetManager, int appWidgetId, long trackId) { + public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, long trackId) { int size = getAppWidgetSize(appWidgetManager, appWidgetId); RemoteViews remoteViews = getRemoteViews(context, trackId, size); appWidgetManager.updateAppWidget(appWidgetId, remoteViews); @@ -96,8 +85,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { */ private static void updateAllAppWidgets(Context context, long trackId) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); - int[] appWidgetIds = appWidgetManager.getAppWidgetIds( - new ComponentName(context, TrackWidgetProvider.class)); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, TrackWidgetProvider.class)); for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId, trackId); } @@ -134,41 +122,31 @@ public class TrackWidgetProvider extends AppWidgetProvider { // Get the preferences long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key); boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; - boolean isPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, - PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); + boolean isPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); boolean metricUnits = PreferencesUtils.isMetricUnits(context); boolean reportSpeed = PreferencesUtils.isReportSpeed(context); - int item1 = PreferencesUtils.getInt( - context, R.string.track_widget_item1, PreferencesUtils.TRACK_WIDGET_ITEM1_DEFAULT); - int item2 = PreferencesUtils.getInt( - context, R.string.track_widget_item2, PreferencesUtils.TRACK_WIDGET_ITEM2_DEFAULT); + int item1 = PreferencesUtils.getInt(context, R.string.track_widget_item1, PreferencesUtils.TRACK_WIDGET_ITEM1_DEFAULT); + int item2 = PreferencesUtils.getInt(context, R.string.track_widget_item2, PreferencesUtils.TRACK_WIDGET_ITEM2_DEFAULT); // Get track and trip statistics ContentProviderUtils contentProviderUtils = ContentProviderUtils.Factory.get(context); if (trackId == -1L) { trackId = recordingTrackId; } - Track track = trackId != -1L ? contentProviderUtils.getTrack(trackId) - : contentProviderUtils.getLastTrack(); + Track track = trackId != -1L ? contentProviderUtils.getTrack(trackId) : contentProviderUtils.getLastTrack(); TripStatistics tripStatistics = track == null ? null : track.getTripStatistics(); updateStatisticsContainer(context, remoteViews, track); - setItem(context, remoteViews, ITEM1_IDS, item1, tripStatistics, isRecording, isPaused, - metricUnits, reportSpeed); - setItem(context, remoteViews, ITEM2_IDS, item2, tripStatistics, isRecording, isPaused, - metricUnits, reportSpeed); + setItem(context, remoteViews, ITEM1_IDS, item1, tripStatistics, isRecording, isPaused, metricUnits, reportSpeed); + setItem(context, remoteViews, ITEM2_IDS, item2, tripStatistics, isRecording, isPaused, metricUnits, reportSpeed); updateRecordButton(context, remoteViews, isRecording, isPaused); updateStopButton(context, remoteViews, isRecording); if (heightSize > 1) { - int item3 = PreferencesUtils.getInt( - context, R.string.track_widget_item3, PreferencesUtils.TRACK_WIDGET_ITEM3_DEFAULT); - int item4 = PreferencesUtils.getInt( - context, R.string.track_widget_item4, PreferencesUtils.TRACK_WIDGET_ITEM4_DEFAULT); - setItem(context, remoteViews, ITEM3_IDS, item3, tripStatistics, isRecording, isPaused, - metricUnits, reportSpeed); - setItem(context, remoteViews, ITEM4_IDS, item4, tripStatistics, isRecording, isPaused, - metricUnits, reportSpeed); + int item3 = PreferencesUtils.getInt(context, R.string.track_widget_item3, PreferencesUtils.TRACK_WIDGET_ITEM3_DEFAULT); + int item4 = PreferencesUtils.getInt(context, R.string.track_widget_item4, PreferencesUtils.TRACK_WIDGET_ITEM4_DEFAULT); + setItem(context, remoteViews, ITEM3_IDS, item3, tripStatistics, isRecording, isPaused, metricUnits, reportSpeed); + setItem(context, remoteViews, ITEM4_IDS, item4, tripStatistics, isRecording, isPaused, metricUnits, reportSpeed); updateRecordStatus(context, remoteViews, isRecording, isPaused); } return remoteViews; @@ -196,9 +174,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param metricUnits true to use metric units * @param reportSpeed try to report speed */ - private static void setItem(Context context, RemoteViews remoteViews, int[] ids, int value, - TripStatistics tripStatistics, boolean isRecording, boolean isPaused, boolean metricUnits, - boolean reportSpeed) { + private static void setItem(Context context, RemoteViews remoteViews, int[] ids, int value, TripStatistics tripStatistics, boolean isRecording, boolean isPaused, boolean metricUnits, boolean reportSpeed) { switch (value) { case 0: updateDistance(context, remoteViews, ids, tripStatistics, metricUnits); @@ -213,8 +189,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { updateMovingTime(context, remoteViews, ids, tripStatistics); break; case 4: - updateAverageMovingSpeed( - context, remoteViews, ids, tripStatistics, metricUnits, reportSpeed); + updateAverageMovingSpeed(context, remoteViews, ids, tripStatistics, metricUnits, reportSpeed); break; default: updateDistance(context, remoteViews, ids, tripStatistics, metricUnits); @@ -236,8 +211,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param remoteViews the remote views * @param track the track */ - private static void updateStatisticsContainer( - Context context, RemoteViews remoteViews, Track track) { + private static void updateStatisticsContainer(Context context, RemoteViews remoteViews, Track track) { PendingIntent pendingIntent; if (track != null) { Intent intent = IntentUtils.newIntent(context, TrackDetailActivity.class) @@ -260,8 +234,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param tripStatistics the trip statistics * @param metricUnits true to use metric units */ - private static void updateDistance(Context context, RemoteViews remoteViews, int[] ids, - TripStatistics tripStatistics, boolean metricUnits) { + private static void updateDistance(Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics, boolean metricUnits) { double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance(); String[] totalDistanceParts = StringUtils.getDistanceParts(context, totalDistance, metricUnits); if (totalDistanceParts[0] == null) { @@ -280,11 +253,9 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param ids the item's ids * @param tripStatistics the trip statistics */ - private static void updateTotalTime(Context context, RemoteViews remoteViews, int[] ids, - TripStatistics tripStatistics, boolean isRecording, boolean isPaused) { + private static void updateTotalTime(Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics, boolean isRecording, boolean isPaused) { if (isRecording && !isPaused && tripStatistics != null) { - long time = tripStatistics.getTotalTime() + System.currentTimeMillis() - - tripStatistics.getStopTime(); + long time = tripStatistics.getTotalTime() + System.currentTimeMillis() - tripStatistics.getStopTime(); remoteViews.setChronometer(ids[3], SystemClock.elapsedRealtime() - time, null, true); remoteViews.setViewVisibility(ids[1], View.GONE); remoteViews.setViewVisibility(ids[2], View.GONE); @@ -295,8 +266,7 @@ public class TrackWidgetProvider extends AppWidgetProvider { remoteViews.setViewVisibility(ids[2], View.GONE); remoteViews.setViewVisibility(ids[3], View.GONE); - String totalTime = tripStatistics == null ? context.getString(R.string.value_unknown) - : StringUtils.formatElapsedTime(tripStatistics.getTotalTime()); + String totalTime = tripStatistics == null ? context.getString(R.string.value_unknown) : StringUtils.formatElapsedTime(tripStatistics.getTotalTime()); remoteViews.setTextViewText(ids[0], context.getString(R.string.stats_total_time)); remoteViews.setTextViewText(ids[1], totalTime); } @@ -312,10 +282,8 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param metricUnits true to use metric units * @param reportSpeed true to report speed */ - private static void updateAverageSpeed(Context context, RemoteViews remoteViews, int[] ids, - TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) { - String averageSpeedLabel = context.getString( - reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); + private static void updateAverageSpeed(Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) { + String averageSpeedLabel = context.getString(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); remoteViews.setTextViewText(ids[0], averageSpeedLabel); double speed = tripStatistics == null ? Double.NaN : tripStatistics.getAverageSpeed(); @@ -337,10 +305,8 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param ids the item's ids * @param tripStatistics the trip statistics */ - private static void updateMovingTime( - Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics) { - String movingTime = tripStatistics == null ? context.getString(R.string.value_unknown) - : StringUtils.formatElapsedTime(tripStatistics.getMovingTime()); + private static void updateMovingTime(Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics) { + String movingTime = tripStatistics == null ? context.getString(R.string.value_unknown) : StringUtils.formatElapsedTime(tripStatistics.getMovingTime()); remoteViews.setTextViewText(ids[0], context.getString(R.string.stats_moving_time)); remoteViews.setTextViewText(ids[1], movingTime); remoteViews.setViewVisibility(ids[2], View.GONE); @@ -356,10 +322,8 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param metricUnits true to use metric units * @param reportSpeed true to report speed */ - private static void updateAverageMovingSpeed(Context context, RemoteViews remoteViews, int[] ids, - TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) { - String averageMovingSpeedLabel = context.getString( - reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); + private static void updateAverageMovingSpeed(Context context, RemoteViews remoteViews, int[] ids, TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) { + String averageMovingSpeedLabel = context.getString(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); remoteViews.setTextViewText(ids[0], averageMovingSpeedLabel); double speed = tripStatistics == null ? Double.NaN : tripStatistics.getAverageMovingSpeed(); @@ -381,21 +345,16 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param isRecording true if recording * @param recordingTrackPaused true if recording track is paused */ - private static void updateRecordButton( - Context context, RemoteViews remoteViews, boolean isRecording, boolean recordingTrackPaused) { - remoteViews.setImageViewResource(R.id.track_widget_record_button, - isRecording && !recordingTrackPaused ? R.drawable.button_pause : R.drawable.button_record); + private static void updateRecordButton(Context context, RemoteViews remoteViews, boolean isRecording, boolean recordingTrackPaused) { + remoteViews.setImageViewResource(R.id.track_widget_record_button, isRecording && !recordingTrackPaused ? R.drawable.button_pause : R.drawable.button_record); int recordActionId; if (isRecording) { - recordActionId = recordingTrackPaused ? R.string.track_action_resume - : R.string.track_action_pause; + recordActionId = recordingTrackPaused ? R.string.track_action_resume : R.string.track_action_pause; } else { recordActionId = R.string.track_action_start; } - Intent intent = new Intent(context, ControlRecordingService.class).setAction( - context.getString(recordActionId)); - PendingIntent pendingIntent = PendingIntent.getService( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + Intent intent = new Intent(context, ControlRecordingService.class).setAction(context.getString(recordActionId)); + PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.track_widget_record_button, pendingIntent); } @@ -406,16 +365,12 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param remoteViews the remote views * @param isRecording true if recording */ - private static void updateStopButton( - Context context, RemoteViews remoteViews, boolean isRecording) { - remoteViews.setImageViewResource(R.id.track_widget_stop_button, - isRecording ? R.drawable.button_stop : R.drawable.ic_button_stop_disabled); + private static void updateStopButton(Context context, RemoteViews remoteViews, boolean isRecording) { + remoteViews.setImageViewResource(R.id.track_widget_stop_button, isRecording ? R.drawable.button_stop : R.drawable.ic_button_stop_disabled); remoteViews.setBoolean(R.id.track_widget_stop_button, "setEnabled", isRecording); if (isRecording) { - Intent intent = new Intent(context, ControlRecordingService.class).setAction( - context.getString(R.string.track_action_end)); - PendingIntent pendingIntent = PendingIntent.getService( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + Intent intent = new Intent(context, ControlRecordingService.class).setAction(context.getString(R.string.track_action_end)); + PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.track_widget_stop_button, pendingIntent); } } @@ -428,20 +383,17 @@ public class TrackWidgetProvider extends AppWidgetProvider { * @param isRecording true if recording * @param recordingTrackPaused true if recording track is paused */ - private static void updateRecordStatus( - Context context, RemoteViews remoteViews, boolean isRecording, boolean recordingTrackPaused) { + private static void updateRecordStatus(Context context, RemoteViews remoteViews, boolean isRecording, boolean recordingTrackPaused) { String status; int colorId; if (isRecording) { - status = context.getString( - recordingTrackPaused ? R.string.generic_paused : R.string.generic_recording); + status = context.getString(recordingTrackPaused ? R.string.generic_paused : R.string.generic_recording); colorId = recordingTrackPaused ? android.R.color.white : R.color.recording_text; } else { status = ""; colorId = android.R.color.white; } - remoteViews.setTextColor( - R.id.track_widget_record_status, context.getResources().getColor(colorId)); + remoteViews.setTextColor(R.id.track_widget_record_status, context.getResources().getColor(colorId)); remoteViews.setTextViewText(R.id.track_widget_record_status, status); } @@ -475,13 +427,11 @@ public class TrackWidgetProvider extends AppWidgetProvider { @TargetApi(16) @Override - public void onAppWidgetOptionsChanged( - Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { + public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); if (newOptions != null) { int newSize; - if (newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1) - == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) { + if (newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1) == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) { newSize = 1; } else { int height = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); diff --git a/src/main/res/values/preference_keys.xml b/src/main/res/values/preference_keys.xml index 4ae486dd7..027c0d96d 100644 --- a/src/main/res/values/preference_keys.xml +++ b/src/main/res/values/preference_keys.xml @@ -48,8 +48,6 @@ limitations under the License. settingsRecording settingsReset - settingsSensorBluetooth settingsSensorBluetoothPairing - settingsSensorRoot settingsStats \ No newline at end of file diff --git a/src/main/res/xml/settings.xml b/src/main/res/xml/settings.xml index 0c04fff26..165bfa646 100644 --- a/src/main/res/xml/settings.xml +++ b/src/main/res/xml/settings.xml @@ -59,10 +59,8 @@ limitations under the License. android:title="@string/settings_recording" />