3 Steps for Shutting off GPS and LocationManager on Android

While the code for shutting off the LocationManager on Android is straight forward, sometimes just one misstep and you can spend hours trying to figure out why it doesn’t work. What will happen is you will see in your code that the LocationManager and perhaps even the listeners will be null and the GPS active icon will continue to display and your battery will drain faster than you ever thought possible. There are a bunch of comments already on Stack Overflow about this problem, so this post attempts to consolidate answers and provide some straight forward steps to help with the most common mistakes.

First let’s review the steps for properly shutting LocationManager down:

Step 1. Remove the listener or listeners. If you are using both GPS and network providers you have to remove both. It sounds oversimplified, but you can only remove the exact listener that is associated with a particular instance of the LocationManager. It’s a one-to-one relationship.

Step 2. Set LocationManager to null.

Step 3. Set listeners to null.

Here’s what the code looks like, the names should be self explanatory:

if(_locationManager != null){

    _locationManager.removeUpdates(_locationListenerGPSProvider);

    _locationManager.removeUpdates(_locationListenerNetworkProvider);

    _locationManager = null;

}

if(_locationListenerGPSProvider != null) {

    _locationListenerGPSProvider = null;

}

if(_locationListenerNetworkProvider != null){

    _locationListenerNetworkProvider = null;

}

If these steps don’t work and the GPS icon continues to display, then there are potentially two reasons why:

Reason 1. You have instantiated intentionally or accidentally more than one copy of LocationManager and/or a listener. This is by far the most common and frustrating reason. The easiest way to avoid this mistake is to only start the LocationManager via the onResume() event, and shut it down using onPause(). Carefully control what is allowed to start and stop it. Be mindful when passing around instances of LocationManager between different Activities whether it is a singleton, static class or simply a reference to the actual object. If LocationManager is already running and you spin up a new instance, then you may not be able to shut it off programmatically and you’ll have to manually shut it off.

Reason 2. Something else other than your app is causing the LocationManager to run. This can easily give the appearance that it has not been turned off via your app. Repeated testing can eliminate this as a possibility, and to make sure you can shut off all other non-essential applications that use location.

References

Android Activity and Life Cycle

Handle null values when using Android’s LocationManager

I’d noticed a number of fatal app crashes recently, and it was only through luck I discovered that I wasn’t handling null values that were being returned by the device’s  LocationManager. I only discovered this through a bit of detective work and being lucky enough to have the app crash while hooked up to logcat when the device decided to act up. I can now say with certainty that it’s true a GPS_PROVIDER or LOCATION_PROVIDER can indeed return null values. So, as a best practice  now I simply listen for them and handle them gracefully.

I’ve also noticed that sometimes these null values can happen sporadically, so I’ve also implemented a counter system that says if a certain number of null values happen in a row then shut down the LocationManager and notify the user, otherwise simply ignore them. Here’s an example of the basic pattern:

// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {

	int counter = 0;

	public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
		if(location != null){
			counter = 0
			double lat = loc.getLatitude();
			double lon = loc.getLongitude();
		}
		else
		{
			counter++;
			if(counter > 3)
			{
				// Remove the listener you previously added
				locationManager.removeUpdates(locationListener);
                                //locationManager = null;

				//Let user know there was a problem and that GPS was shut off....
			}

		}
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
};

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

Here’s one example of a GPS problem on a Motorola Atrix in logcat:

06-01 15:15:43.298: E/libgps(1653): recv_command_nmea() : NMEA_PARSE_ERROR_DATA_FIELDS_MISSING: The sentence does not contain enough fields for its data type