expo.io's BackgroundFetch is not running the defined task
Asked Answered
K

1

31

I am currently developing an app for iOS with expo sdk-version 32. I have to call a REST service periodically from my app. In order to do that I tried to utilize the new BackgroundFetch API.

Here is my Code:

const BACKGROUND_LOCATION_SENDING_TASK = "BACKGROUND_LOCATION_SENDING_TASK";

async function initBackgroundLocationSending() {
    console.log("initBackgroundLocationSending()");

    TaskManager.defineTask(BACKGROUND_LOCATION_SENDING_TASK, () => {

        // this console.log does never get called ... 
        console.log("BACKGROUND_LOCATION_SENDING_TASK");

        // i will implement real fetch logic here when i found out how to get this function called.
        return BackgroundFetch.Result.NewData;
    });

    console.log("is task registered ... ");
    let isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_LOCATION_SENDING_TASK);
    console.log("isRegistered: ", isRegistered);

    if(isRegistered) {
        console.log("unregister task ...");
        await BackgroundFetch.unregisterTaskAsync(BACKGROUND_LOCATION_SENDING_TASK);
        console.log("Done");
    }

    console.log("is task registered ... ");
    isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_LOCATION_SENDING_TASK);
    console.log("isRegistered: ", isRegistered);

    console.log("register task ...");
    await BackgroundFetch.registerTaskAsync(BACKGROUND_LOCATION_SENDING_TASK);
    console.log("OK");


    console.log("is task registered ... ");
    isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_LOCATION_SENDING_TASK);
    console.log("isRegistered: ", isRegistered);

    console.log("set minimum interval ...");
    await BackgroundFetch.setMinimumIntervalAsync(60);
    console.log("OK");

    console.log("get status ... ");
    const status = await BackgroundFetch.getStatusAsync();
    console.log("status: ", status);
}

Console output from calling the function from within App.js:

: initBackgroundLocationSending()
: is task registered ...
: isRegistered:  true
: unregister task ...
: OK
: is task registered ...
: isRegistered:  false
: register task ...
: OK
: is task registered ...
: isRegistered:  true
: set minimum interval ...
: OK
: get status ...
: status:  3

From expo's background-fetch documentation I understand that status: 3 means BackgroundFetch.Status.Available.

the iOS section from my app.json:

...
"ios": {
  "supportsTablet": true,
  "bundleIdentifier": "xxx-yyy-zzz",
  "infoPlist": {
    "UIBackgroundModes": [
      "location",
      "fetch"
    ],
    "NSLocationWhenInUseUsageDescription": "... (replaced)",
    "NSLocationAlwaysAndWhenInUseUsageDescription": "... (replaced)",
    "NSLocationAlwaysUsageDescription": "... (replaced)"
  }
},
...

My testing device is an IPhone 6s with iOS 12.1.3.

What am I missing? Why does it not run the task at all even not after some minutes?

btw: I use expo's background location without any problems

Kate answered 17/2, 2019 at 11:16 Comment(4)
Why was my question downvoted? Please let me know the reason so i can improve it.Kate
having the same issue, opened an issue on github about it github.com/expo/expo/issues/3582Pittel
Here's a more recent unclosed version of the issue github.com/expo/expo/issues/9900 with an MVCEAcanthus
One thing you're missing is the custom Expo IOS client build expo client:ios BUT even with that I am still unable to get it to work correctly.Acanthus
L
1

I would try by moving the task definitions to global scope, as documentation states, since the way you set it up currently is defined inside a function scope

  1. Define the task by providing a name and the function that should be executed Note: This needs to be called in the global scope (e.g outside of your React components)

Meaning this

const BACKGROUND_LOCATION_SENDING_TASK = "BACKGROUND_LOCATION_SENDING_TASK";

async function initBackgroundLocationSending() {
    console.log("initBackgroundLocationSending()");

    TaskManager.defineTask(BACKGROUND_LOCATION_SENDING_TASK, () => {

        // this console.log does never get called ... 
        console.log("BACKGROUND_LOCATION_SENDING_TASK");

        // i will implement real fetch logic here when i found out how to get this function called.
        return BackgroundFetch.Result.NewData;
    });

    ....

}

Should change to this

const BACKGROUND_LOCATION_SENDING_TASK = "BACKGROUND_LOCATION_SENDING_TASK";

 TaskManager.defineTask(BACKGROUND_LOCATION_SENDING_TASK, () => {

     // this console.log does never get called ... 
     console.log("BACKGROUND_LOCATION_SENDING_TASK");

     // i will implement real fetch logic here when i found out how to get this function called.
     return BackgroundFetch.Result.NewData;
 });


async function initBackgroundLocationSending() {
    console.log("initBackgroundLocationSending()");

    ...

}

The rest of initBackgroundLocationSending that handles the registration of the task should be called on component mount

Lezley answered 26/1, 2022 at 0:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.