diff --git a/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java b/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java index 6eb1934d7..9c6b01d08 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java @@ -255,17 +255,18 @@ public class MapActivity extends com.google.android.maps.MapActivity * the current location is outside the visible area. */ private void showCurrentLocation() { - if (currentLocation == null || mapOverlay == null || mapView == null) { + if (mapOverlay == null || mapView == null) { return; } + mapOverlay.setMyLocation(currentLocation); mapView.postInvalidate(); - if (keepMyLocationVisible && !locationIsVisible(currentLocation)) { + + if (currentLocation != null && keepMyLocationVisible && !locationIsVisible(currentLocation)) { GeoPoint geoPoint = LocationUtils.getGeoPoint(currentLocation); MapController controller = mapView.getController(); controller.animateTo(geoPoint); } - } @Override @@ -507,10 +508,6 @@ public class MapActivity extends com.google.android.maps.MapActivity @Override public void onCurrentLocationChanged(Location location) { - if (!location.getProvider().equals(LocationManager.GPS_PROVIDER)) { - return; - } - currentLocation = location; showCurrentLocation(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java index 06a3e7c46..e73111291 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java @@ -19,16 +19,15 @@ import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TrackDataHub; +import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType; import com.google.android.apps.mytracks.content.TrackDataListener; import com.google.android.apps.mytracks.content.Waypoint; -import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType; import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory; import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.maps.mytracks.R; import android.app.Activity; import android.location.Location; -import android.location.LocationManager; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; @@ -261,15 +260,15 @@ public class StatsActivity extends Activity implements TrackDataListener { @Override public void onCurrentLocationChanged(final Location loc) { - if (!loc.getProvider().equals(LocationManager.GPS_PROVIDER)) { - return; - } - if (dataHub.isRecordingSelected()) { runOnUiThread(new Runnable() { @Override public void run() { - showLocation(loc); + if (loc != null) { + showLocation(loc); + } else { + showUnknownLocation(); + } } }); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java b/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java index 561d53b2b..8d1dd590d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java @@ -16,6 +16,7 @@ package com.google.android.apps.mytracks.content; import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS; +import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.Constants; @@ -346,7 +347,7 @@ public class TrackDataHub { loadSharedPreferences(); } long recordingTrackId = preferences.getLong(RECORDING_TRACK_KEY, -1); - return recordingTrackId > 0 && recordingTrackId == selectedTrackId; + return recordingTrackId > 0 && recordingTrackId == selectedTrackId; } /** @@ -463,11 +464,20 @@ public class TrackDataHub { boolean interestedInSampledOutPoints = registration.isInterestedIn(ListenerDataType.SAMPLED_OUT_POINT_UPDATES); if (interestedInPoints || interestedInSampledOutPoints) { - if (reloadAll) notifyPointsCleared(listenerSet); + long minPointId = 0; + int previousNumPoints = 0; + if (reloadAll) { + // Clear existing points and send them all again + notifyPointsCleared(listenerSet); + } else { + // Send only new points + minPointId = registration.lastPointId + 1; + previousNumPoints = registration.numLoadedPoints; + } notifyPointsUpdated(false, - reloadAll ? 0 : registration.lastPointId + 1, - reloadAll ? 0 : registration.numLoadedPoints, + minPointId, + previousNumPoints, listenerSet, interestedInSampledOutPoints ? listenerSet : Collections.EMPTY_SET); } @@ -650,7 +660,7 @@ public class TrackDataHub { * @param forceUpdate whether to force the notifications to happen * @param listeners the listeners to notify */ - private void notifyLocationChanged(final Location location, boolean forceUpdate, + private void notifyLocationChanged(Location location, boolean forceUpdate, final Set listeners) { if (location == null) return; if (listeners.isEmpty()) return; @@ -660,26 +670,56 @@ public class TrackDataHub { boolean oldHasFix = hasFix; boolean oldHasGoodFix = hasGoodFix; - // We consider a good fix to be a recent one with reasonable accuracy. + long now = System.currentTimeMillis(); if (isGpsLocation) { - lastSeenLocation = location; - hasFix = (location != null && System.currentTimeMillis() - location.getTime() <= MAX_LOCATION_AGE_MS); + // We consider a good fix to be a recent one with reasonable accuracy. + hasFix = !isLocationOld(location, now, MAX_LOCATION_AGE_MS); hasGoodFix = (location != null && location.getAccuracy() <= minRequiredAccuracy); - if (hasFix != oldHasFix || hasGoodFix != oldHasGoodFix || forceUpdate) { - notifyFixType(); + } else { + if (!isLocationOld(lastSeenLocation, now, MAX_LOCATION_AGE_MS)) { + // This is a network location, but we have a recent/valid GPS location, just ignore this. + return; + } + + // We haven't gotten a GPS location in a while (or at all), assume we have no fix anymore. + hasFix = false; + hasGoodFix = false; + + // If the network location is recent, we'll use that. + if (isLocationOld(location, now, MAX_NETWORK_AGE_MS)) { + // Alas, we have no clue where we are. + location = null; } } + if (hasFix != oldHasFix || hasGoodFix != oldHasGoodFix || forceUpdate) { + notifyFixType(); + } + + lastSeenLocation = location; + final Location finalLoc = location; runInListenerThread(new Runnable() { @Override public void run() { for (TrackDataListener listener : listeners) { - listener.onCurrentLocationChanged(location); + listener.onCurrentLocationChanged(finalLoc); } } }); } + /** + * Returns true if the given location is either invalid or too old. + * + * @param location the location to test + * @param now the current timestamp in milliseconds + * @param maxAge the maximum age in milliseconds + * @return true if it's invalid or too old, false otherwise + */ + private static boolean isLocationOld(Location location, long now, long maxAge) { + return !LocationUtils.isValidLocation(location) || now - location.getTime() > maxAge; + } + /** * Notifies that the current heading has changed. *