Is it possible to get a notification when any location provider is enabled/disabled and ascertain what action occurred?

Steve Weet picture Steve Weet · Apr 9, 2013 · Viewed 10.2k times · Source

I wish to receive a notification when the user enables or disables either Network or GPS locations, and importantly I wish to know which one they have changed and how. I have a broadcast receiver for the android.location.PROVIDERS_CHANGED broadcast intent and this is receiving the correct broadcast.

I now need to try and determine which action has occurred i.e. enable or disable and which provider has been changed. I know that I could keep the state of each provider and then when I receive notification that they have changed then I could work out what has changed, I am looking for a more "standard" method of doing this. The broadcast intent does not seem to have any extras to indicate which provider has changed.

This is the code I have currently.

    public class LocationProviderChangedReceiver extends BroadcastReceiver {
    private final static String TAG = "LocationProviderChangedReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
      if (intent.getAction().matches("android.location.PROVIDERS_CHANGED"))
      {
        Log.i(TAG,"Location Providers changed");
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
          Log.d(TAG, "No extras data");
         } else {
           Log.d(TAG, "Bundle received of size " + bundle.size);
         } 
      }
    }
  }

And this is a small extract from my Manifest

  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  <receiver 
    android:name=".LocationProviderChangedReceiver"
    android:exported="false">
    <intent-filter>
      <action android:name="android.location.PROVIDERS_CHANGED" />
      <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
  </receiver>

This would be perfect if there was an extra within the Broadcast that stated which provider had changed and whether it was enabled or disabled. Unfortunately this is not the case. Is anyone aware of any mechanism by which I can determine what state has changed without maintaining my own state variables.

In an ideal world I would monitor for changes constantly but only listen for location changes occasionally. I would like to avoid constantly monitoring for location changes.

Answer

M. Usman Khan picture M. Usman Khan · Mar 11, 2015

This works for me:

Add receiver to the Manifest file:

<receiver
        android:name="com.eegeo.location.LocationProviderChangedReceiver">
        <intent-filter>
            <action android:name="android.location.PROVIDERS_CHANGED" />
        </intent-filter>
    </receiver>

Check both location providers in receiver:

public class LocationProviderChangedReceiver  extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {

        boolean anyLocationProv = false;
        LocationManager locationManager = (LocationManager) MyMainActivity.context.getSystemService(Context.LOCATION_SERVICE);

        anyLocationProv |= locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        anyLocationProv |=  locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        Log.i("", "Location service status" + anyLocationProv);


    }

}

Though this receiver is called more than once due to obvious reasons, but this will tell you the status.