React-native-background-geolocation: Duplicate Coordinates

Created on 2 Oct 2018  Β·  16Comments  Β·  Source: transistorsoft/react-native-background-geolocation

Your Environment

  • Plugin version: 2.10.1
  • Platform: iOS or Android
  • OS version: N/A
  • Device manufacturer / model: N/A
  • React Native version (react-native -v): 55.2
  • Plugin config
      desiredAccuracy: 25,
      maximumAge: 20000,
      samples: 2,
      timeout: 20,
      distanceFilter: 30,
      foregroundService: true,
      logLevel: BackgroundGeolocation.LOG_LEVEL_ERROR,
      preventSuspend: true,

We're using our own library to send the requests and have validated that the problem isn't there.j

Expected Behavior

Events with identical cooridinates are rarely generated

Actual Behavior

We're seeing location events coming through with identical coordinates. This is only on devices out in the wild and we can't reproduce on our test devices, so this is more of a question rather than a bug report.

Sometimes the timespan between the events is milliseconds and other times it's hours. They're not always sequential either and we're seeing instances across iOS and Android.

What are the conditions required for the device to report the same lat/lng coordinates? I'd assume that would be very rare and tried doing some research but couldn't find anything concrete. We do have a maxAge on getCurrentPosition, but it's only set to 20s. Is there any other valid reason where that method would return coordinates that have been sent previously?

Steps to Reproduce

N/A

It's worth mentioning we use background location tracking and getCurrentPosition, triggered on certain app actions.

Debug logs

Have asked affected users to submit email logs. Will attach as and when they come through.

I have attached a csv example of events recorded in our database. Not sure it will help, but might be relevant.

dupe-coordinates.csv.zip

stale

All 16 comments

Platform: iOS or Android

There's no possible way you experience this on both iOS AND Android.

The plugin posts a uuid string with each location. You can use this to detect if the plugin posts an actual duplicate location.

Show me plugin logs where this occurs (with exact timestamp when it occurred).

Be default, the Android plugin filters out duplicate locations relative to last recorded location like this:

private boolean locationSameAsLast(Location l) {
        if (lastLocation == null) {
            return false;
        } else if (lastLocation == l) {
            return true;
        } else if (
            (l.getLatitude()    == lastLocation.getLatitude()) &&
            (l.getLongitude()   == lastLocation.getLongitude()) &&
            (l.getSpeed()       == lastLocation.getSpeed()) &&
            (l.getBearing()     == lastLocation.getBearing())
        ) {
            return true;
        } else {
            return false;
        }
    }

The plugin posts a uuid string with each location. You can use this to detect if the plugin posts an actual duplicate location.

Ah cool, we don't record that but that's a useful data point we can definitely collect.

Show me plugin logs where this occurs (with exact timestamp when it occurred).

Still waiting on these as it's a manual request from user side. Will post when we have some.

Thanks for the help @christocracy

@christocracy We've published an update to our app to record the uuid of events, so that should hopefully give us some good insights. In the meantime, we got some logs back from users and the only thing of note in there is a few occurrences of:

09-28 20:32:01.492 ERROR [TSLocationManager getLastLocation] 
  ‼️  Failed to get last location: com.google.android.gms.tasks.zzp@f49093b

Is that a common log or something to look into? I haven't been able to align this to an instance of the duplicates yet which might tell us if that's related.

background-geolocation (2).log

It’s not a big deal. The native location apis hold a reference to the last known location.

There was none in this case. It can happen at boot before the location apis lock in and fetch a location.

And do testing on a variety of devices if possible.

If you install and run the demo app in parallel, you can easily add geofences in the β€œAdvanced App” by long-pressing on the map.

Add 3 or 4 geofences within a kilometer and go for a walk.

@christocracy I've managed to get a stream of data highlighting the issue. I'm still skeptical that it's anything to do with RNBG, but I'm just posting in case anything obvious jumps out.

The only interesting thing about this set of events is that the user didn't have a solid network connection (or network was off) at the time they were recorded. We know this because we keep a reference to device timestamp and server timestamp. We process events ourselves and we've ran through the logic and can't find anything in our own code.

As network was offline, I'm wondering if that also means they didn't have other services like location available at the time. We did try disabling location services while debugging and as expected it didn't report any gps events. Could network connection have any impact on gps? I'm still interested in whether it's plausible to get identical GPS coordinates depending on location service settings, e.g. if it's just relying on wifi/cell-tower positioning. We couldn't replicate that either though, the coordinates were always consistently unique.

