forked from upstream-mirrors/OpenTracks
Cleanup: mainly code formatting and made LocationIterator implement autoclosable.
This commit is contained in:
@@ -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.
|
||||
* <p>
|
||||
* 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<Track> 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<Location> {
|
||||
interface LocationIterator extends Iterator<Location>, 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<TrackDataType> 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<TrackDataType> listeners) {
|
||||
void updateListeners(EnumSet<TrackDataType> listeners) {
|
||||
EnumSet<TrackDataType> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<ScoredResult> SCORED_RESULT_COMPARATOR =
|
||||
new Comparator<ScoredResult>() {
|
||||
@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<ScoredResult> SCORED_RESULT_COMPARATOR = new Comparator<ScoredResult>() {
|
||||
@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<ScoredResult> search(SearchQuery query) {
|
||||
ArrayList<Track> tracks = new ArrayList<>();
|
||||
ArrayList<Waypoint> waypoints = new ArrayList<>();
|
||||
TreeSet<ScoredResult> 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<Track> tracks) {
|
||||
private List<Track> retrieveTracks(SearchQuery query) {
|
||||
ArrayList<Track> 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<Waypoint> waypoints) {
|
||||
private List<Waypoint> retrieveWaypoints(SearchQuery query) {
|
||||
ArrayList<Waypoint> 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;
|
||||
|
||||
@@ -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}.
|
||||
* <p>
|
||||
*
|
||||
* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}.
|
||||
* <p>
|
||||
*
|
||||
* 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.
|
||||
|
||||
@@ -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<Location> locations = new ArrayList<>();
|
||||
private List<Location> locations = new ArrayList<>();
|
||||
|
||||
public Track() {
|
||||
}
|
||||
@@ -190,7 +195,7 @@ public class Track implements Parcelable {
|
||||
locations.add(location);
|
||||
}
|
||||
|
||||
public ArrayList<Location> getLocations() {
|
||||
public List<Location> getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners
|
||||
: Collections.<TrackDataListener>emptySet();
|
||||
Set<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.<TrackDataListener>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<TrackDataListener> sampledInListeners, Set<TrackDataListener> sampledOutListeners) {
|
||||
private void notifyTrackPointsTableUpdate(boolean updateSamplingState, Set<TrackDataListener> sampledInListeners, Set<TrackDataListener> 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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<TrackDataListener, EnumSet<TrackDataType>>
|
||||
listenerToTypesMap = new HashMap<>();
|
||||
private final Map<TrackDataListener, EnumSet<TrackDataType>> listenerToTypesMap = new HashMap<>();
|
||||
|
||||
// Map of track data type to listeners
|
||||
private final Map<TrackDataType, Set<TrackDataListener>>
|
||||
typeToListenersMap = new EnumMap<>(TrackDataType.class);
|
||||
private final Map<TrackDataType, Set<TrackDataListener>> typeToListenersMap = new EnumMap<>(TrackDataType.class);
|
||||
|
||||
public TrackDataManager() {
|
||||
TrackDataManager() {
|
||||
for (TrackDataType trackDataType : TrackDataType.values()) {
|
||||
typeToListenersMap.put(trackDataType, new LinkedHashSet<TrackDataListener>());
|
||||
}
|
||||
@@ -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<TrackDataType> trackDataTypes) {
|
||||
void registerListener(TrackDataListener listener, EnumSet<TrackDataType> 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<TrackDataType> 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<TrackDataType> getTrackDataTypes(TrackDataListener listener) {
|
||||
EnumSet<TrackDataType> getTrackDataTypes(TrackDataListener listener) {
|
||||
return listenerToTypesMap.get(listener);
|
||||
}
|
||||
|
||||
@@ -106,14 +100,14 @@ public class TrackDataManager {
|
||||
*
|
||||
* @param type the type
|
||||
*/
|
||||
public Set<TrackDataListener> getListeners(TrackDataType type) {
|
||||
Set<TrackDataListener> getListeners(TrackDataType type) {
|
||||
return typeToListenersMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the registered {@link TrackDataType}.
|
||||
*/
|
||||
public EnumSet<TrackDataType> getRegisteredTrackDataTypes() {
|
||||
EnumSet<TrackDataType> getRegisteredTrackDataTypes() {
|
||||
EnumSet<TrackDataType> types = EnumSet.noneOf(TrackDataType.class);
|
||||
for (EnumSet<TrackDataType> value : listenerToTypesMap.values()) {
|
||||
types.addAll(value);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user