Skip to content

Instantly share code, notes, and snippets.

@rajiv-singaseni
Created July 21, 2011 12:01
Show Gist options
  • Save rajiv-singaseni/1097057 to your computer and use it in GitHub Desktop.
Save rajiv-singaseni/1097057 to your computer and use it in GitHub Desktop.
A location monitoring activity that toasts if it cannot monitor location.
package com.webile.location;
import android.app.Activity;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class LocationMonitorActivity extends Activity {
private static final String TAG = "LocationListener";
private LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER),
};
private LocationManager mLocationManager = null;
private Location mCurrentBestLocation = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
startReceivingLocationUpdates();
}
@Override
protected void onDestroy() {
super.onDestroy();
stopReceivingLocationUpdates();
}
private void debugLocation(Location location) {
if (location == null)
Log.i(TAG, "No location to debug");
String formattedLocation = String
.format(
"New location: from %s latitude = %.6f, longitude = %.6f, accuracy = %.4f",
location.getProvider(), location.getLatitude(),
location.getLongitude(), location.getAccuracy());
Log.v(TAG, formattedLocation);
}
private void startReceivingLocationUpdates() {
if (mLocationManager != null) {
Log.v(TAG, LocationManager.GPS_PROVIDER
+ " is "
+ mLocationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER));
Log
.v(
TAG,
LocationManager.NETWORK_PROVIDER
+ " is "
+ mLocationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
try {
//TODO: Needs customization
//requesting location updates for every minute or when the users moves by 100 meters
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 60 * 1000 * 1, 100,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "provider does not exist " + ex.getMessage());
}
try {
//TODO: Needs customization
//GPS drains more battery and works better outdoors.
//requesting location updates for every 3 minutes or when the users moves by 100 meters
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 60 * 1000 * 3, 100,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "provider does not exist " + ex.getMessage());
}
Location lastKnownGPSLocation = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownGPSLocation != null)
debugLocation(lastKnownGPSLocation);
else
Log.i(TAG, "No last known GPS location");
Location lastKnownNetworkLocation = mLocationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (lastKnownNetworkLocation != null)
debugLocation(lastKnownNetworkLocation);
else
Log.i(TAG, "No last known network location");
}
new Handler().postDelayed(new Runnable() {
public void run() {
if (mCurrentBestLocation == null) {
failedRecievingLocationUpdates();
}
}
}, 20 * 1000);
}
private void failedRecievingLocationUpdates() {
Toast.makeText(this, "Location services are temporarily unavailable", Toast.LENGTH_LONG)
.show();
}
private void stopReceivingLocationUpdates() {
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private Location getCurrentLocation() {
// go in best to worst order
for (int i = 0; i < mLocationListeners.length; i++) {
Location l = mLocationListeners[i].current();
if (l != null)
return l;
}
return null;
}
/**
* Update the current best location based on the algorithm
*
* @param location
*/
private void updateLocation(Location location) {
if (isBetterLocation(location, mCurrentBestLocation)) {
mCurrentBestLocation = location;
}
}
private static final int TWO_MINUTES = 1000 * 60 * 2;
/**
* Determines whether one Location reading is better than the current
* Location fix
*
* @param location
* The new Location that you want to evaluate
* @param currentBestLocation
* The current Location fix, to which you want to compare the new
* one
*/
protected boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
boolean mValid = false;
String mProvider;
public LocationListener(String provider) {
mProvider = provider;
mLastLocation = new Location(mProvider);
}
public void onLocationChanged(Location newLocation) {
if (newLocation.getLatitude() == 0.0
&& newLocation.getLongitude() == 0.0) {
// Hack to filter out 0.0,0.0 locations
return;
}
mLastLocation.set(newLocation);
updateLocation(newLocation);
mValid = true;
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
mValid = false;
}
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
case LocationProvider.TEMPORARILY_UNAVAILABLE:
mValid = false;
break;
}
}
public Location current() {
return mValid ? mLastLocation : null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment