Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to get the user location at regular intervals when app in background using onHeartbeat #2032

Closed
kopposh opened this issue May 22, 2024 · 9 comments

Comments

@kopposh
Copy link

kopposh commented May 22, 2024

Your Environment

  • Plugin version: "react-native-background-geolocation": "^4.14.6",
  • Platform: iOS and Android
  • OS version: Android >=9, iOS >= 15
  • Device manufacturer / model: Tested on iPhone 15 pro, Mi A1
  • React Native version (react-native -v): Expo 50.0.18
  • Plugin config
defaultReadyOptions: Config = {
  // Debug
  heartbeatInterval: 60 * 14,
  stopTimeout: 60,
  preventSuspend: true,
  debug: false,
  logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
  distanceFilter: 0,
  desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
  stopOnTerminate: false,
  startOnBoot: true,
  stopOnStationary: false,
  disableAutoSyncOnCellular: false,
  useSignificantChangesOnly: false,
}

const subscription = BackgroundGeolocation.onHeartbeat((event) => {
        BackgroundGeolocation.getCurrentPosition({
          samples: 1,
          persist: true,
        }).then((location) => {
            insertLocation({
              latitude: `${location?.coords?.latitude}`,
              longitude: `${location?.coords?.longitude}`,
           });
        });
      });

defaultLocationConfig: CurrentPositionRequest = {
  timeout: 30, 
  maximumAge: 1000, 
  desiredAccuracy: 1, 
  samples: 1,
  persist: false,
};


async (event: GeofenceEvent) => {
  let source = "";
  if (
    event.action === EGeolocationEvent.ENTER ||
    event.action === EGeolocationEvent.EXIT
  ) {
    source = event.action;
  }
  if (source) {
 
    const location = await BackgroundGeolocation.getCurrentPosition({
      ...defaultLocationConfig,
      extras: {
        ...event.extras,
        source,
      },
    });
  
      await insertLocation({
        latitude: `${location?.coords?.latitude}`,
        longitude: `${location?.coords?.longitude}`,
       
      });
  
    }
  }
};

Expected Behavior

Need to capture user location at 14 mins interval for longer durations like 8-9 hours. On both android and iOS. And save to app local storage. There is high possibility for the device to be stationary (left on desk) for longer durations. that means, the app should get data in background mostly and I am also using geoFence in addition to it. Any additional suggestions to achieve the above helps

Actual Behavior

App provides location values ones or twice while in background not more than that. later i think the app is terminated and geoFence isn't giving consistent enter/exit. At times I see records and at times I don't, with the same app on multiple tests.

@christocracy
Copy link
Member

Periodic event-handling is precisely what the background-fetch plugin is for. See its readme.

heartbeat should be avoided.

@kopposh
Copy link
Author

kopposh commented May 23, 2024

We have tried background-fetch initially but it didn't give any output in testing phase.

and also in the readme it says:
"iOS can take days before Apple's machine-learning algorithm settles in and begins regularly firing events. Do not sit staring at your logs waiting for an event to fire. If your simulated events work, that's all you need to know that everything is correctly configured.
If the user doesn't open your iOS app for long periods of time, iOS will stop firing events."

Hence we were doubtful about getting locations regularly. I will retry and share the implementation today.

@christocracy
Copy link
Member

Read the readme for background-fetch and learn how to simulate events. When simulated events fire, that’s all you need to know, that everything is operating correctly.

It works fine; no need to “doubt”.

@kopposh
Copy link
Author

kopposh commented May 23, 2024

I have gone through the readme. I don't see anything mentioned for android similar to simulate events in iOS. Do we have something to test on android as well?

@kopposh
Copy link
Author

kopposh commented May 23, 2024

I am initializing background fetch on start of application. followed the steps provided in readme file and tired to simulate events. but couldn't see any events fired.

const status = await BackgroundFetch.configure(
{
minimumFetchInterval: 20,
enableHeadless: true,
},
async (taskId) => {
try {
insertLocation({
latitude: ${location?.coords?.latitude},
longitude: ${location?.coords?.longitude},
});
}
} catch (err) {
console.log(
"BackgroundGeolocation.initBackgroundFetch error", err
);
}
BackgroundFetch.finish(taskId);
},
async (taskId) => {
BackgroundFetch.finish(taskId);
}
);

Screenshot 2024-05-23 at 4 27 44 PM

few questions:

  1. So, should "com.transistorsoft.fetch" be same or the identifier of app? I tried with the same identifier
  2. does the simulated events fire immediately or at the interval mentioned with minimumFetchInterval
  3. can we try on iPhone simulator or do we need to test on real devices only?

@christocracy
Copy link
Member

  1. Yes
  2. Immediately
  3. Simulated iOS events don’t work in simulator, as warned in the readme. Use a real device.

@kopposh
Copy link
Author

kopposh commented May 28, 2024

I have registered a headless task in my index.js to run when app is terminated on android along with BackgroundFetch.configure(code shown below) and receiving the below warning message.

WARN No task registered for key BackgroundFetch

useEffect(()=>{
BackgroundFetch.registerHeadlessTask(BGHeadlessTask);
},[])

const BGHeadlessTask = async (event: { taskId: any; timeout: any }) => {
let taskId = event.taskId;
let isTimeout = event.timeout;
if (isTimeout) {
BackgroundFetch.finish(taskId);
return;
}
try {
const location = await BackgroundGeolocation.getCurrentPosition({
timeout: 30,
maximumAge: 1000,
desiredAccuracy: 1,
samples: 1,
persist: false,
});
if (location && location?.coords) {
await insertLocation({
latitude: ${location?.coords?.latitude},
longitude: ${location?.coords?.longitude},
source: LOCATION_BG_TRACKING,
});
}
BackgroundFetch.finish(taskId);
} catch (err) {
BackgroundFetch.finish(taskId);
}
}

const status = await BackgroundFetch.configure(
{
minimumFetchInterval: 20,
enableHeadless: true,
stopOnTerminate: false,
},
async (taskId) => {
try {
const location = await BackgroundGeolocation.getCurrentPosition({
timeout: 30,
maximumAge: 1000,
desiredAccuracy: 1,
samples: 1,
persist: false,
});
insertLocation({
latitude: ${location?.coords?.latitude},
longitude: ${location?.coords?.longitude},
});
}
} catch (err) {
console.log(
"BackgroundGeolocation.initBackgroundFetch error", err
);
}
BackgroundFetch.finish(taskId);
},
async (taskId) => {
BackgroundFetch.finish(taskId);
}
);

screenshot when app is terminated for a while and opened again after receiving the warning:
Screenshot 2024-05-28 at 1 27 52 PM

@christocracy
Copy link
Member

christocracy commented May 28, 2024

If you have a question about background-fetch, please seek support by posting an issue there.

Also, please learn to syntax highlight “fenced code blocks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants