transistorsoft / react-native-background-geolocation

Sophisticated, battery-conscious background-geolocation with motion-detection
http://shop.transistorsoft.com/pages/react-native-background-geolocation
MIT License
2.62k stars 428 forks source link

Event Listeners are not being fired when app has been terminated #1714

Closed ankitjainOfficial closed 3 months ago

ankitjainOfficial commented 1 year ago

We are seeing that the on(Geofence, Heartbeat) events are not called when app is closed. The fences are correctly monitored, and the events are called when the app starts. This posses dual problem.

  1. The event that we are getting here, looks like:
    2023-06-14 18:06:39.758 ℹ️-[TSLocationManager log:message:] {"location":{"activity":{"type":"unknown","confidence":100},"battery":{"level":0.6700000166893005,"is_charging":false},"geofence":{"action":"EXIT","identifier":"65144cd3-bc3a-4a85-b53f-9fcf1442ba29"},"event":"geofence","odometer":0,"uuid":"66A2517E-6FB4-48CF-9056-729820E000AF","is_moving":false,"extras":{},"timestamp":"2023-06-14T12:36:39.083Z","coords":{"floor":null,"speed":0.62,"longitude":88.4284296175497,"speed_accuracy":-1,"accuracy":14.3,"ellipsoidal_altitude":0,"heading_accuracy":-1,"altitude_accuracy":10,"heading":50.72,"latitude":22.58013508280505,"altitude":7.7}},"identifier":"65144cd3-bc3a-4a85-b53f-9fcf1442ba29","action":"EXIT"}

The timestamp received is at the time of opening the app. The right timestamp should've been pretty much earlier. From the logs, I think this one.

2023-06-14 17:24:53.117 🔴-[TSGeofenceManager locationManager:didExitRegion:] 6cc54fb9-05cb-45a8-a082-f4a33c4a02ef

The reason I think is, because of this:


2023-06-14 18:06:39.079 
╔═══════════════════════════════════════════════════════════
║ -[TSGeofenceManager fireGeofenceEvent:] 📢EXIT Geofence: 6cc54fb9-05cb-45a8-a082-f4a33c4a02ef
╚═══════════════════════════════════════════════════════════

2023-06-14 18:06:39.080 ✅-[TSGeofenceManager fireGeofenceEvent:] INSERT: AD2AD1C4-859D-494C-8955-0A98E7816415

Secondly, onHeartbeat is never called. Should've called in an interval of ten minutes (as set in config)

Your Environment

Expected Behavior

Expected to get on events to fired at proper time, even when app has been killed.

Actual Behavior

onGeofence gets fired all at once and has the same timestamp, when the app starts. onHeartbeat is never called.

Steps to Reproduce

1. 2. 3. 4.

Context

Debug logs

Logs ``` Logs attached, due to file size restrictions ```

Ankit.log

christocracy commented 1 year ago

Have you read the api docs Config.stopOnTerminate?

you can expect heartbeat to halt when an iOS is terminated. The app won’t be relaunched until the device moves at least 200 meters. Until that occurs, your iOS app remains completely terminated and no code in your app is running.

christocracy commented 1 year ago

BackgroundGeolocation.start(); BackgroundGeolocation.startGeofences();

Why are you executing both these methods? You are to use one or the other.

Since you’ve awaited neither, it’s unknown exactly which state the plug-in will choose.

ankitjainOfficial commented 1 year ago

Have you read the api docs Config.stopOnTerminate?

you can expect heartbeat to halt when an iOS is terminated. The app won’t be relaunched until the device moves at least 200 meters. Until that occurs, your iOS app remains completely terminated and no code in your app is running.

Yes. I understand that. But, as you can see in the logs, the motion sensors did get active, but heartbeat was never fired.

christocracy commented 1 year ago

After making the code-changes I pointed out, create new logs. I don’t trust your code.

ankitjainOfficial commented 1 year ago

Sure thing. Here you go.

