expo.io的BackgroundFetch没有运行定义的任务

Str*_*eck 7 ios background-fetch react-native expo

我目前正在使用expd sdk-version 32开发适用于iOS的应用程序。我必须定期从我的应用程序调用REST服务。为此,我尝试利用新的BackgroundFetch API。

这是我的代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

expo的background-fetch文档中,我了解到该状态:3表示BackgroundFetch.Status.Available

我的app.json中iOS部分:

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

我的测试设备是带有iOS 12.1.3的IPhone 6s。

我想念什么?为什么即使几分钟后它也根本不运行任务?

顺便说一句:我使用expo的背景位置没有任何问题

小智 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;
    });

    ....

}
Run Code Online (Sandbox Code Playgroud)

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()");

    ...

}
Run Code Online (Sandbox Code Playgroud)

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