For several years, I've been using FusedLocationClient.requestLocationUpdates
to get location data from the device. In the past month (not sure exactly when), this method suddenly started hanging when the app is in the background. It's now occurring on all devices, across all app versions that were previously working.
Once the app is in the foreground again, the routine resumes, and the location callback is properly called.
In the past, I've had similar behavior if I didn't have ACCESS_BACKGROUND_LOCATION
granted. However, in this case, I do have that permission.
My location code executes in a Worker
, approximately every minute. Keep in mind, lots of lines were omitted to keep this post simple. If I left out anything deemed important, I can add it here.
private var fusedLocationClient: FusedLocationProviderClient? = null
private lateinit var locationCallback: LocationCallback
...
override fun doWork(): Result {
...
fusedLocationClient = LocationServices.getFusedLocationProviderClient(appContext)
locationCallback = object : LocationCallback() {
override fun onLocationResult(locRes: LocationResult) {
/* this is what's never getting reached when the app is in the background */
}
}
val locationRequestBuilder = LocationRequest.Builder(1000)
.setPriority(Priority.PRIORITY_HIGH_ACCURACY)
val locationBuilder = LocationSettingsRequest.Builder().addLocationRequest(locationRequestBuilder.build())
val settingsResult = LocationServices.getSettingsClient(appContext).checkLocationSettings(locationBuilder.build())
settingsResult.addOnCompleteListener { response ->
fusedLocationClient!!.requestLocationUpdates(locationRequestBuilder.build(), locationCallback, null)
}
...
}
When I first inherited this codebase, a Foreground Service was being used to accomplish this task, which worked fine until the Android 12 update limiting foreground services: This update prevents us from starting that foreground service from the background, which is necessary because of how the Service was built when I initially inherited it: It does a short-run task (collecting location), schedules itself, and then executes again on the scheduled time, then repeats. This flow could not continue without starting the service from the background, because the app could be minimized.
In that same page, the recommendation was to use a Work Manager instead of a Foreground Service, which caused me to switch from Service to Worker. What the Service was attempting to do seems to be more in line with what a Worker is supposed to do, anyway. This seemed to work fine until some time in the past month.
In theory, I could move everything back to a foreground service, then modify the service to continuously run, as opposed to doing one task and scheduling itself over and over, but I'm trying to avoid a major refactor like that, if possible.
My main goal is to keep it doing its short-run tasks, and scheduling itself, as it has been doing for nearly 7 years. But, if this approach is no longer feasible, I'll just bite the bullet and refactor it.
What I tried:
ACCESS_FINE_LOCATION
and ACCESS_BACKGROUND_LOCATION
AndroidManifest.xml
GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(appContext)
)What I ended up having to do was refactor my usage of the FusedLocationProviderClient
to make use of the intervals, and stick everything in a foreground service (as opposed to a Worker). The service starts when the user logs in, and runs continuously, and stops when they log out.
This seems to work fine for the most part, but becomes unreliable when the user selects "Only this time" when requesting location data. I will ask this in a separate question, however.