17

I'm on Android 2.3.7 and I'm trying to write a BroadcastReceiver that will get called when the user turns GPS on/off (ie: by tapping on the "use GPS satellites" in the options.

What I've done so far is this:

1) Created the following broadcastReceiver:

public class GPSStatusBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context arg0, Intent arg1) {
        Toast.makeText(arg0, "Broadcast received!", Toast.LENGTH_SHORT).show();

    }
}

2)Added this to the android manifest, inside the tags:

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

Now the problem with this is that it appears not to be reliable. When I turn GPS on/ff the onReceive() method only runs sometimes (I'd say 1 time out 3) the other times it doesn't get called.

I want to know if there is a reliable way to detect when the GPS is turned off/on.

If there isn't it would be nice to be notified at least when no app is using the GPS anymoer (ie: when the gps icon disappears from statusbar, indicating no one is actively locating).

EDIT: Clarification: I don't want to do this while my app is running. I just whatn my app to be started when gps is turned on/off, do its thing and then terminate, I don't want to subscribe to LocationsUpdates...

Master_T
  • 7,232
  • 11
  • 72
  • 144

4 Answers4

9

On API level 9 and higher you can use LocationManager.PROVIDERS_CHANGED_ACTION:

Broadcast intent action when the configured location providers change. For use with isProviderEnabled(String). If you're interacting with the LOCATION_MODE API, use MODE_CHANGED_ACTION instead.

Constant Value: "android.location.PROVIDERS_CHANGED"

Source

Community
  • 1
  • 1
theWook
  • 843
  • 9
  • 22
4

The following solution might be a weird solution but you can try it if you don't find any solution. Another problem with your solution is it works only after api level 9.

in a thread or service you can check the gps status periodically with a very short interval by using

 LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE );
 boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);

it will use the permission

android.permission.ACCESS_FINE_LOCATION

Even though I am answering this, to me it should not be a good solution. Also there is a chance of minimum period interval delay. Just an option.

stinepike
  • 54,068
  • 14
  • 92
  • 112
  • 1
    As with poitroae's answer: if I use this doesn't it mean my app has to be running? I don't want that. I want my app to be started only when gps is turned on/off, run a method and then terminate. I was under the impression you had to use BroadcastReceivers to do this, was I wrong? – Master_T Mar 16 '13 at 17:59
  • Nope you are completely right. I was wrong on getting that point.. My bad – stinepike Mar 16 '13 at 18:07
  • 1
    My fault, my question was a bit generic, I added the clarification now. – Master_T Mar 16 '13 at 18:15
2

Starting from API 19 you can listen for the intent action LocationManager.MODE_CHANGED_ACTION.

You can also get the current location mode as follows:

try
{
    int locationMode = android.provider.Settings.Secure.getInt(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE);
} catch (android.provider.Settings.SettingNotFoundException e)
{
    e.printStackTrace();
}

The value returned should be one of these:

android.provider.Settings.Secure.LOCATION_MODE_BATTERY_SAVING
android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
android.provider.Settings.Secure.LOCATION_MODE_OFF
android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY
stkent
  • 19,772
  • 14
  • 85
  • 111
ARLabs
  • 1,465
  • 1
  • 14
  • 25
  • This constant was deprecated in API level 28. The preferred methods for checking location mode and listening for changes are via LocationManager#isLocationEnabled() Source: https://developer.android.com/reference/android/provider/Settings.Secure#LOCATION_MODE – t0m Apr 02 '21 at 10:56
-3

Use a LocationListener and override OnStatusChanged.

You can attach your listener using the requestLocationUpdates(String, long, float, LocationListener) method on your LocationManager instance.

poitroae
  • 21,129
  • 10
  • 63
  • 81
  • 1
    Sorry, my question wasn't clear enough. I don't want to detect location in my app. What I want to do is simply detect when GPS is turned on/off by the user system wide. (my app will only be this broadcast receiver that will simply write some data to disk every time GPS is turned on/off) – Master_T Mar 16 '13 at 17:13
  • @Master_T yes, if `OnStatusChanged` is triggered if the status has changed. The status obviously changes when the user enables/disables it. – poitroae Mar 16 '13 at 17:15
  • But for this to work isn't it necessary that my app is active? Or at least running in the background? What I want is that my app gets called whenever the GPS is turned on/off, do its thing and then terminate. That's why I was using a BroadcasReceiver, as it notifies apps even if they are not running. – Master_T Mar 16 '13 at 17:55