forked from upstream-mirrors/OpenTracks
Merged Rodrigo's changes.
This commit is contained in:
@@ -70,8 +70,9 @@ import android.widget.Toast;
|
|||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksMap extends MapActivity
|
public class MyTracksMap extends MapActivity
|
||||||
implements LocationListener, SensorEventListener, View.OnTouchListener,
|
implements View.OnTouchListener, View.OnClickListener,
|
||||||
View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
private static final int TRACKPOINT_BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
// Saved instance state keys:
|
// Saved instance state keys:
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@@ -82,9 +83,9 @@ public class MyTracksMap extends MapActivity
|
|||||||
public static final String KEY_HAVE_GOOD_FIX = "haveGoodFix";
|
public static final String KEY_HAVE_GOOD_FIX = "haveGoodFix";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently selected track (or null if nothing selected).
|
* The ID of the currently selected track (or -1 if nothing selected).
|
||||||
*/
|
*/
|
||||||
private Track selectedTrack;
|
private long selectedTrackId = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The id of the currently recording track.
|
* The id of the currently recording track.
|
||||||
@@ -97,13 +98,19 @@ public class MyTracksMap extends MapActivity
|
|||||||
*/
|
*/
|
||||||
private boolean keepMyLocationVisible;
|
private boolean keepMyLocationVisible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of the first location that was seen when reading tracks from the
|
||||||
|
* provider.
|
||||||
|
*/
|
||||||
|
private long firstSeenLocationId = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the last location that was seen when reading tracks from the
|
* Id of the last location that was seen when reading tracks from the
|
||||||
* provider. This is used to determine which locations are new compared to the
|
* provider. This is used to determine which locations are new compared to the
|
||||||
* last time the mapOverlay was updated.
|
* last time the mapOverlay was updated.
|
||||||
*/
|
*/
|
||||||
private long lastSeenLocationId = -1;
|
private long lastSeenLocationId = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magnetic variation.
|
* Magnetic variation.
|
||||||
*/
|
*/
|
||||||
@@ -130,19 +137,13 @@ public class MyTracksMap extends MapActivity
|
|||||||
* A thread with a looper. Post to updateTrackHandler to execute Runnables on
|
* A thread with a looper. Post to updateTrackHandler to execute Runnables on
|
||||||
* this thread.
|
* this thread.
|
||||||
*/
|
*/
|
||||||
private final HandlerThread updateTrackThread =
|
private HandlerThread updateTrackThread;
|
||||||
new HandlerThread("updateTrackThread");
|
|
||||||
|
|
||||||
/** Handler for updateTrackThread */
|
/** Handler for updateTrackThread */
|
||||||
private Handler updateTrackHandler;
|
private Handler updateTrackHandler;
|
||||||
|
|
||||||
private MyTracksProviderUtils providerUtils;
|
private MyTracksProviderUtils providerUtils;
|
||||||
|
|
||||||
/**
|
|
||||||
* This value is used to decide how many points to display.
|
|
||||||
*/
|
|
||||||
private int samplingFrequency = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A runnable that updates the track from the provider (looking for points
|
* A runnable that updates the track from the provider (looking for points
|
||||||
* added after "lastSeenLocationId".
|
* added after "lastSeenLocationId".
|
||||||
@@ -150,7 +151,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
private final Runnable updateTrackRunnable = new Runnable() {
|
private final Runnable updateTrackRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (selectedTrack == null) {
|
if (!isATrackSelected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
readAllNewTrackPoints();
|
readAllNewTrackPoints();
|
||||||
@@ -163,11 +164,12 @@ public class MyTracksMap extends MapActivity
|
|||||||
private Runnable restoreTrackRunnable = new Runnable() {
|
private Runnable restoreTrackRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (selectedTrack == null) {
|
if (!isATrackSelected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mapOverlay.clearPoints();
|
mapOverlay.clearPoints();
|
||||||
lastSeenLocationId = selectedTrack.getStartId();
|
firstSeenLocationId = -1;
|
||||||
|
lastSeenLocationId = -1;
|
||||||
readAllNewTrackPoints();
|
readAllNewTrackPoints();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -178,7 +180,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
private final Runnable restoreWaypointsRunnable = new Runnable() {
|
private final Runnable restoreWaypointsRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (selectedTrack == null) {
|
if (!isATrackSelected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +190,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
// We will silently drop extra waypoints to make the app responsive.
|
// We will silently drop extra waypoints to make the app responsive.
|
||||||
// TODO: Try to only load the waypoints in the view port.
|
// TODO: Try to only load the waypoints in the view port.
|
||||||
cursor = providerUtils.getWaypointsCursor(
|
cursor = providerUtils.getWaypointsCursor(
|
||||||
selectedTrack.getId(), 0,
|
selectedTrackId, 0,
|
||||||
MyTracksConstants.MAX_DISPLAYED_WAYPOINTS_POINTS);
|
MyTracksConstants.MAX_DISPLAYED_WAYPOINTS_POINTS);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
@@ -219,10 +221,9 @@ public class MyTracksMap extends MapActivity
|
|||||||
public void run() {
|
public void run() {
|
||||||
uiHandler.post(new Runnable() {
|
uiHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
showTrack(selectedTrack);
|
showTrack(selectedTrackId);
|
||||||
mapOverlay.setSelectedTrack(selectedTrack);
|
mapOverlay.setTrackDrawingEnabled(isATrackSelected());
|
||||||
mapOverlay.setShowEndMarker(selectedTrack == null ||
|
mapOverlay.setShowEndMarker(!isRecordingSelected());
|
||||||
selectedTrack.getId() != recordingTrackId);
|
|
||||||
mapView.invalidate();
|
mapView.invalidate();
|
||||||
busyPane.setVisibility(View.GONE);
|
busyPane.setVisibility(View.GONE);
|
||||||
updateOptionsButton();
|
updateOptionsButton();
|
||||||
@@ -316,6 +317,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
locationManager =
|
locationManager =
|
||||||
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
|
||||||
|
updateTrackThread = new HandlerThread("updateTrackThread");
|
||||||
updateTrackThread.start();
|
updateTrackThread.start();
|
||||||
updateTrackHandler = new Handler(updateTrackThread.getLooper());
|
updateTrackHandler = new Handler(updateTrackThread.getLooper());
|
||||||
|
|
||||||
@@ -331,8 +333,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
// No track is being recorded. We should not be here.
|
// No track is being recorded. We should not be here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedTrack == null
|
if (!isRecordingSelected()) {
|
||||||
|| selectedTrack.getId() != recordingTrackId) {
|
|
||||||
// No track, or one other than the recording track is selected,
|
// No track, or one other than the recording track is selected,
|
||||||
// don't bother.
|
// don't bother.
|
||||||
return;
|
return;
|
||||||
@@ -348,7 +349,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(MyTracksConstants.TAG,
|
||||||
"MyTracksMap: ContentObserver.onChange waypoints");
|
"MyTracksMap: ContentObserver.onChange waypoints");
|
||||||
if (selectedTrack == null) {
|
if (!isATrackSelected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateTrackHandler.post(restoreWaypointsRunnable);
|
updateTrackHandler.post(restoreWaypointsRunnable);
|
||||||
@@ -375,6 +376,21 @@ public class MyTracksMap extends MapActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether there's a track currently selected for display.
|
||||||
|
*/
|
||||||
|
private boolean isATrackSelected() {
|
||||||
|
return selectedTrackId >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether we're currently recording the same track that's selected
|
||||||
|
* for display.
|
||||||
|
*/
|
||||||
|
private boolean isRecordingSelected() {
|
||||||
|
return isATrackSelected() && selectedTrackId == recordingTrackId;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setupZoomControls() {
|
protected void setupZoomControls() {
|
||||||
mapView.setBuiltInZoomControls(true);
|
mapView.setBuiltInZoomControls(true);
|
||||||
}
|
}
|
||||||
@@ -384,6 +400,9 @@ public class MyTracksMap extends MapActivity
|
|||||||
// Final cleanup before activity is destroyed.
|
// Final cleanup before activity is destroyed.
|
||||||
// May not be called at all in some situations.
|
// May not be called at all in some situations.
|
||||||
Log.d(MyTracksConstants.TAG, "MyTracksMap.onDestroy");
|
Log.d(MyTracksConstants.TAG, "MyTracksMap.onDestroy");
|
||||||
|
|
||||||
|
updateTrackThread.quit();
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,10 +468,9 @@ public class MyTracksMap extends MapActivity
|
|||||||
|
|
||||||
// While this activity was paused the user may have deleted the selected
|
// While this activity was paused the user may have deleted the selected
|
||||||
// track. In that case the map overlay needs to be cleared:
|
// track. In that case the map overlay needs to be cleared:
|
||||||
Track track = mapOverlay.getSelectedTrack();
|
if (isATrackSelected() && !providerUtils.trackExists(selectedTrackId)) {
|
||||||
if (track != null && !providerUtils.trackExists(track.getId())) {
|
|
||||||
// The recording track must have been deleted meanwhile.
|
// The recording track must have been deleted meanwhile.
|
||||||
mapOverlay.setSelectedTrack(null);
|
mapOverlay.setTrackDrawingEnabled(false);
|
||||||
mapView.invalidate();
|
mapView.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,10 +532,10 @@ public class MyTracksMap extends MapActivity
|
|||||||
+ gpsProvider.getName());
|
+ gpsProvider.getName());
|
||||||
}
|
}
|
||||||
locationManager.requestLocationUpdates(gpsProvider.getName(),
|
locationManager.requestLocationUpdates(gpsProvider.getName(),
|
||||||
0 /*minTime*/, 0 /*minDist*/, this);
|
0 /*minTime*/, 0 /*minDist*/, locationListener);
|
||||||
try {
|
try {
|
||||||
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
|
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
|
||||||
1000 * 60 * 5 /*minTime*/, 0 /*minDist*/, this);
|
1000 * 60 * 5 /*minTime*/, 0 /*minDist*/, locationListener);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// If anything at all goes wrong with getting a cell location do not
|
// If anything at all goes wrong with getting a cell location do not
|
||||||
// abort. Cell location is not essential to this app.
|
// abort. Cell location is not essential to this app.
|
||||||
@@ -535,7 +553,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(MyTracksConstants.TAG,
|
||||||
"MyTracksMap: Now registering sensor listeners.");
|
"MyTracksMap: Now registering sensor listeners.");
|
||||||
sensorManager.registerListener(
|
sensorManager.registerListener(
|
||||||
this, compass, SensorManager.SENSOR_DELAY_UI);
|
sensorListener, compass, SensorManager.SENSOR_DELAY_UI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -545,12 +563,12 @@ public class MyTracksMap extends MapActivity
|
|||||||
if (locationManager != null) {
|
if (locationManager != null) {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(MyTracksConstants.TAG,
|
||||||
"MyTracksMap: Now unregistering location listeners.");
|
"MyTracksMap: Now unregistering location listeners.");
|
||||||
locationManager.removeUpdates(this);
|
locationManager.removeUpdates(locationListener);
|
||||||
}
|
}
|
||||||
if (sensorManager != null) {
|
if (sensorManager != null) {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(MyTracksConstants.TAG,
|
||||||
"MyTracksMap: Now unregistering sensor listeners.");
|
"MyTracksMap: Now unregistering sensor listeners.");
|
||||||
sensorManager.unregisterListener(this);
|
sensorManager.unregisterListener(sensorListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,7 +597,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
*/
|
*/
|
||||||
private void updateOptionsButton() {
|
private void updateOptionsButton() {
|
||||||
optionsBtn.setVisibility(
|
optionsBtn.setVisibility(
|
||||||
selectedTrack != null ? View.VISIBLE : View.INVISIBLE);
|
isATrackSelected() ? View.VISIBLE : View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -632,12 +650,18 @@ public class MyTracksMap extends MapActivity
|
|||||||
/**
|
/**
|
||||||
* Zooms and pans the map so that the given track is visible.
|
* Zooms and pans the map so that the given track is visible.
|
||||||
*
|
*
|
||||||
* @param track a given track
|
* @param trackId a given track ID
|
||||||
*/
|
*/
|
||||||
public void showTrack(Track track) {
|
public void showTrack(long trackId) {
|
||||||
if (track == null || mapView == null || track.getNumberOfPoints() < 2) {
|
if (mapView == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Track track = providerUtils.getTrack(trackId);
|
||||||
|
if (track == null || track.getNumberOfPoints() < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TripStatistics stats = track.getStatistics();
|
TripStatistics stats = track.getStatistics();
|
||||||
int bottom = stats.getBottom();
|
int bottom = stats.getBottom();
|
||||||
int left = stats.getLeft();
|
int left = stats.getLeft();
|
||||||
@@ -680,24 +704,30 @@ public class MyTracksMap extends MapActivity
|
|||||||
* @param trackId a given track id
|
* @param trackId a given track id
|
||||||
*/
|
*/
|
||||||
public void setSelectedTrack(final long trackId) {
|
public void setSelectedTrack(final long trackId) {
|
||||||
if (selectedTrack != null && selectedTrack.getId() == trackId) {
|
if (selectedTrackId == trackId) {
|
||||||
// Selected track did not change, nothing to do.
|
// Selected track did not change, nothing to do.
|
||||||
mapOverlay.setSelectedTrack(selectedTrack);
|
mapOverlay.setTrackDrawingEnabled(isATrackSelected());
|
||||||
mapView.invalidate();
|
mapView.invalidate();
|
||||||
updateOptionsButton();
|
updateOptionsButton();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackId < 0) {
|
if (trackId < 0) {
|
||||||
// Remove selection.
|
// Remove selection.
|
||||||
selectedTrack = null;
|
selectedTrackId = -1;
|
||||||
mapOverlay.setSelectedTrack(null);
|
mapOverlay.setTrackDrawingEnabled(false);
|
||||||
mapOverlay.clearWaypoints();
|
mapOverlay.clearWaypoints();
|
||||||
updateOptionsButton();
|
updateOptionsButton();
|
||||||
mapView.invalidate();
|
mapView.invalidate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
busyPane.setVisibility(View.VISIBLE);
|
busyPane.setVisibility(View.VISIBLE);
|
||||||
selectedTrack = providerUtils.getTrack(trackId);
|
selectedTrackId = trackId;
|
||||||
|
loadSelectedTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSelectedTrack() {
|
||||||
updateTrackHandler.post(restoreTrackRunnable);
|
updateTrackHandler.post(restoreTrackRunnable);
|
||||||
updateTrackHandler.post(restoreWaypointsRunnable);
|
updateTrackHandler.post(restoreWaypointsRunnable);
|
||||||
updateTrackHandler.post(setSelectedTrackRunnable);
|
updateTrackHandler.post(setSelectedTrackRunnable);
|
||||||
@@ -753,8 +783,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
menu.setHeaderTitle(R.string.tracklist_this_track);
|
menu.setHeaderTitle(R.string.tracklist_this_track);
|
||||||
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
|
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
|
||||||
R.string.tracklist_edit_track);
|
R.string.tracklist_edit_track);
|
||||||
if (!MyTracks.getInstance().isRecording() || (selectedTrack != null
|
if (!MyTracks.getInstance().isRecording() || !isRecordingSelected()) {
|
||||||
&& selectedTrack.getId() != recordingTrackId)) {
|
|
||||||
menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0,
|
menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0,
|
||||||
R.string.tracklist_send_to_google);
|
R.string.tracklist_send_to_google);
|
||||||
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
|
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
|
||||||
@@ -791,7 +820,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
if (!super.onMenuItemSelected(featureId, item)) {
|
if (!super.onMenuItemSelected(featureId, item)) {
|
||||||
if (selectedTrack != null) {
|
if (isATrackSelected()) {
|
||||||
MyTracks.getInstance().onActivityResult(
|
MyTracks.getInstance().onActivityResult(
|
||||||
MyTracksConstants.getActionFromMenuId(item.getItemId()), RESULT_OK,
|
MyTracksConstants.getActionFromMenuId(item.getItemId()), RESULT_OK,
|
||||||
new Intent());
|
new Intent());
|
||||||
@@ -852,8 +881,7 @@ public class MyTracksMap extends MapActivity
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v == messagePane) {
|
if (v == messagePane) {
|
||||||
launchMyLocationSettings();
|
launchMyLocationSettings();
|
||||||
}
|
} else if (v == optionsBtn) {
|
||||||
if (v == optionsBtn) {
|
|
||||||
optionsBtn.performLongClick();
|
optionsBtn.performLongClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -895,9 +923,8 @@ public class MyTracksMap extends MapActivity
|
|||||||
sharedPreferences.getLong(
|
sharedPreferences.getLong(
|
||||||
getString(R.string.recording_track_key),
|
getString(R.string.recording_track_key),
|
||||||
-1);
|
-1);
|
||||||
if (selectedTrack != null) {
|
if (isATrackSelected()) {
|
||||||
mapOverlay.setShowEndMarker(
|
mapOverlay.setShowEndMarker(!isRecordingSelected());
|
||||||
selectedTrack.getId() != recordingTrackId);
|
|
||||||
mapView.postInvalidate();
|
mapView.postInvalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -906,136 +933,139 @@ public class MyTracksMap extends MapActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private final LocationListener locationListener = new LocationListener() {
|
||||||
public void onProviderEnabled(String provider) {
|
@Override
|
||||||
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
public void onProviderEnabled(String provider) {
|
||||||
messageText.setText(R.string.wait_for_fix);
|
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
||||||
}
|
messageText.setText(R.string.wait_for_fix);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderDisabled(String provider) {
|
|
||||||
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
|
||||||
messageText.setText(R.string.status_enable_gps);
|
|
||||||
messagePane.setVisibility(View.VISIBLE);
|
|
||||||
messagePane.setOnClickListener(this);
|
|
||||||
screen.requestLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Location location) {
|
|
||||||
if (location.getProvider().equals(MyTracksConstants.GPS_PROVIDER)) {
|
|
||||||
// Recalculate the variation if there was a jump in location > 1km:
|
|
||||||
if (currentLocation == null
|
|
||||||
|| location.distanceTo(currentLocation) > 1000) {
|
|
||||||
setVariation(location);
|
|
||||||
}
|
}
|
||||||
currentLocation = location;
|
}
|
||||||
boolean haveGoodFixNow =
|
|
||||||
currentLocation.getAccuracy() < minRequiredAccuracy;
|
@Override
|
||||||
if (haveGoodFixNow != haveGoodFix) {
|
public void onProviderDisabled(String provider) {
|
||||||
haveGoodFix = haveGoodFixNow;
|
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
||||||
messagePane.setVisibility(haveGoodFix ? View.GONE : View.VISIBLE);
|
messageText.setText(R.string.status_enable_gps);
|
||||||
|
messagePane.setVisibility(View.VISIBLE);
|
||||||
|
messagePane.setOnClickListener(MyTracksMap.this);
|
||||||
screen.requestLayout();
|
screen.requestLayout();
|
||||||
}
|
}
|
||||||
showCurrentLocation();
|
|
||||||
} else {
|
|
||||||
Log.d(MyTracksConstants.TAG,
|
|
||||||
"MyTracksMap: Network location update received.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
public void onLocationChanged(Location location) {
|
||||||
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
if (location.getProvider().equals(MyTracksConstants.GPS_PROVIDER)) {
|
||||||
switch (status) {
|
// Recalculate the variation if there was a jump in location > 1km:
|
||||||
case LocationProvider.OUT_OF_SERVICE:
|
if (currentLocation == null
|
||||||
case LocationProvider.TEMPORARILY_UNAVAILABLE:
|
|| location.distanceTo(currentLocation) > 1000) {
|
||||||
haveGoodFix = false;
|
setVariation(location);
|
||||||
messagePane.setVisibility(View.VISIBLE);
|
}
|
||||||
|
currentLocation = location;
|
||||||
|
boolean haveGoodFixNow =
|
||||||
|
currentLocation.getAccuracy() < minRequiredAccuracy;
|
||||||
|
if (haveGoodFixNow != haveGoodFix) {
|
||||||
|
haveGoodFix = haveGoodFixNow;
|
||||||
|
messagePane.setVisibility(haveGoodFix ? View.GONE : View.VISIBLE);
|
||||||
screen.requestLayout();
|
screen.requestLayout();
|
||||||
break;
|
}
|
||||||
|
showCurrentLocation();
|
||||||
|
} else {
|
||||||
|
Log.d(MyTracksConstants.TAG,
|
||||||
|
"MyTracksMap: Network location update received.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSensorChanged(SensorEvent se) {
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
synchronized (this) {
|
if (provider.equals(MyTracksConstants.GPS_PROVIDER)) {
|
||||||
float magneticHeading = se.values[0];
|
switch (status) {
|
||||||
double heading = magneticHeading + variation;
|
case LocationProvider.OUT_OF_SERVICE:
|
||||||
if (mapOverlay.setHeading((float) heading)) {
|
case LocationProvider.TEMPORARILY_UNAVAILABLE:
|
||||||
mapView.invalidate();
|
haveGoodFix = false;
|
||||||
|
messagePane.setVisibility(View.VISIBLE);
|
||||||
|
screen.requestLayout();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
@Override
|
private final SensorEventListener sensorListener = new SensorEventListener() {
|
||||||
public void onAccuracyChanged(Sensor s, int accuracy) {
|
@Override
|
||||||
// do nothing
|
public void onSensorChanged(SensorEvent se) {
|
||||||
}
|
synchronized (this) {
|
||||||
|
float magneticHeading = se.values[0];
|
||||||
/**
|
double heading = magneticHeading + variation;
|
||||||
* Set the sampling frequency from the total number of points in the track.
|
if (mapOverlay.setHeading((float) heading)) {
|
||||||
*
|
mapView.invalidate();
|
||||||
* @param track The track to read the total number of points from.
|
}
|
||||||
*/
|
}
|
||||||
private void setSamplingFrequency(Track track) {
|
}
|
||||||
long totalLocations = track.getStopId() - track.getStartId();
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor s, int accuracy) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Limit the number of map points readings.
|
|
||||||
samplingFrequency =
|
|
||||||
(int) (1 +
|
|
||||||
totalLocations / MyTracksConstants.TARGET_DISPLAYED_TRACK_POINTS);
|
|
||||||
Log.i(MyTracksConstants.TAG, "Sampling locations: " + samplingFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readAllNewTrackPoints() {
|
private void readAllNewTrackPoints() {
|
||||||
Cursor cursor = null;
|
int numPoints = mapOverlay.getNumLocations();
|
||||||
// Refetch the track to get the latest StopId
|
if (numPoints >= MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS) {
|
||||||
selectedTrack = providerUtils.getTrack(selectedTrack.getId());
|
// We're about to exceed the maximum allowed number of points, so reload
|
||||||
long totalLocations = selectedTrack.getStopId() -
|
// the whole track with fewer points (the sampling frequency will be
|
||||||
selectedTrack.getStartId();
|
// lower).
|
||||||
|
loadSelectedTrack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lastStoredLocationId =
|
||||||
|
providerUtils.getLastLocationId(selectedTrackId);
|
||||||
|
int samplingFrequency = -1;
|
||||||
|
for (;;) {
|
||||||
|
Cursor cursor = null;
|
||||||
|
try {
|
||||||
|
cursor = providerUtils.getLocationsCursor(selectedTrackId,
|
||||||
|
lastSeenLocationId + 1, TRACKPOINT_BUFFER_SIZE, false);
|
||||||
|
if (cursor == null || !cursor.moveToFirst()) {
|
||||||
|
// No (more) data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
setSamplingFrequency(selectedTrack);
|
|
||||||
int bufferSize = 1024;
|
|
||||||
int points = 0;
|
|
||||||
long tailLocationId = selectedTrack.getStopId() - 10;
|
|
||||||
Location location;
|
|
||||||
while (lastSeenLocationId < (selectedTrack.getStopId() + 10)) {
|
|
||||||
cursor = providerUtils.getLocationsCursor(
|
|
||||||
selectedTrack.getId(), lastSeenLocationId + 1, bufferSize, false);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
final int idColumnIdx = cursor.getColumnIndexOrThrow(
|
final int idColumnIdx = cursor.getColumnIndexOrThrow(
|
||||||
TrackPointsColumns._ID);
|
TrackPointsColumns._ID);
|
||||||
do {
|
do {
|
||||||
points++;
|
long locationId = cursor.getLong(idColumnIdx);
|
||||||
location = providerUtils.createLocation(cursor);
|
lastSeenLocationId = locationId;
|
||||||
lastSeenLocationId = cursor.getLong(idColumnIdx);
|
if (firstSeenLocationId == -1) {
|
||||||
// Include a point if it fits one of the following criteria:
|
// This was our first point, keep its ID
|
||||||
// - Has the mod for the sampling frequency.
|
firstSeenLocationId = locationId;
|
||||||
// - Is the first point.
|
|
||||||
// - Is on of the last n points.
|
|
||||||
// => This is to make sure we draw the last points people are probably zoomed in to.
|
|
||||||
if (!MyTracksUtils.isValidLocation(location) ||
|
|
||||||
points % samplingFrequency == 0 ||
|
|
||||||
points == 0 ||
|
|
||||||
lastSeenLocationId > tailLocationId) {
|
|
||||||
mapOverlay.addLocation(new Location(location));
|
|
||||||
}
|
}
|
||||||
|
if (samplingFrequency == -1) {
|
||||||
|
// Now we already have at least one point, calculate the sampling
|
||||||
|
// frequency
|
||||||
|
long numTotalPoints = lastStoredLocationId - firstSeenLocationId;
|
||||||
|
samplingFrequency = (int) (1 +
|
||||||
|
numTotalPoints / MyTracksConstants.TARGET_DISPLAYED_TRACK_POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = providerUtils.createLocation(cursor);
|
||||||
|
|
||||||
|
// Include a point if it fits one of the following criteria:
|
||||||
|
// - Has the mod for the sampling frequency (includes first point).
|
||||||
|
// - Is the last point and we are not recording this track.
|
||||||
|
// - The point is a segment split
|
||||||
|
if (numPoints % samplingFrequency == 0 ||
|
||||||
|
(!isRecordingSelected() && locationId == lastStoredLocationId) ||
|
||||||
|
!MyTracksUtils.isValidLocation(location)) {
|
||||||
|
mapOverlay.addLocation(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
numPoints++;
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
} else {
|
} finally {
|
||||||
// TODO this is wrong sometimes. Should just return.
|
if (cursor != null) {
|
||||||
if (lastSeenLocationId >= selectedTrack.getStopId()) {
|
|
||||||
cursor.close();
|
cursor.close();
|
||||||
mapView.postInvalidate();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
lastSeenLocationId += bufferSize;
|
|
||||||
}
|
}
|
||||||
cursor.close();
|
|
||||||
cursor = null;
|
|
||||||
}
|
}
|
||||||
mapView.postInvalidate();
|
mapView.postInvalidate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
||||||
|
|
||||||
import com.google.android.maps.GeoPoint;
|
import com.google.android.maps.GeoPoint;
|
||||||
import com.google.android.maps.MapView;
|
import com.google.android.maps.MapView;
|
||||||
import com.google.android.maps.Overlay;
|
import com.google.android.maps.Overlay;
|
||||||
@@ -58,7 +56,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
private final ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>();
|
private final ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>();
|
||||||
private final ArrayList<Location> points = new ArrayList<Location>(1024);
|
private final ArrayList<Location> points = new ArrayList<Location>(1024);
|
||||||
|
|
||||||
private Track selectedTrack;
|
private boolean trackDrawingEnabled;
|
||||||
private int lastHeading = 0;
|
private int lastHeading = 0;
|
||||||
private Location myLocation;
|
private Location myLocation;
|
||||||
private boolean showEndMarker = true;
|
private boolean showEndMarker = true;
|
||||||
@@ -122,14 +120,6 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
errorCirclePaint.setAntiAlias(true);
|
errorCirclePaint.setAntiAlias(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedTrack(Track track) {
|
|
||||||
selectedTrack = track;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Track getSelectedTrack() {
|
|
||||||
return selectedTrack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a location to the map overlay.
|
* Add a location to the map overlay.
|
||||||
*
|
*
|
||||||
@@ -145,6 +135,10 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
waypoints.add(wpt);
|
waypoints.add(wpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNumLocations() {
|
||||||
|
return points.size();
|
||||||
|
}
|
||||||
|
|
||||||
public void clearWaypoints() {
|
public void clearWaypoints() {
|
||||||
waypoints.clear();
|
waypoints.clear();
|
||||||
}
|
}
|
||||||
@@ -153,21 +147,33 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
points.clear();
|
points.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTrackDrawingEnabled(boolean trackDrawingEnabled) {
|
||||||
|
this.trackDrawingEnabled = trackDrawingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public void setShowEndMarker(boolean showEndMarker) {
|
public void setShowEndMarker(boolean showEndMarker) {
|
||||||
this.showEndMarker = showEndMarker;
|
this.showEndMarker = showEndMarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
|
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
|
||||||
|
|
||||||
if (shadow) {
|
if (shadow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the selected track:
|
if (trackDrawingEnabled) {
|
||||||
drawTrack(canvas, mapView, selectedTrack, true);
|
// Draw the selected track:
|
||||||
|
drawTrack(canvas, mapView);
|
||||||
|
|
||||||
// Draw the waypoints:
|
// Draw the waypoints:
|
||||||
|
drawWaypoints(canvas, mapView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the current location
|
||||||
|
drawMyLocation(canvas, mapView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawWaypoints(Canvas canvas, MapView mapView) {
|
||||||
ArrayList<Waypoint> currentWaypoints = waypoints;
|
ArrayList<Waypoint> currentWaypoints = waypoints;
|
||||||
for (int i = 1; i < currentWaypoints.size(); i++) {
|
for (int i = 1; i < currentWaypoints.size(); i++) {
|
||||||
Waypoint wpt = currentWaypoints.get(i);
|
Waypoint wpt = currentWaypoints.get(i);
|
||||||
@@ -190,11 +196,14 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
}
|
}
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawMyLocation(Canvas canvas, MapView mapView) {
|
||||||
// Draw the arrow icon:
|
// Draw the arrow icon:
|
||||||
if (myLocation == null) {
|
if (myLocation == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeoPoint geoPoint = new GeoPoint(
|
GeoPoint geoPoint = new GeoPoint(
|
||||||
(int) (myLocation.getLatitude() * 1E6),
|
(int) (myLocation.getLatitude() * 1E6),
|
||||||
(int) (myLocation.getLongitude() * 1E6));
|
(int) (myLocation.getLongitude() * 1E6));
|
||||||
@@ -211,12 +220,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
canvas.drawCircle(pt.x, pt.y, radius, errorCirclePaint);
|
canvas.drawCircle(pt.x, pt.y, radius, errorCirclePaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawTrack(Canvas canvas, MapView mapView, Track track,
|
private void drawTrack(Canvas canvas, MapView mapView) {
|
||||||
boolean selected) {
|
|
||||||
|
|
||||||
if (track == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (points.size() < 2) {
|
if (points.size() < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user