package net.atomcode.bearing.location.provider;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import net.atomcode.bearing.location.LocationListener;
import net.atomcode.bearing.location.LocationProvider;
import net.atomcode.bearing.location.LocationProviderRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Simple location provider using the legacy android location services
*/
public class LegacyLocationProvider implements LocationProvider
{
private static LegacyLocationProvider instance;
public static LegacyLocationProvider getInstance()
{
if (instance == null)
{
instance = new LegacyLocationProvider();
}
return instance;
}
private LocationManager locationManager;
private Map<String, android.location.LocationListener> runningRequests;
@Override public void create(Context context)
{
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
runningRequests = new HashMap<String, android.location.LocationListener>();
}
@Override public void destroy()
{
for (android.location.LocationListener runningRequest : runningRequests.values())
{
locationManager.removeUpdates(runningRequest);
}
runningRequests.clear();
}
@Override
public Location getLastKnownLocation(LocationProviderRequest request)
{
String provider = getProviderForRequest(request);
return locationManager.getLastKnownLocation(provider);
}
@Override
public String requestSingleLocationUpdate(LocationProviderRequest request, final LocationListener listener)
{
String provider = getProviderForRequest(request);
if (request.useCache)
{
Location lastKnownUserLocation = locationManager.getLastKnownLocation(provider);
// Check if last known location is valid
if (lastKnownUserLocation != null &&
System.currentTimeMillis() - lastKnownUserLocation.getTime() < request.cacheExpiry)
{
if (lastKnownUserLocation.getAccuracy() < request.accuracy.value)
{
if (listener != null)
{
listener.onUpdate(lastKnownUserLocation);
return null;
}
}
}
}
final String requestId = UUID.randomUUID().toString();
runningRequests.put(requestId, new android.location.LocationListener()
{
@Override public void onLocationChanged(Location location)
{
if (listener != null)
{
listener.onUpdate(location);
}
runningRequests.remove(requestId);
}
@Override public void onStatusChanged(String provider, int status, Bundle extras)
{
}
@Override public void onProviderEnabled(String provider)
{
}
@Override public void onProviderDisabled(String provider)
{
}
});
locationManager.requestSingleUpdate(provider, runningRequests.get(requestId), Looper.getMainLooper());
return requestId;
}
@Override
public String requestRecurringLocationUpdates(final LocationProviderRequest request, final LocationListener listener)
{
String requestId = UUID.randomUUID().toString();
int powerCriteria = Criteria.POWER_LOW;
int accuracyCriteria = Criteria.ACCURACY_MEDIUM;
switch (request.accuracy)
{
case LOW:
powerCriteria = Criteria.POWER_LOW;
accuracyCriteria = Criteria.ACCURACY_COARSE;
break;
case MEDIUM:
powerCriteria = Criteria.POWER_MEDIUM;
accuracyCriteria = Criteria.ACCURACY_MEDIUM;
break;
case HIGH:
powerCriteria = Criteria.POWER_HIGH;
accuracyCriteria = Criteria.ACCURACY_FINE;
}
Criteria criteria = new Criteria();
criteria.setPowerRequirement(powerCriteria);
criteria.setAccuracy(accuracyCriteria);
String bestProvider = locationManager.getBestProvider(criteria, false);
runningRequests.put(requestId, new android.location.LocationListener()
{
@Override public void onLocationChanged(Location location)
{
if (listener != null)
{
listener.onUpdate(location);
}
}
@Override public void onStatusChanged(String provider, int status, Bundle extras)
{
}
@Override public void onProviderEnabled(String provider)
{
}
@Override public void onProviderDisabled(String provider)
{
}
});
locationManager.requestLocationUpdates(bestProvider, request.trackingRate, 0, runningRequests.get(requestId));
return null;
}
@Override
public void cancelUpdates(String requestId)
{
if (runningRequests.containsKey(requestId))
{
locationManager.removeUpdates(runningRequests.get(requestId));
runningRequests.remove(requestId);
}
}
/**
* Get the provider for the given request
*/
private String getProviderForRequest(LocationProviderRequest request)
{
String provider = null;
switch (request.accuracy)
{
case LOW:
provider = LocationManager.PASSIVE_PROVIDER;
if (locationManager.isProviderEnabled(provider))
{
break;
}
case MEDIUM:
provider = LocationManager.NETWORK_PROVIDER;
if (locationManager.isProviderEnabled(provider))
{
break;
}
case HIGH:
provider = LocationManager.GPS_PROVIDER;
}
return provider;
}
}