Skip to content
This repository has been archived by the owner on Apr 23, 2023. It is now read-only.

Commit

Permalink
Merge pull request #8 from mapzen/chuck/get-last-location-should-pref…
Browse files Browse the repository at this point in the history
…er-recent

Get last location now prefers updates within last 60 seconds.
  • Loading branch information
baldur committed Aug 20, 2014
2 parents 8a065b3 + bf32745 commit 40b85e8
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 1 deletion.
5 changes: 5 additions & 0 deletions lost/src/main/java/com/mapzen/android/lost/Clock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mapzen.android.lost;

public interface Clock {
public long getCurrentTimeInMillis();
}
17 changes: 16 additions & 1 deletion lost/src/main/java/com/mapzen/android/lost/LocationClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class LocationClient {
// Name of the mock location provider.
public static final String MOCK_PROVIDER = "mock";

// Location updates more than 60 seconds old are considered stale.
public static final int RECENT_UPDATE_THRESHOLD_IN_MILLIS = 60 * 1000;

private final Context context;
private final ConnectionCallbacks connectionCallbacks;

Expand All @@ -55,6 +58,8 @@ public class LocationClient {
private boolean mockMode;
private Location mockLocation;

Clock clock = new SystemClock();

public LocationClient(Context context, ConnectionCallbacks connectionCallbacks) {
this.context = context;
this.connectionCallbacks = connectionCallbacks;
Expand All @@ -79,12 +84,22 @@ public Location getLastLocation() {
}

final List<String> providers = locationManager.getAllProviders();
final long minTime = clock.getCurrentTimeInMillis() - RECENT_UPDATE_THRESHOLD_IN_MILLIS;
Location bestLocation = null;
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;
for (String provider : providers) {
final Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) {
final float accuracy = location.getAccuracy();
final long time = location.getTime();
if (time > minTime && accuracy < bestAccuracy) {
bestLocation = location;
bestAccuracy = accuracy;
bestTime = time;
} else if (time < minTime && bestAccuracy == Float.MAX_VALUE && time > bestTime) {
bestLocation = location;
bestTime = time;
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions lost/src/main/java/com/mapzen/android/lost/SystemClock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mapzen.android.lost;

public class SystemClock implements Clock {
@Override
public long getCurrentTimeInMillis() {
return System.currentTimeMillis();
}
}
41 changes: 41 additions & 0 deletions lost/src/test/java/com/mapzen/android/lost/LocationClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
import static com.mapzen.android.lost.LocationClient.RECENT_UPDATE_THRESHOLD_IN_MILLIS;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.robolectric.Robolectric.application;
import static org.robolectric.Robolectric.shadowOf;
Expand Down Expand Up @@ -112,6 +113,46 @@ public void getLastLocation_shouldReturnMostAccurateResult() throws Exception {
assertThat(locationClient.getLastLocation()).isEqualTo(passiveLocation);
}

@Test
public void getLastLocation_shouldIgnoreStaleLocations() throws Exception {
long time = System.currentTimeMillis();
TestClock testClock = new TestClock();
testClock.setCurrentTimeInMillis(time);
locationClient.clock = testClock;

Location gpsLocation = new Location(GPS_PROVIDER);
gpsLocation.setAccuracy(100);
gpsLocation.setTime(time);
shadowLocationManager.setLastKnownLocation(GPS_PROVIDER, gpsLocation);

Location networkLocation = new Location(NETWORK_PROVIDER);
networkLocation.setAccuracy(100);
networkLocation.setTime(time - (2 * RECENT_UPDATE_THRESHOLD_IN_MILLIS));
shadowLocationManager.setLastKnownLocation(NETWORK_PROVIDER, networkLocation);

assertThat(locationClient.getLastLocation()).isEqualTo(gpsLocation);
}

@Test
public void getLastLocation_ifNoFreshLocationsShouldReturnMostRecent() throws Exception {
long time = System.currentTimeMillis();
TestClock testClock = new TestClock();
testClock.setCurrentTimeInMillis(time);
locationClient.clock = testClock;

Location gpsLocation = new Location(GPS_PROVIDER);
gpsLocation.setAccuracy(100);
gpsLocation.setTime(time - (2 * RECENT_UPDATE_THRESHOLD_IN_MILLIS));
shadowLocationManager.setLastKnownLocation(GPS_PROVIDER, gpsLocation);

Location networkLocation = new Location(NETWORK_PROVIDER);
networkLocation.setAccuracy(100);
networkLocation.setTime(time - (3 * RECENT_UPDATE_THRESHOLD_IN_MILLIS));
shadowLocationManager.setLastKnownLocation(NETWORK_PROVIDER, networkLocation);

assertThat(locationClient.getLastLocation()).isEqualTo(gpsLocation);
}

@Test(expected = IllegalStateException.class)
public void requestLocationUpdates_shouldThrowExceptionIfNotConnected() throws Exception {
locationClient = new LocationClient(application, connectionCallbacks);
Expand Down
14 changes: 14 additions & 0 deletions lost/src/test/java/com/mapzen/android/lost/TestClock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.mapzen.android.lost;

public class TestClock implements Clock {
private long currentTimeInMillis;

@Override
public long getCurrentTimeInMillis() {
return currentTimeInMillis;
}

public void setCurrentTimeInMillis(long currentTimeInMillis) {
this.currentTimeInMillis = currentTimeInMillis;
}
}

0 comments on commit 40b85e8

Please sign in to comment.