This is the updated the code, as per your advice.

      const state = await BackgroundGeolocation.ready({
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        enableHeadless: true,
        distanceFilter: 50,
        stopOnTerminate: false,
        locationAuthorizationRequest: 'Always',
        backgroundPermissionRationale: {
          title: "Allow access to this device's location in the background?",
          message:
            'We use your location to assist in your continued journey to well being by monitoring breaches to inclusion/exclusion zones set up or allowed by you even when you are not using the app',
          positiveAction: 'Change to allow all the time',
          negativeAction: "I'm not sure about this",
        },
        geofenceInitialTriggerEntry: true,
        scheduleUseAlarmManager: true,
        debug: true,
        heartbeatInterval: 1 * 10 * 60,
        logLevel: 5,
        startOnBoot: true,
        preventSuspend: true
      });
      console.log('- BackgroundGeolocation is ready: ', state);
      await BackgroundGeolocation.start();

And attached the corresponding logs

Ankit 2.log

christocracy commented 1 year ago

What timestamps within these logs are you concerned about?

ankitjainOfficial commented 1 year ago

Just to summarize my testing. I had created multiple fences and travelled through all of them.

If this helps in any way, all the fences are 200m and none of them are overlapping.

Geofence Exit Event happened at 17:29

2023-06-15 17:29:23.169 
╔═══════════════════════════════════════════════════════════
║ -[TSGeofenceManager fireGeofenceEvent:] 📢EXIT Geofence: f25c1307-106b-4dfe-8cec-df738a42326d
╚═══════════════════════════════════════════════════════════

2023-06-15 17:29:23.175 ✅-[TSGeofenceManager fireGeofenceEvent:] INSERT: ADD2FEF3-16AF-4FB6-8789-EE3D47C155B4

The on event listener, was fired at 18:53, when I had actually opened my app.


2023-06-15 18:53:29.763 🔵-[TSLocationManager log:message:] ANKIT onGeofence

2023-06-15 18:53:29.763 ℹ️-[TSLocationManager log:message:] {"location":{"activity":{"type":"unknown","confidence":100},"battery":{"level":0.6299999952316284,"is_charging":false},"geofence":{"action":"EXIT","identifier":"f25c1307-106b-4dfe-8cec-df738a42326d"},"event":"geofence","odometer":539.9,"uuid":"ADD2FEF3-16AF-4FB6-8789-EE3D47C155B4","is_moving":false,"extras":{},"timestamp":"2023-06-15T11:59:23.169Z","coords":{"floor":null,"speed":0,"longitude":88.43688091022776,"speed_accuracy":-1,"accuracy":14.6,"ellipsoidal_altitude":0,"heading_accuracy":-1,"altitude_accuracy":9.6,"heading":27.97,"latitude":22.580782217034255,"altitude":7}},"identifier":"f25c1307-106b-4dfe-8cec-df738a42326d","action":"EXIT"}

  1. Also, onHeartbeat was never actually called on iOS. You can check the logs, if you don't believe me. Just for understanding, you had earlier stated that it fires after 200m of movement. So, as you can see, I had moved a lot.

Thanks,

christocracy commented 1 year ago

onHeartbeat does not fire when the plug-in is in the moving state. It only fires while in the stationary state.

also, iOS throttles the heartbeat timer when the device is completely stationary, screen off and disconnected from power.

ankitjainOfficial commented 1 year ago

ok. understood. What about the late fire of fence events?

ankitjainOfficial commented 1 year ago

@christocracy Sir, any idea where I might have gone wrong?

christocracy commented 1 year ago

Show me all the attributes you're using to create the geofence f25c1307-106b-4dfe-8cec-df738a42326d.

christocracy commented 1 year ago

Are you sure your iOS app is calling .ready(config) each and every time your app launches, even if the OS automatically re-launches it in the background from a terminated state?

DevSomya2000 commented 1 year ago

