react-native-background-geolocation icon indicating copy to clipboard operation
react-native-background-geolocation copied to clipboard

OnLocation is getting called thousands of times and crashes the app

Open lniepolski opened this issue 2 years ago • 8 comments

Your Environment

  • Plugin version: 4.11.1
  • Platform: iOS
  • OS version: A lot. I've seen everything between iOS 15.6.1 to 16.6
  • Device manufacturer / model: Mainly iPads
  • React Native version (react-native -v): 0.71.8
  • Plugin config
  BackgroundGeolocation.ready({
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        distanceFilter: 50,
        stopTimeout: 60 * 10,
        debug: false,
        stopOnTerminate: true
      });

Expected Behavior

I expect the callback BackgroundGeolocation.onLocation to be called every 50 meters.

Actual Behavior

Based on our internal logs it sometimes gets executed thousands of times in a matter of seconds. From what've seen, it seems to be mainly happening on iPads.

Steps to Reproduce

Haven't been able to reproduce it:

My code:

  useEffect(() => {
    let onLocation;
    if (trackActivity) {
      onLocation = BackgroundGeolocation.onLocation(location => {
        ...
      });

      BackgroundGeolocation.ready({
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        distanceFilter: 50,
        stopTimeout: 60 * 10,
        debug: false,
        stopOnTerminate: true
      });
    }
    return () => {
      if (onLocation) onLocation.remove();
    };
  }, []);

lniepolski avatar Aug 08 '23 02:08 lniepolski

You've likely created an infinite loop somewhere in your code.

Post all code where you're accessing BackgroundGeolocation.

christocracy avatar Aug 08 '23 14:08 christocracy


  useEffect(() => {
    let onLocation;
    if (trackActivity) {
      onLocation = BackgroundGeolocation.onLocation(location => {
        ...
      });

      BackgroundGeolocation.ready({
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        distanceFilter: 50,
        stopTimeout: 60 * 10,
        debug: false,
        stopOnTerminate: true
      });
    }
    return () => {
      if (onLocation) onLocation.remove();
    };
  }, []);

  useEffect(() => {
    if (trackActivity) {
      if (isActive) {
        BackgroundGeolocation.start();
      } else {
        BackgroundGeolocation.stop();
      }
    }
  }, [isActive]);

lniepolski avatar Aug 08 '23 14:08 lniepolski

I would check your logic on that isActive property. You are likely doing something unexpected there under some conditions.

christocracy avatar Aug 08 '23 15:08 christocracy

Btw, it’s perfectly safe to add event-listeners and call .ready under any circumstances. You don’t need that logic if (trackActivity) {.

calling .ready does not start-tracking and adding event-listeners does nothing more than add a callback function to a List.

christocracy avatar Aug 08 '23 15:08 christocracy

Based on our logs, isActive is changed only once.

Also, what is weird, is that it seems to be happening only on iPads.

Screenshot 2023-08-08 at 11 14 12

lniepolski avatar Aug 08 '23 15:08 lniepolski

I looked a little bit more into that and it seems to be a problem with just one client of ours who provides their company's devices to their employees. Any idea what could be causing that?

lniepolski avatar Aug 08 '23 15:08 lniepolski

Without plug-in logs, it’s impossible to speculate about what’s happening.

see wiki “Debugging” to learn how to fetch logs from the plug-in.

christocracy avatar Aug 08 '23 15:08 christocracy

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar May 06 '24 01:05 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar May 20 '24 01:05 github-actions[bot]

@christocracy removealllisteners() should be called or not? I want location tracking if app is not in the background. I use listener to check http status, if request failed then again i sent location to server

In this scenario, should I call remove listener?

haiderTkxel avatar Aug 21 '24 13:08 haiderTkxel

The plugin's event-listeners are nothing more than an Array of callbacks functions that get iterated when an event occurs. They have no effect on the performance of the plugin, just as disconnecting the speakers of your stereo system doesn't actually stop the music from playing.

What does your question here have to do with the title of this issue "OnLocation is getting called thousands of times and crashes the app"?

christocracy avatar Aug 21 '24 13:08 christocracy

The plugin's event-listeners are nothing more than an Array of callbacks functions that get iterated when an event occurs. They have no effect on the performance of the plugin, just as disconnecting the speakers of your stereo system doesn't actually stop the music from playing.

What does your question here have to do with the title of this issue "OnLocation is getting called thousands of times and crashes the app"?

@christocracy If I add the listener and don't remove it then there is a chance of memory leak? Every time app opens the listener added or overrides the previous listener?

Suppose, request http fails and app was killed by user before request fails then i think this listener should work in the background if stopOnTerminate: false.

If I remove listener on app killed then listener would not be called if request fails.

haiderTkxel avatar Aug 21 '24 13:08 haiderTkxel

Do you know that each event-listener method returns a Subscription object which contains a single method .remove()?

See API docs onLocation, for example.

const subscription = BackgroundGeolocation.onLocation((location) => {
  console.log("[onLocation] success: ", location);
}, (error) => {
  console.log("[onLocation] ERROR: ", error);
});
React.useEffect(() => {
  let onLocationListener = BackgroundGeolocation.onLocation((location) => {
    console.log('[onLocation]', location);
  });
  
  return () => {
    // Remove BackgroundGeolocation event-subscribers when the View is removed or refreshed
    // during development live-reload.  Without this, event-listeners will accumulate with
    // each refresh during live-reload.
    onLocationListener.remove();
  }
}, []);

christocracy avatar Aug 21 '24 13:08 christocracy

@christocracy If I remove listener on app killed then listener would not be called if request fails. Right?

haiderTkxel avatar Aug 21 '24 14:08 haiderTkxel

You don't need to worry about listeners on a "killed" app since your app will have been removed from memory.

christocracy avatar Aug 21 '24 14:08 christocracy