Tuesday, 19 January 2021

Retrieve background location using WorkManager always return same lastknown location

My app works fine if using foreground service to get user location, however in background I just need location for each 15 minutes, also Google requires new Policy for getting background location so, foreground service is over my expectation.

I am trying to get location from background using WorkManager, it can run normally every (around) 15 minutes. My location is requested, however it always returns the previous address, even 1, 2... hours are passed.

Here is my code:


class LocationWorker(private val context: Context, params: WorkerParameters) :
        CoroutineWorker(context, params) {
    
   private var fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
  
   override suspend fun doWork() = withContext(Dispatchers.IO) {
      val location = getLocation()
      if (location == null) {
         if (runAttemptCount < MAX_ATTEMPT) { // max_attempt = 3
            Result.retry()
         } else {
            Result.failure()
         }
      } else {
         Log.d(TAG, "doWork success $location")
         Result.success()
      }
    }
    
    private suspend fun getLocation(): Location? = withTimeoutOrNull(TIMEOUT) {
       suspendCancellableCoroutine<Location?> { continuation ->
          val intent = PendingIntent.getBroadcast(context, REQUEST_CODE, Intent(ACTION), 0)
          val receiver = object : BroadcastReceiver() {
              override fun onReceive(context: Context?, data: Intent?) {
                  if (data?.action != ACTION) return
                  val lastLocation = LocationResult.extractResult(data)?.lastLocation
                  Log.e(TAG, "Get lastLocation success $lastLocation")
                  fusedLocationClient.removeLocationUpdates(intent)
                  context?.unregisterReceiver(this)
                  continuation.resume(lastLocation)
              }
        }
        context.registerReceiver(receiver, IntentFilter(ACTION))
        val request = LocationRequest().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY }
        fusedLocationClient.requestLocationUpdates(request, intent)
        continuation.invokeOnCancellation {
            fusedLocationClient.removeLocationUpdates(intent)
            context.unregisterReceiver(receiver)
        }
    }
    
    companion object {
            val TAG = LocationWorker::class.java.simpleName
            const val LOCATION_WORKER_TAG = "LOCATION_WORKER_TAG"
            const val MAX_ATTEMPT = 3
            private const val ACTION = "my.background.location"
            private const val TIMEOUT = 60_000L
            private const val REQUEST_CODE = 888
        }
    }

Pre-condition:

  • Tested device: emulator android 27 (O_MR1)
  • Route Play normally
  • GPS is enabled
  • Allow location permission (allow all time)

Why don't the lastknown location not updated ?

I also tried this demo https://github.com/pratikbutani/LocationTracker-WorkManager/ . However, the problem is same, lastknown location is not updated.



from Retrieve background location using WorkManager always return same lastknown location

No comments:

Post a Comment