@christocracy Sir, I work with @ankitjainOfficial and I am showing you the process we are using to create all the geofences

const [geoFencingForPatient] = useLazyQuery(
    GetGeoFencingDetails,
    {
      async onCompleted(data) {
        const geofences: Geofence[] = (
          data?.healthGetFencesForPatient || []
        )
          .filter(({radius}) => radius && radius > 0)
          .map(it => ({
            identifier: it.id,
            radius: it.radius,
            latitude: Number(it.latitude),
            longitude: Number(it.longitude),
            notifyOnEntry:
              it.type === GeoFencingTypes.IN ||
              it.type === GeoFencingTypes.IN_AND_OUT,
            notifyOnExit:
              it.type === GeoFencingTypes.OUT ||
              it.type === GeoFencingTypes.IN_AND_OUT,
          }));
        await BackgroundGeolocation.removeGeofences();
        await BackgroundGeolocation.addGeofences(geofences);
      },
    },
  );

  useEffect(() => {
    if (loggedIn && userType === UserTypes.PATIENT) {
      console.log('FETCHING GEOFENCES', loggedIn, userType);
      geoFencingForPatient();
    }
  }, [geoFencingForPatient, loggedIn, userType]);

And here is the updated plugin config


        const state = await BackgroundGeolocation.ready({
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        enableHeadless: true,
        distanceFilter: 50,
        stopOnTerminate: false,
        locationAuthorizationRequest: 'Always',
        backgroundPermissionRationale: {
          title: "Allow access to this device's location in the background?",
          message:
            'We use your location to assist in your continued journey to well being by monitoring breaches to inclusion/exclusion zones set up or allowed by you even when you are not using the app',
          positiveAction: 'Change to allow all the time',
          negativeAction: "I'm not sure about this",
        },
        geofenceInitialTriggerEntry: true,
        scheduleUseAlarmManager: true,
        heartbeatInterval: 1 * 10 * 60,
        logLevel: 5,
        startOnBoot: true,
        preventSuspend: true,
        geofenceModeHighAccuracy: true,
        schedule: [
          '1-7 10:00-10:30 location',
          '1-7 12:00-12:30 location',
          '1-7 14:00-14:30 location',
          '1-7 16:00-16:30 location',
          '1-7 18:00-18:30 location',
          '1-7 20:00-20:30 location',
          '1-7 00:00-23:59 geofence',
        ],
      });
      console.log('- BackgroundGeolocation is ready: ', state);
      await BackgroundGeolocation.start();
christocracy commented 1 year ago

Are you sure your iOS app is calling .ready(config) each and every time your app launches — no matter what —, even if the OS automatically re-launches it in the background from a terminated state?

christocracy commented 1 year ago

Are you re-adding geofences at each launch of your app? You should NOT re-add geofences which are already being monitored.

Use .geofenceExists to determine if a particular geofence uuid is already being monitored.

ankitjainOfficial commented 1 year ago

Sure. I’ll take both points, check and confirm with you. Thanks for the pointers.

On Mon, 19 Jun 2023 at 8:55 PM, Chris Scott @.***> wrote:

Are you re-adding geofences at each launch of your app? You should NOT re-add geofences which are already being monitored.

Use .geofenceExists https://transistorsoft.github.io/react-native-background-geolocation/classes/backgroundgeolocation.html#geofenceexists to determine if a particular geofence uuid is already being monitored.

— Reply to this email directly, view it on GitHub https://github.com/transistorsoft/react-native-background-geolocation/issues/1714#issuecomment-1597380355, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACD4FMTRIVGHOY27XCHILJTXMBVONANCNFSM6AAAAAAZGPNKOU . You are receiving this because you were mentioned.Message ID: <transistorsoft/react-native-background-geolocation/issues/1714/1597380355 @github.com>

-- Thanks,

Ankit Choraria

github-actions[bot] commented 3 months ago

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

github-actions[bot] commented 3 months ago

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