My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

package com.joelapenna.foursquared.location;

import com.joelapenna.foursquared.FoursquaredSettings;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

import java.util.Date;
import java.util.List;
import java.util.Observable;

public class BestLocationListener extends Observable implements LocationListener {
private static final String TAG = "BestLocationListener";
private static final boolean DEBUG = FoursquaredSettings.LOCATION_DEBUG;

public static final long LOCATION_UPDATE_MIN_TIME = 0;
public static final long LOCATION_UPDATE_MIN_DISTANCE = 0;

public static final long SLOW_LOCATION_UPDATE_MIN_TIME = 1000 * 60 * 5;
public static final long SLOW_LOCATION_UPDATE_MIN_DISTANCE = 50;

public static final float REQUESTED_FIRST_SEARCH_ACCURACY_IN_METERS = 100.0f;
public static final int REQUESTED_FIRST_SEARCH_MAX_DELTA_THRESHOLD = 1000 * 60 * 5;

public static final long LOCATION_UPDATE_MAX_DELTA_THRESHOLD = 1000 * 60 * 5;

private Location mLastLocation;

public BestLocationListener() {
super();
}

@Override
public void onLocationChanged(Location location) {
if (DEBUG) Log.d(TAG, "onLocationChanged: " + location);
updateLocation(location);
}

@Override
public void onProviderDisabled(String provider) {
// do nothing.
}

@Override
public void onProviderEnabled(String provider) {
// do nothing.
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// do nothing.
}

synchronized public void onBestLocationChanged(Location location) {
if (DEBUG) Log.d(TAG, "onBestLocationChanged: " + location);
mLastLocation = location;
setChanged();
notifyObservers(location);
}

synchronized public Location getLastKnownLocation() {
return mLastLocation;
}

synchronized public void clearLastKnownLocation() {
mLastLocation = null;
}

public void updateLocation(Location location) {
if (DEBUG) {
Log.d(TAG, "updateLocation: Old: " + mLastLocation);
Log.d(TAG, "updateLocation: New: " + location);
}

// Cases where we only have one or the other.
if (location != null && mLastLocation == null) {
if (DEBUG) Log.d(TAG, "updateLocation: Null last location");
onBestLocationChanged(location);
return;

} else if (location == null) {
if (DEBUG) Log.d(TAG, "updated location is null, doing nothing");
return;
}

long now = new Date().getTime();
long locationUpdateDelta = now - location.getTime();
long lastLocationUpdateDelta = now - mLastLocation.getTime();
boolean locationIsInTimeThreshold = locationUpdateDelta <= LOCATION_UPDATE_MAX_DELTA_THRESHOLD;
boolean lastLocationIsInTimeThreshold = lastLocationUpdateDelta <= LOCATION_UPDATE_MAX_DELTA_THRESHOLD;
boolean locationIsMostRecent = locationUpdateDelta <= lastLocationUpdateDelta;

boolean accuracyComparable = location.hasAccuracy() || mLastLocation.hasAccuracy();
boolean locationIsMostAccurate = false;
if (accuracyComparable) {
// If we have only one side of the accuracy, that one is more
// accurate.
if (location.hasAccuracy() && !mLastLocation.hasAccuracy()) {
locationIsMostAccurate = true;
} else if (!location.hasAccuracy() && mLastLocation.hasAccuracy()) {
locationIsMostAccurate = false;
} else {
// If we have both accuracies, do a real comparison.
locationIsMostAccurate = location.getAccuracy() <= mLastLocation.getAccuracy();
}
}

if (DEBUG) {
Log.d(TAG, "locationIsMostRecent:\t\t\t" + locationIsMostRecent);
Log.d(TAG, "locationUpdateDelta:\t\t\t" + locationUpdateDelta);
Log.d(TAG, "lastLocationUpdateDelta:\t\t" + lastLocationUpdateDelta);
Log.d(TAG, "locationIsInTimeThreshold:\t\t" + locationIsInTimeThreshold);
Log.d(TAG, "lastLocationIsInTimeThreshold:\t" + lastLocationIsInTimeThreshold);

Log.d(TAG, "accuracyComparable:\t\t\t" + accuracyComparable);
Log.d(TAG, "locationIsMostAccurate:\t\t" + locationIsMostAccurate);
}

// Update location if its more accurate and w/in time threshold or if
// the old location is
// too old and this update is newer.
if (accuracyComparable && locationIsMostAccurate && locationIsInTimeThreshold) {
onBestLocationChanged(location);
} else if (locationIsInTimeThreshold && !lastLocationIsInTimeThreshold) {
onBestLocationChanged(location);
}
}

public boolean isAccurateEnough(Location location) {
if (location != null && location.hasAccuracy()
&& location.getAccuracy() <= REQUESTED_FIRST_SEARCH_ACCURACY_IN_METERS) {
long locationUpdateDelta = new Date().getTime() - location.getTime();
if (locationUpdateDelta < REQUESTED_FIRST_SEARCH_MAX_DELTA_THRESHOLD) {
if (DEBUG) Log.d(TAG, "Location is accurate: " + location.toString());
return true;
}
}
if (DEBUG) Log.d(TAG, "Location is not accurate: " + String.valueOf(location));
return false;
}

public void register(LocationManager locationManager, boolean gps) {
if (DEBUG) Log.d(TAG, "Registering this location listener: " + this.toString());
long updateMinTime = SLOW_LOCATION_UPDATE_MIN_TIME;
long updateMinDistance = SLOW_LOCATION_UPDATE_MIN_DISTANCE;
if (gps) {
updateMinTime = LOCATION_UPDATE_MIN_TIME;
updateMinDistance = LOCATION_UPDATE_MIN_DISTANCE;
}
List<String> providers = locationManager.getProviders(true);
int providersCount = providers.size();
for (int i = 0; i < providersCount; i++) {
String providerName = providers.get(i);
if (locationManager.isProviderEnabled(providerName)) {
updateLocation(locationManager.getLastKnownLocation(providerName));
}
// Only register with GPS if we've explicitly allowed it.
if (gps || !LocationManager.GPS_PROVIDER.equals(providerName)) {
locationManager.requestLocationUpdates(providerName, updateMinTime,
updateMinDistance, this);
}
}
}

public void unregister(LocationManager locationManager) {
if (DEBUG) Log.d(TAG, "Unregistering this location listener: " + this.toString());
locationManager.removeUpdates(this);
}

/**
* Updates the current location with the last known location without
* registering any location listeners.
*
* @param locationManager the LocationManager instance from which to
* retrieve the latest known location
*/
synchronized public void updateLastKnownLocation(LocationManager locationManager) {
List<String> providers = locationManager.getProviders(true);
for (int i = 0, providersCount = providers.size(); i < providersCount; i++) {
String providerName = providers.get(i);
if (locationManager.isProviderEnabled(providerName)) {
updateLocation(locationManager.getLastKnownLocation(providerName));
}
}
}
}

Change log

e48aaf5511ec by markww on Apr 19, 2010   Diff
Added a really simplistic method of
clearing the current location in
BestLocationListener, which can be toggled
on through preferences. This is
experimental for users having trouble with
geolocation.
Go to: 
Sign in to write a code review

Older revisions

bdc4dc178538 by Tauno on Feb 2, 2010   Diff
Cleaned up GlobalSearchProvider
implementation
1e82f3309b01 by Tauno Talimaa <tauntz> on Jan 27, 2010   Diff
Added quick search box support for
searching Venues
3faaf3e11e15 by Joe LaPenna <j...@joelapenna.com> on Jan 14, 2010   Diff
Don't try to log the location
retrieved from BestLocationListener.ge
tLastKnownLocation
All revisions of this file

File info

Size: 7669 bytes, 190 lines
Powered by Google Project Hosting