flutter_background_geolocation icon indicating copy to clipboard operation
flutter_background_geolocation copied to clipboard

[Help Wanted]: My task triggered by onLocation is being killed early

Open lfchris opened this issue 2 months ago • 5 comments

Required Reading

  • [x] Confirmed

Plugin Version

4.18.0

Mobile operating-system(s)

  • [x] iOS
  • [ ] Android

Device Manufacturer(s) and Model(s)

iPhone 15 Pro

Device operating-systems(s)

26.0.2

What do you require assistance about?

My task triggered by onLocation in the background is doing some network calls. These calls are being killed if running to long. Do you have any experiences with how much time the OS grants you to do things in the background?

[Optional] Plugin Code and/or Config


[Optional] Relevant log output


lfchris avatar Nov 01 '25 06:11 lfchris

Hey @lfchris,

This is a classic (and very frustrating) problem when dealing with background location on iOS!

To answer your direct question: The time the OS grants you inside the onLocation event is not a full background task window (like 30 seconds or 3 minutes). It's an extremely short window, often just a few seconds, intended only for very lightweight, synchronous processing. This is why your network calls are being killed—iOS is ruthless about this to save battery.

Solution: Don't make network calls in the onLocation handler.

The onLocation event is the wrong place for any asynchronous task that can fail (like a network call). The plugin is designed to handle this for you reliably.

The correct pattern is to use the plugin's built-in HTTP persistence. You configure the plugin with your server URL, and it takes care of everything:

It receives a location.

It immediately saves it to its internal SQLite database (this is very fast and synchronous).

Separately, the plugin uses its own native background task to batch-sync the locations from its database to your server.

This way, the plugin handles all the retries, connection failures, and "task killed" issues for you, and your onLocation event finishes instantly.

Your config should look something like this, (remove any fetch calls from your onLocation):

JavaScript

BackgroundGeolocation.configure({ // YOUR SERVER ENDPOINT url: 'https://your-server.com/api/locations',

// --- Settings for reliability --- autoSync: true, // Automatically sync to the URL autoSyncThreshold: 10, // Sync when 10 locations are queued batchSync: true, // Send locations in a batch (highly recommended) maxBatchSize: 100, // Max 100 locations per POST

// ... your other config (distanceFilter, etc.) }); Your onLocation event should only be used for things like updating the UI if the app is in the foreground.

Hope this helps!

  • when the plug-in in is in the moving state (State.isMoving == true), you have infinite background time -- your http requests should not be frozen.

  • when the plug-in is in the stationary state (ie location-services OFF), the OS will freeze your app almost immediately.

  • see api docs .startBackgroundTask.

  • you will have a better experience if you can offload your http requests to the plug-in's builtin http service.

christocracy avatar Nov 01 '25 12:11 christocracy

Hey @lfchris,

This is a classic (and very frustrating) problem when dealing with background location on iOS!

To answer your direct question: The time the OS grants you inside the onLocation event is not a full background task window (like 30 seconds or 3 minutes). It's an extremely short window, often just a few seconds, intended only for very lightweight, synchronous processing. This is why your network calls are being killed—iOS is ruthless about this to save battery.

Solution: Don't make network calls in the onLocation handler.

The onLocation event is the wrong place for any asynchronous task that can fail (like a network call). The plugin is designed to handle this for you reliably.

The correct pattern is to use the plugin's built-in HTTP persistence. You configure the plugin with your server URL, and it takes care of everything:

It receives a location.

It immediately saves it to its internal SQLite database (this is very fast and synchronous).

Separately, the plugin uses its own native background task to batch-sync the locations from its database to your server.

This way, the plugin handles all the retries, connection failures, and "task killed" issues for you, and your onLocation event finishes instantly.

Your config should look something like this, (remove any fetch calls from your onLocation):

JavaScript

BackgroundGeolocation.configure({ // YOUR SERVER ENDPOINT url: 'https://your-server.com/api/locations',

// --- Settings for reliability --- autoSync: true, // Automatically sync to the URL autoSyncThreshold: 10, // Sync when 10 locations are queued batchSync: true, // Send locations in a batch (highly recommended) maxBatchSize: 100, // Max 100 locations per POST

// ... your other config (distanceFilter, etc.) }); Your onLocation event should only be used for things like updating the UI if the app is in the foreground.

Hope this helps!

@justin55afdfdsf5ds45f4ds5f45ds4 Thank you for your comprehensive explanation. I do not think I can use the plugin's built-in HTTP method because I need to do the things via a library which are then doing the network calls. This needs to be done on the device. Concretely, the app subscribes to certain firebase fcm topics on location changes.

lfchris avatar Nov 01 '25 14:11 lfchris

  • when the plug-in in is in the moving state (State.isMoving == true), you have infinite background time -- your http requests should not be frozen.
  • when the plug-in is in the stationary state (ie location-services OFF), the OS will freeze your app almost immediately.
  • see api docs .startBackgroundTask.
  • you will have a better experience if you can offload your http requests to the plug-in's builtin http service.

@christocracy Thank you for your explanation.

I am using useSignificantChangesOnly, so I do not have the moving and stationary states.

As I already explained to @justin55afdfdsf5ds45f4ds5f45ds4, the app subscribes to certain firebase fcm topics on location changes, so this needs to be done on the device by the fcm library and cannot be offloaded to the plug-in's builtin http service (I think).

But this sounds interesting: startBackgroundTask

Can I just call it from onLocation like:

bg.BackgroundGeolocation.onLocation((bg.Location location) async {
  bg.BackgroundGeolocation.startBackgroundTask().then((int taskId) {

  subscribeToTopics([topics]).then(() {
      BackgroundGeolocation.finish(taskId);
    });
  });
}, _onLocationError);

lfchris avatar Nov 01 '25 14:11 lfchris

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

github-actions[bot] avatar Dec 02 '25 02:12 github-actions[bot]

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

github-actions[bot] avatar Dec 16 '25 02:12 github-actions[bot]