-
Notifications
You must be signed in to change notification settings - Fork 70
Respsect LocationRequest Parameters #146
Changes from 2 commits
2388605
50a9548
e989857
f10b5c8
5a2d08e
b8c236f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,14 +38,26 @@ public class LostClientManager implements ClientManager { | |
private Map<LostApiClient, Set<LocationCallback>> clientToLocationCallbacks; | ||
private Map<LostApiClient, Map<LocationCallback, Looper>> clientCallbackToLoopers; | ||
|
||
private Map<LocationListener, LocationRequest> listenerToLocationRequests; | ||
private Map<PendingIntent, LocationRequest> intentToLocationRequests; | ||
private Map<LocationCallback, LocationRequest> callbackToLocationRequests; | ||
private Map<LocationRequest, Long> requestToLastReportedTime; | ||
private Map<LocationRequest, Location> requestToLastReportedLocation; | ||
|
||
private LostClientManager() { | ||
public LostClientManager() { | ||
clients = new HashSet<>(); | ||
|
||
clientToListeners = new HashMap<>(); | ||
clientToPendingIntents = new HashMap<>(); | ||
clientToLocationCallbacks = new HashMap<>(); | ||
clientCallbackToLoopers = new HashMap<>(); | ||
|
||
listenerToLocationRequests = new HashMap<>(); | ||
intentToLocationRequests = new HashMap<>(); | ||
callbackToLocationRequests = new HashMap<>(); | ||
requestToLastReportedTime = new HashMap<>(); | ||
requestToLastReportedLocation = new HashMap<>(); | ||
|
||
} | ||
|
||
public static LostClientManager shared() { | ||
|
@@ -83,6 +95,7 @@ public void addListener(LostApiClient client, LocationRequest request, | |
} | ||
listeners.add(listener); | ||
clientToListeners.put(client, listeners); | ||
listenerToLocationRequests.put(listener, request); | ||
} | ||
|
||
public void addPendingIntent(LostApiClient client, LocationRequest request, | ||
|
@@ -93,6 +106,7 @@ public void addPendingIntent(LostApiClient client, LocationRequest request, | |
} | ||
intents.add(callbackIntent); | ||
clientToPendingIntents.put(client, intents); | ||
intentToLocationRequests.put(callbackIntent, request); | ||
} | ||
|
||
public void addLocationCallback(LostApiClient client, LocationRequest request, | ||
|
@@ -110,6 +124,7 @@ public void addLocationCallback(LostApiClient client, LocationRequest request, | |
} | ||
looperMap.put(callback, looper); | ||
clientCallbackToLoopers.put(client, looperMap); | ||
callbackToLocationRequests.put(callback, request); | ||
} | ||
|
||
public boolean removeListener(LostApiClient client, LocationListener listener) { | ||
|
@@ -124,7 +139,7 @@ public boolean removeListener(LostApiClient client, LocationListener listener) { | |
clientToListeners.remove(client); | ||
} | ||
} | ||
|
||
listenerToLocationRequests.remove(listener); | ||
return removedListener; | ||
} | ||
|
||
|
@@ -140,6 +155,7 @@ public boolean removePendingIntent(LostApiClient client, PendingIntent callbackI | |
clientToPendingIntents.remove(client); | ||
} | ||
} | ||
intentToLocationRequests.remove(callbackIntent); | ||
return removedPendingIntent; | ||
} | ||
|
||
|
@@ -163,51 +179,61 @@ public boolean removeLocationCallback(LostApiClient client, LocationCallback cal | |
clientCallbackToLoopers.remove(client); | ||
} | ||
} | ||
callbackToLocationRequests.remove(callback); | ||
return removedCallback; | ||
} | ||
|
||
public void reportLocationChanged(Location location) { | ||
for (LostApiClient client : clientToListeners.keySet()) { | ||
if (clientToListeners.get(client) != null) { | ||
for (LocationListener listener : clientToListeners.get(client)) { | ||
listener.onLocationChanged(location); | ||
} | ||
} | ||
} | ||
/** | ||
* Reports location changed for all listeners respecting their corresponding | ||
* {@link LocationRequest#getFastestInterval()} and | ||
* {@link LocationRequest#getSmallestDisplacement()} values. Returns a map of the updated | ||
* last reported times so that {@code LostClientManager#requestToLastReportedTime} after | ||
* all reporting (including pending intents and location callbacks) has been done. | ||
* @param location | ||
* @return | ||
*/ | ||
public ReportedChanges reportLocationChanged(final Location location) { | ||
return iterateAndNotify(location, | ||
clientToListeners, listenerToLocationRequests, new Notifier<LocationListener>() { | ||
@Override void notify(LostApiClient client, LocationListener listener) { | ||
listener.onLocationChanged(location); | ||
} | ||
}); | ||
} | ||
|
||
public void sendPendingIntent(Context context, Location location, | ||
LocationAvailability availability, LocationResult result) { | ||
for (LostApiClient client : clientToPendingIntents.keySet()) { | ||
if (clientToPendingIntents.get(client) != null) { | ||
for (PendingIntent intent : clientToPendingIntents.get(client)) { | ||
try { | ||
Intent toSend = new Intent().putExtra(KEY_LOCATION_CHANGED, location); | ||
toSend.putExtra(LocationAvailability.EXTRA_LOCATION_AVAILABILITY, availability); | ||
toSend.putExtra(LocationResult.EXTRA_LOCATION_RESULT, result); | ||
intent.send(context, 0, toSend); | ||
} catch (PendingIntent.CanceledException e) { | ||
Log.e(TAG, "Unable to send pending intent: " + intent); | ||
/** | ||
* Fires intent for all pending intents respecting their corresponding | ||
* {@link LocationRequest#getFastestInterval()} and | ||
* {@link LocationRequest#getSmallestDisplacement()} values. Returns a map of the updated | ||
* last reported times so that {@code LostClientManager#requestToLastReportedTime} after | ||
* all reporting (including pending intents and location callbacks) has been done. | ||
* @param location | ||
* @return | ||
*/ | ||
public ReportedChanges sendPendingIntent(final Context context, | ||
final Location location, final LocationAvailability availability, | ||
final LocationResult result) { | ||
return iterateAndNotify(location, | ||
clientToPendingIntents, intentToLocationRequests, new Notifier<PendingIntent>() { | ||
@Override void notify(LostApiClient client, PendingIntent pendingIntent) { | ||
fireIntent(context, pendingIntent, location, availability, result); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
|
||
public void reportLocationResult(final LocationResult result) { | ||
for (LostApiClient client : clientToLocationCallbacks.keySet()) { | ||
if (clientToLocationCallbacks.get(client) != null) { | ||
for (final LocationCallback callback : clientToLocationCallbacks.get(client)) { | ||
Looper looper = clientCallbackToLoopers.get(client).get(callback); | ||
Handler handler = new Handler(looper); | ||
handler.post(new Runnable() { | ||
@Override public void run() { | ||
callback.onLocationResult(result); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
public ReportedChanges reportLocationResult(Location location, | ||
final LocationResult result) { | ||
return iterateAndNotify(location, | ||
clientToLocationCallbacks, callbackToLocationRequests, new Notifier<LocationCallback>() { | ||
@Override void notify(LostApiClient client, LocationCallback callback) { | ||
notifyCallback(client, callback, result); | ||
} | ||
}); | ||
} | ||
|
||
public void updateReportedValues(ReportedChanges changes) { | ||
requestToLastReportedTime.putAll(changes.timeChanges()); | ||
requestToLastReportedLocation.putAll(changes.locationChanges()); | ||
} | ||
|
||
public void reportProviderEnabled(String provider) { | ||
|
@@ -234,13 +260,7 @@ public void notifyLocationAvailability(final LocationAvailability availability) | |
for (LostApiClient client : clientToLocationCallbacks.keySet()) { | ||
if (clientToLocationCallbacks.get(client) != null) { | ||
for (final LocationCallback callback : clientToLocationCallbacks.get(client)) { | ||
Looper looper = clientCallbackToLoopers.get(client).get(callback); | ||
Handler handler = new Handler(looper); | ||
handler.post(new Runnable() { | ||
@Override public void run() { | ||
callback.onLocationAvailability(availability); | ||
} | ||
}); | ||
notifyAvailability(client, callback, availability); | ||
} | ||
} | ||
} | ||
|
@@ -269,4 +289,75 @@ public Map<LostApiClient, Set<PendingIntent>> getPendingIntents() { | |
public Map<LostApiClient, Set<LocationCallback>> getLocationCallbacks() { | ||
return clientToLocationCallbacks; | ||
} | ||
|
||
private void fireIntent(Context context, PendingIntent intent, Location location, | ||
LocationAvailability availability, LocationResult result) { | ||
try { | ||
Intent toSend = new Intent().putExtra(KEY_LOCATION_CHANGED, location); | ||
toSend.putExtra(LocationAvailability.EXTRA_LOCATION_AVAILABILITY, availability); | ||
toSend.putExtra(LocationResult.EXTRA_LOCATION_RESULT, result); | ||
intent.send(context, 0, toSend); | ||
} catch (PendingIntent.CanceledException e) { | ||
Log.e(TAG, "Unable to send pending intent: " + intent); | ||
} | ||
} | ||
|
||
private void notifyCallback(LostApiClient client, final LocationCallback callback, | ||
final LocationResult result) { | ||
Looper looper = clientCallbackToLoopers.get(client).get(callback); | ||
Handler handler = new Handler(looper); | ||
handler.post(new Runnable() { | ||
@Override public void run() { | ||
callback.onLocationResult(result); | ||
} | ||
}); | ||
} | ||
|
||
private void notifyAvailability(LostApiClient client, final LocationCallback callback, | ||
final LocationAvailability availability) { | ||
Looper looper = clientCallbackToLoopers.get(client).get(callback); | ||
Handler handler = new Handler(looper); | ||
handler.post(new Runnable() { | ||
@Override public void run() { | ||
callback.onLocationAvailability(availability); | ||
} | ||
}); | ||
} | ||
|
||
private <T> ReportedChanges iterateAndNotify(Location location, | ||
Map<LostApiClient, Set<T>> clientToObj, Map<T, LocationRequest> objToLocationRequest, | ||
Notifier notifier) { | ||
Map<LocationRequest, Long> updatedRequestToReportedTime = new HashMap<>(); | ||
Map<LocationRequest, Location> updatedRequestToReportedLocation = new HashMap<>(); | ||
for (LostApiClient client : clientToObj.keySet()) { | ||
if (clientToObj.get(client) != null) { | ||
for (final T obj : clientToObj.get(client)) { | ||
LocationRequest request = objToLocationRequest.get(obj); | ||
Long lastReportedTime = requestToLastReportedTime.get(request); | ||
Location lastReportedLocation = requestToLastReportedLocation.get(request); | ||
if (lastReportedTime == null && lastReportedLocation == null) { | ||
updatedRequestToReportedTime.put(request, System.currentTimeMillis()); | ||
updatedRequestToReportedLocation.put(request, location); | ||
notifier.notify(client, obj); | ||
} else { | ||
long intervalSinceLastReport = System.currentTimeMillis() - lastReportedTime; | ||
long fastestInterval = request.getFastestInterval(); | ||
float smallestDisplacement = request.getSmallestDisplacement(); | ||
float displacementSinceLastReport = location.distanceTo(lastReportedLocation); | ||
if (intervalSinceLastReport >= fastestInterval && | ||
displacementSinceLastReport >= smallestDisplacement) { | ||
updatedRequestToReportedTime.put(request, System.currentTimeMillis()); | ||
updatedRequestToReportedLocation.put(request, location); | ||
notifier.notify(client, obj); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return new ReportedChanges(updatedRequestToReportedTime, updatedRequestToReportedLocation); | ||
} | ||
|
||
abstract class Notifier<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call, changed to an interface |
||
abstract void notify(LostApiClient client, T obj); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I really like the use of generics to allows us to treat There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😄 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.mapzen.android.lost.internal; | ||
|
||
import com.mapzen.android.lost.api.LocationRequest; | ||
|
||
import android.location.Location; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* Represents changes to reported locations and times at which locations were reported for | ||
* different modes of notification (listeners, pending intents, and callbacks). After all types of | ||
* callbacks are invoked, these changes will be committed so that the next time a location is | ||
* reported, the {@link FusedLocationProviderServiceImpl} can properly determine if it should be | ||
* reported to listeners, pending intents, and callbacks. | ||
*/ | ||
public class ReportedChanges { | ||
|
||
private Map<LocationRequest, Long> updatedRequestToReportedTime; | ||
private Map<LocationRequest, Location> updatedRequestToReportedLocation; | ||
|
||
public ReportedChanges(Map<LocationRequest, Long> timeChanges, | ||
Map<LocationRequest, Location> locationChanges) { | ||
updatedRequestToReportedTime = timeChanges; | ||
updatedRequestToReportedLocation = locationChanges; | ||
} | ||
|
||
public Map<LocationRequest, Long> timeChanges() { | ||
return updatedRequestToReportedTime; | ||
} | ||
|
||
public Map<LocationRequest, Location> locationChanges() { | ||
return updatedRequestToReportedLocation; | ||
} | ||
|
||
public void putAll(ReportedChanges changes) { | ||
updatedRequestToReportedTime.putAll(changes.timeChanges()); | ||
updatedRequestToReportedLocation.putAll(changes.locationChanges()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we replace
requestToLastReportedTime
andrequestToLastReportedLocation
with a single private instance ofReportedChanges
since that seems to encapsulate the same thing?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced