9

In my application I am sending location update to server in each 5 minutes. For that I am using gms LocationListener. This is working fine. I am running this inside a service. It won't work if the user turned off the GPS. since it is running it in service even after turning on the GPS it will wait for completing the 5 minutes of update time. So what I want is when the user turned on the GPS it should trigger the onLocationUpdate Listener.

For that I have did as follows I have initialised GpsStatus.Listener in my service, and implemented it onStatusChange() function, but after I change the GPS status from on to off/ off to on, the function is not triggering .

Code

public class LocationUpdateService extends Service implements GpsStatus.Listener, com.google.android.gms.location.LocationListener{
    onCreate(Bundle b){
        super.onCreate();
        registerGpsStatusListener();
    }

    private void registerGpsStatusListener() {
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.addGpsStatusListener(this);
    }

    @Override
    public void onGpsStatusChanged(int event) {
        switch (event) {
            case GpsStatus.GPS_EVENT_STARTED:
                Log.e(TAG, "onGpsStatusChanged started");
                break;

            case GpsStatus.GPS_EVENT_STOPPED:
                Log.e(TAG, "onGpsStatusChanged stopped");
                break;

            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Log.e(TAG, "onGpsStatusChanged first fix");
                break;

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                Log.e(TAG, "onGpsStatusChanged status");
                break;
        }
    }

    @Override
    public void onLocationChanged(Location location) {
       //opertations
    }
}

My queries are :

1- Why the method onGpsStatusChanged() is not calling after changing the GPS status.

2- How do I get location inside onLocationChanged() method, so that I can call onLocationUpdate() method.

NOTE: Please do not recommend to use BroadcastReceiver since it requires huge code modification of my current code.

Komal12
  • 3,340
  • 4
  • 16
  • 25
droidev
  • 7,352
  • 11
  • 62
  • 94
  • I guess you might not like this answer. if interested use ReactiveLocation https://github.com/mcharmas/Android-ReactiveLocation – Ravi Gadipudi Sep 30 '15 at 07:33
  • GPS status listener is about what happens inside GPS service after it has been on for a while. To see if GPS has been turned on, you need `LocationListener.isProviderEnabled()`. Look at the answer here:http://stackoverflow.com/questions/18259039/gpsstatus-listener-works-only-if-gps-is-on – panonski Oct 01 '15 at 08:28
  • The second question I don't understand so well. The `(Location location) ` is where you receive the new location. Then you can process the data and do things like `location.getLatitude() `, etc... – panonski Oct 01 '15 at 08:30

4 Answers4

3

I think you are trying to know when the user switches the GPS on or off from his device. In that case you can have a look at this answer.This is the only correct and reliable way to detect GPS on/off switch (at least it is the only one that worked for me).

Community
  • 1
  • 1
varunkr
  • 5,364
  • 11
  • 50
  • 99
  • I am looking for a better solution other than, broadcast receiver – droidev Sep 30 '15 at 08:37
  • Better solution? Better in what sense? I have spent quite some time working on GPS and I couldn't find a better solution. The broadcast receiver solution was the most reliable and worked perfectly. In case you find one please post it. – varunkr Sep 30 '15 at 09:02
  • but PROVIDERS_CHANGED broadcast will triggered when any of the location provider connected , isn’t it – droidev Sep 30 '15 at 10:53
  • @varunkr "better" == simpler ;) – angryITguy Apr 26 '17 at 01:53
  • @varunkr: When you turn on a fake gps app, you cannot listen the gps switching with broadcast receiver. – Hai nguyen Aug 16 '17 at 01:52
3

I recommend you use google location service instead of location manager. For example, with this LocationSimpleTracker you can easily detect GPS status and last location.

data class LocationSimpleTracker(val context: Context) {
    private val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
    private var locationCallback: LocationCallback? = null

    fun detectGPS(onGPSChanged: (Boolean) -> Unit) {
        locationCallback = object : LocationCallback() {

            override fun onLocationAvailability(var1: LocationAvailability?) {
                Timber.i("GPS enabled: ${var1?.isLocationAvailable}")
                onGPSChanged(var1?.isLocationAvailable ?: false)
            }

            override fun onLocationResult(result: LocationResult?) {
                Timber.i("New location: ${result?.lastLocation}")
            }
        }
        fusedLocationProviderClient.requestLocationUpdates(buildLocationRequest(), locationCallback, null)
    }

    private fun buildLocationRequest(): LocationRequest = LocationRequest.create().apply {
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        interval = 5000 //5 seconds
        fastestInterval = 5000 //5 seconds
        maxWaitTime = 1000 //1 seconds
    }

    fun stop() {
        fusedLocationProviderClient.removeLocationUpdates(locationCallback)
    }
}

And create an instance in your activity. Good luck.

Moises Apaza Q
  • 131
  • 2
  • 4
1

After you set up your GpsStatus.Listener you need to add the listener to your LocationManager.

locationManager.addGpsStatusListener(yourGpsStatusListener);
  • 1
    for Android 24 API (N) and higher it's `locationManager.registerGnssStatusCallback(listener)` – user924 May 03 '21 at 10:04
1

For all Android versions (up to the current 30 API):

private val locationManager: LocationManager = context
    .getSystemService(Context.LOCATION_SERVICE) as LocationManager

private var gpsStatusListener: Any? = null

private fun registerGpsStatusCallback() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        val listener = object : GnssStatus.Callback() {
            override fun onStarted() {
                super.onStarted()
            }

            override fun onStopped() {
                super.onStopped()
            }

            override fun onFirstFix(ttffMillis: Int) {
                super.onFirstFix(ttffMillis)
            }

            override fun onSatelliteStatusChanged(status: GnssStatus) {
                super.onSatelliteStatusChanged(status)
                var inUse = 0
                for (i in 0 until status.satelliteCount) {
                    if (status.usedInFix(i)) {
                        inUse++
                    }
                }
            }
        }
        locationManager.registerGnssStatusCallback(listener, backgroundHandler)
        gpsStatusListener = listener
    } else {
        @Suppress("DEPRECATION")
        val listener = GpsStatus.Listener { event ->
            when (event) {
                GpsStatus.GPS_EVENT_STARTED -> {}
                GpsStatus.GPS_EVENT_STOPPED -> {}
                GpsStatus.GPS_EVENT_FIRST_FIX -> {}
                GpsStatus.GPS_EVENT_SATELLITE_STATUS -> {
                    val inUse = locationManager.getGpsStatus(null)?.satellites?.count { it.usedInFix() } ?: 0
                }
            }
        }
        @Suppress("DEPRECATION")
        locationManager.addGpsStatusListener(listener)
        gpsStatusListener = listener
    }
}

private fun unregisterGpsStatusCallback() {
    gpsStatusListener?.let { listener ->
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            locationManager.unregisterGnssStatusCallback(listener as GnssStatus.Callback)
        } else {
            @Suppress("DEPRECATION")
            locationManager.removeGpsStatusListener(listener as GpsStatus.Listener)
        }
        gpsStatusListener = null
    }
}
user924
  • 8,146
  • 7
  • 57
  • 139