1

I'm trying to get the user's speed 10 times in three seconds when a function is called, and then calculate the sum of all the gotten values. I have the global variable:

lateinit var fusedLocationProviderClient : FusedLocationProviderClient

Which I then initialize in the onCreate method like this:

fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

And then this is the code where I try to calculate the sum of the speeds:

val task = fusedLocationProviderClient.lastLocation
var sumSpeed = 0F
task.addOnSuccessListener {
    if (it != null) {
        for (i in 1..10) {
            Thread.sleep(300)
            sumSpeed += it.speed
        }
    }

    current_gps_speed_tv.text = "Total is: $sumSpeed"

    if (sumSpeed < 25) {
        ...
    }
}

The result of sumSpeed always remains the same (34m/s), which is 10 times it.speed, which is also the same every time (3.4m/s).

I've searched for other answers (like this one) but what I'm using seems to be different. Why does this happen? Thank you.

Enrico Cortinovis
  • 811
  • 3
  • 8
  • 31

1 Answers1

1

This won't work for at least a few different reasons.

  1. You're trying to poll it more than once per second. I think the fastest rate position is updated is at best once per second, and it's going to depend on device.

  2. You are simply adding the same value to the sum 10 times and sleeping the thread pointlessly. Calling sleep pauses execution of your code. It does not magically change the value of it to some new value polled from the GPS.

  3. Calling Thread.sleep on the main thread will freeze your app.

  4. You are polling lastLocation, which is some location already known from the last time the GPS was used. It only reports a single value that comes from the past. It cannot report multiple new values. Your success listener is called only one time, because either the last location is available or it's not.

To get multiple locations over a period of time, you need to use requestLocationUpdates instead of lastLocation. See here for the documentation.

Edit, to expand on 2 based on your comment:

Imagine this code:

val x = 5
var sum = 0
for (i in 0..9) {
    sum = sum + 5
}
println(sum)

This adds the value of x to sum 10 times, so the result will be 50.

Now consider this code:

val x = 5
var sum = 0
for (i in 0..9) {
    Thread.sleep(100)
    sum = sum + 5
}
println(sum)

This code has the exact same result. It just takes a lot longer to return because it keeps pausing to sleep. Sleeping has no effect on the value of x. x is always the same value. The same is true of it in your code. There is only ever one instance of it in your function.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • Thank you. Reason `2` must be what causes the total value to be 10x `it.speed` . But I did not understand why it is also always the same amount (3.4)? – Enrico Cortinovis Oct 19 '21 at 18:56
  • I added an example to help you understand. – Tenfour04 Oct 19 '21 at 19:07
  • Thank you for the explanation, in the last comment I may not have explained myself well. I wanted to ask why it is always 3.4m/s, not only in the 10 times the loop adds that same value to `sumSpeed`, but every time that whole block of code is executed (i.e. whatever speed the user is going, in whichever location the user opens the app). – Enrico Cortinovis Oct 19 '21 at 19:12
  • I would not expect an accurate speed from `lastLocation` because it is passive. If there is no app actively and frequently polling the location, the last location may only contain a very out-of-date value for speed. – Tenfour04 Oct 19 '21 at 19:58