Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo BackgroundTask

一个提供用于运行后台任务的 API 的库。

Android
iOS
tvOS
Included in Expo Go
Recommended version:
~58.0.1

expo-background-task 提供了一个 API,用于以优化终端用户设备电池和电量消耗的方式运行可延迟的后台任务。此模块在 Android 上使用 WorkManager API,在 iOS 上使用 BGTaskScheduler API 来安排任务。它还使用 expo-task-manager Native API 来运行 JavaScript 任务。

观看:Expo Background Task 深入解析
观看:Expo Background Task 深入解析

使用 expo-background-task 在后台同步数据、预取内容并运行延迟工作。

后台任务

后台任务是在后台执行、独立于应用生命周期之外的可延迟工作单元。这对于需要在应用处于非活动状态时执行的任务很有用,例如与服务器同步数据、获取新内容,甚至检查是否有任何 expo-updates。

后台任务何时运行?

Expo Background Task API 利用各个平台,在应用处于后台时,于对用户和设备而言最合适的时间执行任务。

这意味着任务可能不会在安排后立即运行,但如果系统决定运行,它会在未来某个时间运行。你可以指定任务运行的最小时间间隔(以分钟为单位)。在指定的时间间隔过去后,只要满足指定条件,任务就会在某个时间执行。

只有在电池电量充足(或设备已接通电源)且网络可用时,后台任务才会运行。不满足这些条件时,任务不会执行。具体行为会因操作系统而异。

后台任务何时会停止?

后台任务由平台 API 和系统限制管理。了解任务何时停止有助于有效规划其使用方式。

  • 如果用户强制关闭应用,后台任务会停止。应用重启后,任务会恢复。
  • 如果系统停止应用或设备重启,后台任务会恢复,并且应用会重新启动。

在 Android 上,从最近使用的应用列表中移除应用并不会完全停止应用;而在 iOS 上,在应用切换器中向上滑动关闭应用会完全终止应用。

平台差异

Android 
Android

在 Android 上,WorkManager API 允许为任务指定最小运行间隔(最少 15 分钟)。在指定的时间间隔过去后,只要满足指定条件,任务就会在某个时间执行。

iOS 
iOS

在 iOS 上,BGTaskScheduler API 会决定启动后台任务的最佳时间。系统会考虑电池电量、网络可用性和用户的使用模式,以确定何时运行任务。你仍然可以为任务指定最小运行间隔,但系统可能会选择在更晚的时间运行任务。

已知限制

iOS 
iOS

Background Tasks API 在 iOS 模拟器上不可用。它仅在实体设备上运行时可用。

安装

Terminal
- npx expo install expo-background-task
- yarn expo install expo-background-task
- pnpm expo install expo-background-task
- bun expo install expo-background-task

If you are installing this in an existing React Native app, make sure to install expo in your project.

在应用配置中进行配置 
iOS

要在 iOS 上运行后台任务,需要将以下内容添加到应用的 Info.plist 文件中:

  • 将 processing 值添加到 UIBackgroundModes 数组中。这会启用后台处理功能。
  • 添加包含 com.expo.modules.backgroundtask.processing 标识符的 BGTaskSchedulerPermittedIdentifiers 数组。这会注册允许使用的后台任务标识符。

如果你使用的是 CNG,prebuild 会自动应用所需的 UIBackgroundModes 和 BGTaskSchedulerPermittedIdentifiers 配置。

在 iOS 上手动配置 Info.plist

如果你未使用 Continuous Native Generation(CNG),则需要将以下内容添加到应用的 Info.plist 文件中:

ios/project-name/Supporting/Info.plist
<key>UIBackgroundModes</key> <array> <string>processing</string> </array> <key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>com.expo.modules.backgroundtask.processing</string> </array>

使用

下面的示例演示了如何使用 expo-background-task。