I've attached the data we've pulled, here's some context:

  • These events all have the same geometry, but there are other events in between these with different geometry. So they're not sequential
  • We started attaching the RNBG uuid to events and as you can see that is unique for each
  • We also have our own session ID which is identical across events as expected
  • The device ID is also consistent across all these events
  • The timestamp in the first column is our recorded timestamp, but I've also included the RNBG timestamp too (which is UTC)

As I said, I'm not expecting any answers just posting in case anything obvious jumps out. Our next steps are to go through debugging steps again with the demo app side-loaded and also try and determine if there's any correlation between the different duplicate coordinates. Will keep the thread updated with any findings

dupe-events-example.csv.zip

@christocracy Just to check, if I call getCurrentPosition multiple times within the maximumAge period, then should the timestamp the module supplies me the same for all those calls? i.e. uuid is different, timestamp is from original and obviously coordinates the same

yes.

@christocracy So I've been able to reproduce a couple of scenarios which don't fully explain the issues we're having, but are interesting anyway:

1. Identical Coordinates (Android)

I was able to get the module to fire multiple GPS events with the same coordinates within the maximumAge duration of the last event by repeatedly making calls to getCurrentPosition in a short period of time. For context, we request current position when certain scenes are opened, so to replicate I could quickly enter and exit those scenes. If you don't do it fast it behaves as advertised and filters the duplicates. Here's the log:

╔═════════════════════════════════════════════
β•‘ LocationService: location:1008
╠═════════════════════════════════════════════
β•Ÿβ”€ πŸ“  Location[fused -37.797806,144.986289 hAcc=106 et=+5d13h56m14s716ms alt=35.139691597985625 vel=1.1555142 bear=313.0 vAcc=256 sAcc=??? bAcc=??? {Bundle[{battery_level=0.41, uuid=7643a0f4-a036-4c31-8935-02507afb6bf5, requestId=1008, is_charging=true, verticalAccuracy=256.0}]}], age: 104ms

10-12 15:14:33.295 INFO [TSLocationManager onSingleLocationResult] 
  πŸ”΅  Acquired current position
10-12 15:14:33.309 DEBUG [TSLocationManager calculateMedianAccuracy] 128.0
10-12 15:14:33.351 INFO [SQLiteLocationDAO persist] 
  βœ…  INSERT: 7643a0f4-a036-4c31-8935-02507afb6bf5
10-12 15:14:33.358 DEBUG [LocationService onLocation] 
╔═════════════════════════════════════════════
β•‘ LocationService: location:1007
╠═════════════════════════════════════════════
β•Ÿβ”€ πŸ“  Location[fused -37.797806,144.986289 hAcc=106 et=+5d13h56m14s716ms alt=35.139691597985625 vel=1.1555142 bear=313.0 vAcc=256 sAcc=??? bAcc=??? {Bundle[{battery_level=0.41, uuid=2264a638-1a1c-4dcc-901c-aa1d3066dbfa, requestId=1007, is_charging=true, verticalAccuracy=256.0}]}], age: 22ms

10-12 15:14:33.375 INFO [TSLocationManager onSingleLocationResult] 
  πŸ”΅  Acquired current position
10-12 15:14:33.383 DEBUG [TSLocationManager calculateMedianAccuracy] 128.0
10-12 15:14:33.412 INFO [SQLiteLocationDAO persist] 
  βœ…  INSERT: 2264a638-1a1c-4dcc-901c-aa1d3066dbfa
10-12 15:14:33.417 DEBUG [LocationService onLocation] 
╔═════════════════════════════════════════════
β•‘ LocationService: location:1009
╠═════════════════════════════════════════════
β•Ÿβ”€ πŸ“  Location[fused -37.797806,144.986289 hAcc=106 et=+5d13h56m14s716ms alt=35.139691597985625 vel=1.1555142 bear=313.0 vAcc=256 sAcc=??? bAcc=??? {Bundle[{battery_level=0.41, uuid=915057e8-b349-4bfd-9578-eeb0946f533a, requestId=1009, is_charging=true, verticalAccuracy=256.0}]}], age: 38ms

10-12 15:14:33.457 INFO [TSLocationManager onSingleLocationResult] 
  πŸ”΅  Acquired current position
