一个通用库,提供用于执行后台获取任务的 API。
expo-background-fetch
提供了执行 后台获取 任务的 API,允许你在后台定期运行特定代码来更新你的应用。该模块在底层使用 TaskManager Native API。
¥expo-background-fetch
provides an API to perform background fetch tasks, allowing you to run specific code periodically in the background to update your app. This module uses TaskManager Native API under the hood.
¥Known issues
BackgroundFetch
仅在应用处于后台时有效,而在应用终止或设备重新启动时无效。你可以查看 相关的 GitHub 问题 了解更多详细信息。
¥BackgroundFetch
only works when the app is backgrounded, not if the app was terminated or upon device reboot.
You can check out the relevant GitHub issue for more details.
¥Installation
-
npx expo install expo-background-fetch
If you are installing this in an existing React Native app (bare workflow), start by installing expo
in your project. Then, follow the additional instructions as mentioned by library's README under "Installation in bare React Native projects" section.
¥Configuration
了解如何在 expo-background-fetch
存储库中的安装说明 文件中配置原生项目。
¥Learn how to configure the native projects in the installation instructions in the expo-background-fetch
repository.
¥Usage
下面是一个演示如何使用 expo-background-fetch
的示例。
¥Below is an example that demonstrates how to use expo-background-fetch
.
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';
const BACKGROUND_FETCH_TASK = 'background-fetch';
// 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)
TaskManager.defineTask(BACKGROUND_FETCH_TASK, async () => {
const now = Date.now();
console.log(`Got background fetch call at date: ${new Date(now).toISOString()}`);
// Be sure to return the successful result type!
return BackgroundFetch.BackgroundFetchResult.NewData;
});
// 2. Register the task at some point in your app by providing the same name,
// and some configuration options for how the background fetch should behave
// Note: This does NOT need to be in the global scope and CAN be used in your React components!
async function registerBackgroundFetchAsync() {
return BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
minimumInterval: 60 * 15, // 15 minutes
stopOnTerminate: false, // android only,
startOnBoot: true, // android only
});
}
// 3. (Optional) Unregister tasks by specifying the task name
// This will cancel any future background fetch 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 unregisterBackgroundFetchAsync() {
return BackgroundFetch.unregisterTaskAsync(BACKGROUND_FETCH_TASK);
}
export default function BackgroundFetchScreen() {
const [isRegistered, setIsRegistered] = React.useState(false);
const [status, setStatus] = React.useState(null);
React.useEffect(() => {
checkStatusAsync();
}, []);
const checkStatusAsync = async () => {
const status = await BackgroundFetch.getStatusAsync();
const isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_FETCH_TASK);
setStatus(status);
setIsRegistered(isRegistered);
};
const toggleFetchTask = async () => {
if (isRegistered) {
await unregisterBackgroundFetchAsync();
} else {
await registerBackgroundFetchAsync();
}
checkStatusAsync();
};
return (
<View style={styles.screen}>
<View style={styles.textContainer}>
<Text>
Background fetch status:{' '}
<Text style={styles.boldText}>
{status && BackgroundFetch.BackgroundFetchStatus[status]}
</Text>
</Text>
<Text>
Background fetch task name:{' '}
<Text style={styles.boldText}>
{isRegistered ? BACKGROUND_FETCH_TASK : 'Not registered yet!'}
</Text>
</Text>
</View>
<View style={styles.textContainer}></View>
<Button
title={isRegistered ? 'Unregister BackgroundFetch task' : 'Register BackgroundFetch task'}
onPress={toggleFetchTask}
/>
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
textContainer: {
margin: 10,
},
boldText: {
fontWeight: 'bold',
},
});
¥Triggering background fetches
后台提取可能很难测试,因为它们的发生可能不一致。幸运的是,你可以在开发应用时手动触发后台提取。
¥Background fetches can be difficult to test because they can happen inconsistently. Fortunately, you can trigger background fetches manually when developing your apps.
对于 iOS,你可以使用 macOS 上的 Instruments
应用手动触发后台提取:
¥For iOS, you can use the Instruments
app on macOS to manually trigger background fetches:
打开仪器应用。Instruments 应用可以通过 Spotlight(⌘ + Space)搜索或从 /Applications/Xcode.app/Contents/Applications/Instruments.app
打开
¥Open the Instruments app. The Instruments app can be searched through Spotlight (⌘ + Space) or opened from /Applications/Xcode.app/Contents/Applications/Instruments.app
选择 Time Profiler
¥Select Time Profiler
选择你的设备/模拟器并选择 Expo Go
应用
¥Select your device / simulator and pick the Expo Go
app
按左上角的 Record
按钮
¥Press the Record
button in the top left corner
导航至 Document
菜单并选择 Simulate Background Fetch - Expo Go
:
¥Navigate to the Document
Menu and select Simulate Background Fetch - Expo Go
:
对于 Android,你可以将任务的 minimumInterval
选项设置为一个较小的数字并让你的应用后台运行,如下所示:
¥For Android, you can set the minimumInterval
option of your task to a small number and background your application like so:
async function registerBackgroundFetchAsync() {
return BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
minimumInterval: 1 * 60, // task will fire 1 minute after app is backgrounded
});
}
import * as BackgroundFetch from 'expo-background-fetch';
BackgroundFetch.getStatusAsync()
Gets a status of background fetch.
Promise<BackgroundFetchStatus | null>
Returns a promise which fulfils with one of BackgroundFetchStatus
enum values.
BackgroundFetch.registerTaskAsync(taskName, options)
Name | Type | Description |
---|---|---|
taskName | string | Name of the task to register. The task needs to be defined first - see |
options (optional) | BackgroundFetchOptions | An object containing the background fetch options. Default: {} |
Registers background fetch task with given name. Registered tasks are saved in persistent storage and restored once the app is initialized.
Promise<void>
Example
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';
TaskManager.defineTask(YOUR_TASK_NAME, () => {
try {
const receivedNewData = // do your background fetch here
return receivedNewData ? BackgroundFetch.BackgroundFetchResult.NewData : BackgroundFetch.BackgroundFetchResult.NoData;
} catch (error) {
return BackgroundFetch.BackgroundFetchResult.Failed;
}
});
BackgroundFetch.setMinimumIntervalAsync(minimumInterval)
Name | Type | Description |
---|---|---|
minimumInterval | number | Number of seconds that must elapse before another background fetch can be called. |
Sets the minimum number of seconds that must elapse before another background fetch can be initiated. This value is advisory only and does not indicate the exact amount of time expected between fetch operations.
This method doesn't take any effect on Android. It is a global value which means that it can overwrite settings from another application opened through Expo Go.
Promise<void>
A promise which fulfils once the minimum interval is set.
BackgroundFetch.unregisterTaskAsync(taskName)
Name | Type | Description |
---|---|---|
taskName | string | Name of the task to unregister. |
Unregisters background fetch task, so the application will no longer be executing this task.
Promise<void>
A promise which fulfils when the task is fully unregistered.
BackgroundFetchOptions
BackgroundFetchOptions Properties
Name | Type | Description |
---|---|---|
minimumInterval (optional) | number | Inexact interval in seconds between subsequent repeats of the background fetch alarm. The final interval may differ from the specified one to minimize wakeups and battery usage.
|
startOnBoot (optional) | boolean | Only for: Android Whether to restart background fetch events when the device has finished booting. Default: false |
stopOnTerminate (optional) | boolean | Only for: Android Whether to stop receiving background fetch events after user terminates the app. Default: true |
BackgroundFetchResult
This return value is to let iOS know what the result of your background fetch was, so the platform can better schedule future background fetches. Also, your app has up to 30 seconds to perform the task, otherwise your app will be terminated and future background fetches may be delayed.
BackgroundFetchResult Values
BackgroundFetchStatus
BackgroundFetchStatus Values
Denied
BackgroundFetchStatus.Denied = 1
The user explicitly disabled background behavior for this app or for the whole system.
Restricted
BackgroundFetchStatus.Restricted = 2
Background updates are unavailable and the user cannot enable them again. This status can occur when, for example, parental controls are in effect for the current user.
¥Permissions
¥Android
在 Android 上,此模块可能会在设备启动时进行监听。有必要继续完成从 startOnBoot
开始的任务。它还使处于空闲和睡眠状态的设备 "awake" 保持快速状态,以提高任务的可靠性。因此,RECEIVE_BOOT_COMPLETED
和 WAKE_LOCK
权限都会自动添加。
¥On Android, this module might listen when the device is starting up. It's necessary to continue working on tasks started with startOnBoot
. It also keeps devices "awake" that are going idle and asleep fast, to improve reliability of the tasks. Because of this both the RECEIVE_BOOT_COMPLETED
and WAKE_LOCK
permissions are added automatically.
Android Permission | Description |
---|---|
Allows an application to receive the Intent.ACTION_BOOT_COMPLETED that is broadcast after the system finishes booting.
| |
Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming. |
¥iOS
要在 iOS 上的独立应用中使用 BackgroundFetch
API,你的应用必须在 Info.plist 文件中包含后台模式。详细信息请参见 后台任务配置指南。
¥To use BackgroundFetch
API in standalone apps on iOS, your app has to include background mode in the Info.plist file. See background tasks configuration guide for more details.