App.tsx
import * as BackgroundTask from 'expo-background-task'; import * as TaskManager from 'expo-task-manager'; import { useEffect, useState } from 'react'; import { StyleSheet, Text, View, Button } from 'react-native'; const BACKGROUND_TASK_IDENTIFIER = 'background-task'; // Register and create the task so that it is available also when the background task screen // (a React component defined later in this example) is not visible. // Note: This needs to be called in the global scope, not in a React component. TaskManager.defineTask(BACKGROUND_TASK_IDENTIFIER, async () => { try { const now = Date.now(); console.log(`Got background task call at date: ${new Date(now).toISOString()}`); } catch (error) { console.error('Failed to execute the background task:', error); return BackgroundTask.BackgroundTaskResult.Failed; } return BackgroundTask.BackgroundTaskResult.Success; }); // 2. Register the task at some point in your app by providing the same name // Note: This does NOT need to be in the global scope and CAN be used in your React components! async function registerBackgroundTaskAsync() { return BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER); } // 3. (Optional) Unregister tasks by specifying the task name // This will cancel any future background task calls that match the given name // Note: This does NOT need to be in the global scope and CAN be used in your React components! async function unregisterBackgroundTaskAsync() { return BackgroundTask.unregisterTaskAsync(BACKGROUND_TASK_IDENTIFIER); } export default function BackgroundTaskScreen() { const [isRegistered, setIsRegistered] = useState<boolean>(false); const [status, setStatus] = useState<BackgroundTask.BackgroundTaskStatus | null>(null); useEffect(() => { updateAsync(); }, []); const updateAsync = async () => { const status = await BackgroundTask.getStatusAsync(); setStatus(status); const isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_TASK_IDENTIFIER); setIsRegistered(isRegistered); }; const toggle = async () => { if (!isRegistered) { await registerBackgroundTaskAsync(); } else { await unregisterBackgroundTaskAsync(); } await updateAsync(); }; return ( <View style={styles.screen}> <View style={styles.textContainer}> <Text> Background Task Service Availability:{' '} <Text style={styles.boldText}> {status ? BackgroundTask.BackgroundTaskStatus[status] : null} </Text> </Text> </View> <Button disabled={status === BackgroundTask.BackgroundTaskStatus.Restricted} title={isRegistered ? 'Cancel background task' : 'Schedule background task'} onPress={toggle} /> <Button title="Check background task status" onPress={updateAsync} /> </View> ); } const styles = StyleSheet.create({ screen: { flex: 1, justifyContent: 'center', alignItems: 'center', }, textContainer: { margin: 10, }, boldText: { fontWeight: 'bold', }, });

多个后台任务

由于 iOS 上的 Background Tasks API 和 Android 上的 WorkManager API 限制了单个应用可安排的任务数量,因此 Expo Background Task 在两个平台上都使用单个 worker。虽然你可以定义多个 JavaScript 后台任务,但它们都会通过此单个 worker 运行。

最后注册的后台任务决定执行的最小时间间隔。

测试后台任务

可以使用 triggerTaskWorkerForTestingAsync 方法测试后台任务。此方法会在 Android 上直接运行所有已注册的任务,并在 iOS 上调用 BGTaskScheduler。这对于测试后台任务的行为很有用,无需等待系统触发这些任务。

此方法仅在开发模式下可用。在生产构建中无法使用。

import * as BackgroundTask from 'expo-background-task'; import { Button } from 'react-native'; function App() { const triggerTask = async () => { await BackgroundTask.triggerTaskWorkerForTestingAsync(); }; return <Button title="Trigger background task" onPress={triggerTask} />; }

检查后台任务 
Android

要排查或调试 Android 上的后台任务问题,请使用 Android SDK 中包含的 adb 工具检查已安排的任务,并将 <package-name> 替换为应用配置中的 Android package name:

Terminal
- adb shell dumpsys jobscheduler | grep -A 40 -m 1 -E "JOB #.* <package-name>"

此命令的输出会显示应用已安排的任务,包括其状态、约束和其他信息。在输出中查找 JOB 行,以找到作业的 ID 和其他详细信息:

JOB #u0a453/275: 216a359 <package-name>/androidx.work.impl.background.systemjob.SystemJobService u0a453 tag=*job*/<package-name>/androidx.work.impl.background.systemjob.SystemJobService#275 Source: uid=u0a453 user=0 pkg=<package-name> ... Required constraints: TIMING_DELAY CONNECTIVITY UID_NOT_RESTRICTED [0x90100000] Preferred constraints: Dynamic constraints: Satisfied constraints: CONNECTIVITY DEVICE_NOT_DOZING BACKGROUND_NOT_RESTRICTED TARE_WEALTH WITHIN_QUOTA UID_NOT_RESTRICTED [0x1b500000] Unsatisfied constraints: TIMING_DELAY [0x80000000] ... Enqueue time: -8m12s280ms Run time: earliest=+6m47s715ms, latest=none, original latest=none Restricted due to: none. Ready: false (job=false user=true !restricted=true !pending=true !active=true !backingup=true comp=true)

第一行包含 Job ID(275)。Run time: earliest 值表示任务可能开始的最早时间,而 enqueue time 则显示任务已安排了多长时间。