10-12 15:14:33.470 DEBUG [TSLocationManager calculateMedianAccuracy] 117.132
10-12 15:14:33.493 INFO [SQLiteLocationDAO persist] 
  βœ…  INSERT: 915057e8-b349-4bfd-9578-eeb0946f533a

2. Full Duplicate (Android)

We've only seen a couple of these in the wild and it's not a huge deal, but I was able to replicate the module giving me two identical events in sequence by doing the following:

  1. Request getCurrentPosition
  2. Promptly turn off location services

I think the module gives one last location when turning off location services, but it is the same uuid/timestamp/coordinates. Here's the log for that with the dupe insert:

╔═════════════════════════════════════════════
β•‘ LocationService: location:1027
╠═════════════════════════════════════════════
β•Ÿβ”€ πŸ“  Location[fused -37.798254,144.986575 hAcc=79 et=+5d14h8m46s156ms alt=51.311688016754566 vel=0.061444677 bear=293.0 vAcc=256 sAcc=??? bAcc=??? {Bundle[{battery_level=0.41, uuid=d779b02b-403d-420c-ab33-1eaf025b5075, requestId=1027, is_charging=true, verticalAccuracy=256.0}]}], age: 18ms

10-12 15:27:04.813 INFO [TSLocationManager onSingleLocationResult] 
  πŸ”΅  Acquired current position
10-12 15:27:04.830 DEBUG [TSLocationManager calculateMedianAccuracy] 79.432
10-12 15:27:04.881 INFO [SQLiteLocationDAO persist] 
  βœ…  INSERT: d779b02b-403d-420c-ab33-1eaf025b5075
10-12 15:27:30.771 INFO [LocationService onLocation] 
  ℹ️  Location availability: true
10-12 15:27:37.461 INFO [LocationService onLocation] 
  ℹ️  Location availability: false
10-12 15:27:44.178 INFO [BackgroundGeolocation$n onReceive] 
╔═════════════════════════════════════════════
β•‘ Location-provider change: false
╠═════════════════════════════════════════════
β•Ÿβ”€ GPS: false
β•Ÿβ”€ Network: false

10-12 15:27:44.201 INFO [TSLocationManager onSingleLocationResult] 
  πŸ”΅  Acquired providerchange position
10-12 15:27:44.215 DEBUG [TSLocationManager calculateMedianAccuracy] 79.24
10-12 15:27:44.240 INFO [SQLiteLocationDAO persist] 
  βœ…  INSERT: d779b02b-403d-420c-ab33-1eaf025b5075
10-12 15:27:50.312 WARN [SingleLocationRequest finish] 
  ⚠️  timeout: 1028
10-12 15:27:50.354 WARN [TSLocationManager onLocationTimeout] 
  ⚠️  TSLocationManager received location timeout
10-12 15:27:50.370 WARN [BackgroundGeolocation _onLocationError] 
  ⚠️  Location error: 408

I think I saw this a couple of times outside of this in testing but this is the only way I could reproduce consistently

3. iOS & Android differences

I think this might be intentional, but when requesting getCurrentLocation android won't trigger a new event if it falls within maximumAge, but iOS will (with a different uuid). Again not a huge deal as we can filter ourselves but it's a behaviour difference between platforms.


Let me know if those are useful or not. We're still struggling to identify why a device would trigger duplicate coordinates over a long period of time but the sequential ones we can mitigate. We're going to add a throttle on the getCurrentPosition call and also do our own filtering which should hopefully cover off most of our issues.

@christocracy did you get chance to look at my previous message?

Case 1

I was able to get the module to fire multiple GPS events with the same coordinates within the maximumAge

I don't understand your problem here. Requesting 3 locations within a few milliseconds is nearly guaranteed to give you the same coords.

Case 2

The case #2 doesn't really apply. This is a special case where a providerchange event occurs without access to location-services. The Android plugin automatically records a location where the device was when the providerchange event occurred. When location-services is completely disabled, obviously fetching the current location is impossible so the plugin does the best it can and applies the last known location to the event.

However, perhaps I should re-generate the uuid to make it unique. It will still have identical coordinates to some previous location.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.

Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you.

Be default, the Android plugin filters out duplicate locations relative to last recorded location like

@christocracy - Is this filtering out of duplicate locations also applicable in case of time based tracking ? i.e. when distanceFilter : 0

Was this page helpful?
0 / 5 - 0 ratings