androidkotlinandroid-fusedlocation

Cannot stop Fused Location Provider using removeLocationUpdates()


I have an activity that is receiving the user location every X seconds. When the user location is within the radius of 15 meters from a specific point, I want the Location Provider to stop updating the user location and to start a new activity.

I have the following method to stop location updates:

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

I call stopLocationUpdates() in both onPause() and onDestroy() methods. I've tried to call it inside the for each location cicle, when the case distance < 15 is verified. None of this seems to work.

I am trying to call finish() to finish the current activity and by using the Logcat I see that the location keeps updating, although the activity is finished. Plus, the new activity (ExerciseActivity) keeps launching in loop. Please, let me know how I can stop this. Thank you in advance.

I leave here the major parts of the code of this activity:

class MapActivity : AppCompatActivity() {

private val requestPermissionsRequestCode = 1
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
private lateinit var locationRequest: LocationRequest
private var allCheckpoints: List<CheckpointResult> = ArrayList()
private val mAdapterNextCheckpoints = NextCheckpointAdapter()
private var nextCheckpoints: ArrayList<CheckpointResult> = ArrayList()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_map)

    requestPermissionsIfNecessary(arrayOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_NETWORK_STATE,
        Manifest.permission.ACCESS_WIFI_STATE,
        Manifest.permission.INTERNET
    ))

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    fusedLocationClient.lastLocation
        .addOnSuccessListener { location: Location? ->
            if (location != null) {
                mUserMarker.position = GeoPoint(location.latitude, location.longitude)
                mUserMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
                mUserMarker.title = getString(R.string.your_position)
                map.overlays.add(mUserMarker)
                map.controller.setCenter(mUserMarker.position)
            }
        }
    startLocationUpdates()
}

private fun startLocationUpdates() {
    locationRequest = create()
    locationRequest.interval = 4000
    locationRequest.priority = Priority.PRIORITY_HIGH_ACCURACY
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            for (location in locationResult.locations) {
                mUserMarker.position = GeoPoint(location.latitude, location.longitude)
                mUserMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
                mUserMarker.title = getString(R.string.your_position)
                map.overlays.add(mUserMarker)
                mAdapterNextCheckpoints

                if (nextCheckpoints.isNotEmpty()) {
                    for (checkpoint in nextCheckpoints) {
                        val results = FloatArray(3)
                        Location.distanceBetween(checkpoint.latitude,
                            checkpoint.longitude,
                            location.latitude,
                            location.longitude, results)
                        val distance = results[0]
                        Log.d("Distance: ", distance.toString())
                        if (distance <= 15) {
                            //stopLocationUpdates()
                            val i = Intent(this@MapActivity, ExerciseActivity::class.java)
                            i.putExtra("exerciseId", checkpoint.exercise.exerciseId)
                            startActivity(i)
                            finish()
                        }
                    }
                }
            }
        }
    }
    fusedLocationClient.requestLocationUpdates(locationRequest,
        locationCallback,
        Looper.getMainLooper())
}

override fun onResume() {
    super.onResume()
    startLocationUpdates()
}

override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

override fun onDestroy() {
    super.onDestroy()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}
}

Solution

  • Try removing startLocationUpdates() call inside onCreate() and I hope it will get you to work.

    Explenation: You are calling startLocationUpdates() method in both onCreate() and onResume() methods. So it will make two callbacks which you store the latest inside locationCallback. But you loose the first callback created when onCreate() is called. So when you call fusedLocationClient .removeLocationUpdates(locationCallback), you just remove one of the callbacks!