Forked from rajiv-singaseni/LocationMonitorActivity.java
Created
September 25, 2012 18:14
-
-
Save markus2610/3783521 to your computer and use it in GitHub Desktop.
A location monitoring activity that toasts if it cannot monitor location.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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