要强制运行任务,请使用 adb shell am broadcast 命令。运行此命令前,请将应用切换到后台,因为应用处于前台时任务不会运行。

Terminal
- adb shell cmd jobscheduler run -f <package-name> <JOB_ID>

其中,JOB_ID 是你希望运行的作业的标识符,该标识符可以在上一步中找到。

排查后台任务问题 
iOS

iOS 没有类似 adb 的工具来检查后台任务。要在 iOS 上测试后台任务,请使用内置的 triggerTaskWorkerForTestingAsync 方法。此方法会模拟系统触发任务。

你可以在调试模式下从应用中触发此方法(在生产构建中无法使用),以便在无需等待系统的情况下测试后台任务的行为。如果后台任务配置不正确,你会在 Xcode 控制台中看到错误描述:

No task request with identifier com.expo.modules.backgroundtask.processing has been scheduled

上述错误表示你需要运行 prebuild,以将更改应用到应用配置中。

此错误还表示你必须运行 prebuild,将后台任务配置应用到应用中。此外,请确保已按照此示例定义并注册后台任务。

API

import * as BackgroundTask from 'expo-background-task';

Methods

BackgroundTask.getStatusAsync()

Android
iOS
tvOS

Returns the status for the Background Task API. On web, it always returns BackgroundTaskStatus.Restricted, while on native platforms it returns BackgroundTaskStatus.Available.

A BackgroundTaskStatus enum value or null if not available.

BackgroundTask.registerTaskAsync(taskName, options)

Android
iOS
tvOS
ParameterTypeDescription
taskNamestring

Name of the task to register. The task needs to be defined first - see TaskManager.defineTask for more details.

options(optional)BackgroundTaskOptions

An object containing the background task options.

Default:{}

Registers a background task with the given name. Registered tasks are saved in persistent storage and restored once the app is initialized.

Returns:
Promise<void>

Example

import * as TaskManager from 'expo-task-manager'; // Register the task outside of the component TaskManager.defineTask(BACKGROUND_TASK_IDENTIFIER, async () => { try { await AsyncStorage.setItem(LAST_TASK_DATE_KEY, Date.now().toString()); } catch (error) { console.error('Failed to save the last fetch date', error); return BackgroundTaskResult.Failed; } return BackgroundTaskResult.Success; });

You can now use the registerTaskAsync function to register the task:

BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER, {});

BackgroundTask.triggerTaskWorkerForTestingAsync()

Android
iOS
tvOS

When in debug mode this function will trigger running the background tasks. This function will only work for apps built in debug mode. This method is only available in development mode. It will not work in production builds.

Returns:
Promise<boolean>

A promise which fulfils when the task is triggered.

BackgroundTask.unregisterTaskAsync(taskName)

Android
iOS
tvOS
ParameterTypeDescription
taskNamestring

Name of the task to unregister.


Unregisters a background task, so the application will no longer be executing this task.

Returns:
Promise<void>

A promise which fulfils when the task is fully unregistered.

Event subscriptions

BackgroundTask.addExpirationListener(listener)

iOS
ParameterType
listener() => void

Adds a listener that is called when the background executor expires. On iOS, tasks can run for minutes, but the system can interrupt the process at any time. This listener is called when the system decides to stop the background tasks and should be used to clean up resources or save state. When the expiry handler is called, the main task runner is rescheduled automatically.

Returns:
{ remove: () => void }

An object with a remove method to unsubscribe the listener.

Types

BackgroundTaskOptions

Android
iOS
tvOS

Options for registering a background task

PropertyTypeDescription
minimumInterval(optional)number

Inexact interval in minutes between subsequent repeats of the background tasks. The final interval may differ from the specified one to minimize wakeups and battery usage.

  • Defaults to once every 12 hours (The minimum interval is 15 minutes)
  • The system controls the background task execution interval and treats the specified value as a minimum delay. Tasks won't run exactly on schedule. On iOS, short intervals are often ignored—the system typically runs background tasks during specific windows, such as overnight.

Enums

BackgroundTaskResult

Android
iOS
tvOS

Return value for background tasks.

Success

BackgroundTaskResult.Success = 1

The task finished successfully.

Failed

BackgroundTaskResult.Failed = 2

The task failed.

BackgroundTaskStatus

Android
iOS
tvOS

Availability status for background tasks

Restricted

BackgroundTaskStatus.Restricted = 1

Background tasks are unavailable.

Available

BackgroundTaskStatus.Available = 2

Background tasks are available for the app.