Expo BackgroundFetch
一个提供用于执行后台获取任务的 API 的库。
警告 已弃用:
expo-background-fetch库将被expo-background-task的新版本替代。expo-background-fetch不会再收到补丁,并将在即将发布的版本中移除。
expo-background-fetch 提供了一个 API 来执行 background fetch 任务,使你能够在后台定期运行特定代码以更新你的应用。该模块在底层使用了 TaskManager 原生 API。
已知问题 iOS
🌐 Known issues
BackgroundFetch 仅在应用处于后台时有效,如果应用已被终止或设备重启,则无效。你可以查看相关的 GitHub 问题了解更多详情。
在 iOS 上,BackgroundFetch 库要求你使用 开发版本,因为在 iOS Expo Go 应用中未启用后台获取功能。
🌐 On iOS the BackgroundFetch library requires you to use a development build since Background Fetch is not enabled in the iOS Expo Go app.
安装
🌐 Installation
- npx expo install expo-background-fetchIf you are installing this in an existing React Native app, make sure to install expo in your project.
配置 iOS
🌐 Configuration
要在 iOS 上运行后台获取任务,你需要将 fetch 值添加到应用的 Info.plist 文件中的 UIBackgroundModes 数组中。这是后台获取正常工作所必需的。
🌐 To be able to run background fetch tasks on iOS, you need to add the fetch value to the UIBackgroundModes array in your app's Info.plist file. This is required for background fetch to work properly.
如果你正在使用 CNG,所需的 UIBackgroundModes 配置将会由预构建自动应用。
在 iOS 上手动配置 UIBackgroundModes
如果你没有使用连续本地生成(CNG)或者你是手动使用原生 iOS 项目,那么你需要将以下内容添加到你的 Expo.plist 文件中:
🌐 If you're not using Continuous Native Generation (CNG) or you're using a native ios project manually, then you'll need to add the following to your Expo.plist file:
<key>UIBackgroundModes</key> <array> <string>fetch</string> </array>
用法
🌐 Usage
下面是一个演示如何使用 expo-background-fetch 的示例。
🌐 Below is an example that demonstrates how to use expo-background-fetch.
import { useState, useEffect } 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] = useState(false); const [status, setStatus] = useState<BackgroundFetch.BackgroundFetchStatus | null>(null); 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(⌘ + 空格)搜索 Instruments 应用,也可以从
/Applications/Xcode.app/Contents/Applications/Instruments.app打开 - 选择
Time Profiler - 选择你的设备/模拟器,然后选择
Expo Go应用 - 按左上角的
Record按钮 - 导航到
Document菜单并选择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 }); }
应用接口
🌐 API
import * as BackgroundFetch from 'expo-background-fetch';
Methods
Deprecated: Use
getStatusAsync()fromexpo-background-taskinstead. Theexpo-background-fetchpackage has been deprecated.
Gets a status of background fetch.
Promise<BackgroundFetchStatus | null>Returns a promise which fulfils with one of BackgroundFetchStatus enum values.
Deprecated: Use
registerTaskAsync()fromexpo-background-taskinstead. Theexpo-background-fetchpackage has been deprecated.
| Parameter | 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; } });
Deprecated: Use the
registerTaskAsync()method from expo-background-task package, and specifyBackgroundTaskOptionsargument instead, when setting task interval time.
| Parameter | 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.
Deprecated: Use
unregisterTaskAsync()fromexpo-background-taskinstead. Theexpo-background-fetchpackage has been deprecated.
| Parameter | 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.
Interfaces
| Property | 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 |
Enums
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.
BackgroundFetchStatus.Denied = 1The user explicitly disabled background behavior for this app or for the whole system.
BackgroundFetchStatus.Restricted = 2Background 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 启动的任务是必要的。它还会保持即将进入闲置和快速休眠状态的设备“唤醒”,以提高任务的可靠性。因此,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. |