react-native-background-fetch (RNBF) provides background processing that can optimize the performance of an application's user interface. RNBF is for React Native applications and has support for both iOS and Android. The following post is a high-level but thorough description of this module's features. Further, we take a more detailed look at the native Android and iOS technology behind the module. For more information about installation, setup and simulating events, check out the docs here.
Table of contents
- Main features
- Platform implementation comparison
- Comparison with other modules
- The native technology behind RNBF
- Benchmark tests (Coming Soon)
- Configurations for iOS and Android
- Configurations for Android only
- Methods
- Basic examples
Main features
- Provides background processing for React Native applications on both iOS and Android.
- (Android Only) Support for manually triggering RNBF to handle a background task. This can be triggered by the user OR the application itself.
- (iOS and Android) Also has support for allowing the OS to determine when RNBF will periodically handle background tasks. This typically occurs at a minimum of 15 minutes per interval but can change due to several factors including frequency of device usage.
Platform implementation comparison
iOS
- When your app is terminated, RNBF will NO longer be able to handle events on iOS.
- If a user doesn't open the application for a long period of time, RNBF will handle events less frequently.
- The user MUST have the "background app refresh" setting turned ON in order for RNBF to trigger background tasks on iOS. This setting is "ON" by default in iOS.
Android
- RNBF can continue handling events even after app termination.
- Support for options such as the ability to require that the battery or storage NOT be low in order to run the background worker.
- If needed, you can require that the device be connected to a charger in order to handle tasks.
- Also has the ability to optionally require that the device be idle in order to handle background tasks.
- If needed, you can manually trigger the background worker to start working on a task. This functionality also has the option to continuously run tasks one after another.
Comparison with other modules
Bottom line, I think that RNBF is currently the best overall React Native module for background processing. It works for both iOS and Android. And it is by far, the best maintained module with the most active support. Further, with that being said, there really aren't many great options available for React Native background processing. The alternatives are not well maintained and mostly do NOT have as many (working) features as RNBF. If you'd like to take a closer look at a comparison of background processing modules for React Native, check out this post. In the near future, I'll post a recipe of what would be the ideal React Native module for background processing.
The native technology behind RNBF
The following is a description of ONLY the features, of these technologies, that are made available to RNBF.
JobScheduler (Android)
- By default, RNBF uses this for Android.
- JobScheduler has the option to use its own internal mechanism for determining the intervals between when it triggers background events. If you use this option, JobScheduler prioritizes battery life by throttling task execution.
- If needed, you can manually schedule tasks instead of relying on JobScheduler to determine when tasks are handled.
- Depending on the Android version, JobScheduler might stop a task before it is finished. For build version code "LOLLIPOP", jobs have a maximum execution time of 1 minute. Starting with build version code "M" and ending with "R", jobs have a maximum execution time of 10 minutes. Starting from build version code "S", jobs will NOT be stopped after 10 minutes UNLESS the system is busy or needs extra resources. If you want to understand more about how build version codes relate to versions of Android, SDK levels and more, please see this guide.
AlarmManager (Android)
- RNBF gives you the option to bypass JobScheduler in order to use native Android's AlarmManager.
- In comparison to JobScheduler, AlarmManager executes tasks more frequently at the cost of higher battery usage.
- Like JobScheduler, you can also manually schedule tasks instead of relying on the native module to determine when tasks are handled.
BGTaskScheduler (iOS)
- This is the only native module that RNBF uses for iOS.
- With this native module, you do NOT have the option to manually trigger task execution. Instead, you have to rely on the BGTaskScheduler to do that for you.
- BGTaskScheduler will automatically limit how often tasks are triggered based on usage patterns. For instance, if a user hasn't turned on their device for a long period of time, tasks will be started less frequently once the device is turned on.
- It can take days before Apple's machine-learning algorithm behind BGTaskScheduler to regularly trigger tasks.
- In order to avoid having to wait long periods of time before BGTaskScheduler will start events, you can use simulated events for development / testing. If the simulated events are working correctly, then you have correctly configured RNBF for BGTaskScheduler / iOS.
Benchmark tests
(COMING SOON)
In the near future, I'll detail the results of some basic tests in order to provide some more insight into the capabilities of RNBF. Examples of some of these tests include "when using OS determined event triggering, how often does RNBF try to start new tasks", "does the worker automatically prevent multiple tasks from running at the same time", and "under certain conditions, how long will RNBF run a single task before timing out?".
Configurations for iOS and Android
requiredNetworkType
This configuration specifies what type of network connection (if any) is required for RNBF to handle events. You can choose between "none", "any", "cellular", "unmetered" or "not roaming".
minimumFetchInterval
Sets the amount of time in minutes between OS determined executions of events. Defaults to 15 minutes (which is also the minimum).
Configurations for Android only
stopOnTerminate
Set false
in order to continue background work even after user terminates the app.
enableHeadless
Set true
in order to use React Native's Headless JS feature for continuing background work after app termination.
startOnBoot
Continue background work when device is rebooted.
forceAlarmManager
By default, RNBF uses Android's JobScheduler. Setting forceAlarmManager: true
will bypass JobScheduler to use Android's AlarmManager.
requiresBatteryNotLow
Set true
in order to ONLY run the background worker if the battery is NOT low. "Low" is considered to be at the point where a user is given a "low battery" warning.
requiresStorageNotLow
Setting requiresStorageNotLow: true
will cause the background worker to ONLY run when storage is NOT low. "Low" is considered to be at the point that a user is given a "low storage" warning.
requiresCharging
Set true
in order to require that the device be connected to a charger for the module to do background work.
requiresDeviceIdle
When set true
, the background worker will ONLY work on tasks if the device is NOT in active use.
periodic
Valid only for the scheduleTask
method. Set true
to execute the task handling callback repeatedly. When false
, the task handling callback will execute just once.
Methods
configure
Add configuration options and specify the callback function to handle background work. Also specify a timeout function that runs when a task has reached its allowed execution duration. Example:
BackgroundFetch.configure({
forceAlarmManager: true,
... <MORE CONFIG HERE>
}, handleTask, onTimeout)
status (iOS Only)
Returns the status of the background worker as either "restricted" (0), "denied" (1) or "available" (2). Example:
const status = await BackgroundFetch.configure({ ... })
scheduleTask (Android Only)
Use this method to manually execute background work. Set periodic: true
in the config to keep triggering scheduleTask
over and over. This method executes the same task handling callback function that the configure
method defines. You can also specify a delay between the calling of this method and when the module starts working on a task. Example:
await BackgroundFetch.scheduleTask({
taskId: 'TASK ID HERE',
delay: 3000, // amount of time in ms between when scheduleTask() is called and the execution of the task
forceAlarmManager: true
})
stop
Stop all background work. Optionally, if you provide a taskId
as an argument, you can stop a specific call to scheduleTask
.
finish
This must be called at the end of the callback function that handles your background task in order to signal to the OS that the task is complete. Example:
const handleTask = async (taskId) => {
// Do background work here
BackgroundFetch.finish(taskId)
}
Basic examples
Here are a couple basic examples of how to use RNBF in order to give you a sense of the overall implementation approach. For more detailed and specific examples, please check out the docs and / or the example app.
OS determined task schedule (iOS and Android)
This is an example of how to implement a worker that allows the OS to determine when RNBF will periodically handle background tasks. Here is an example of a timeline for how this type of worker functions:
- Call
initBackgroundFetch()
to start worker in background. - Worker waits for a minimum of 15 minutes.
- Worker triggers
handleTask()
to do background work. - The task finishes.
- The worker waits again for another minimum of 15 minutes.
- The worker triggers
handleTask()
a second time to do more background work. - The second task finishes.
- Steps 2 - 7 are repeated.
// Example of OS determined task schedule
import BackgroundFetch from 'react-native-background-fetch'
// Start the background worker
const initBackgroundFetch = async () => {
const status = await BackgroundFetch.configure({
minimumFetchInterval: 15, // 15 minutes
// ADDITIONAL CONFIG HERE
}, handleTask, onTimeout)
console.log('[ RNBF STATUS ]', status)
}
// handleTask is called periodically when RNBF triggers an event
const handleTask = async (taskId) => {
console.log('[ RNBF TASK ID ]', taskId)
// DO BACKGROUND WORK HERE
// This MUST be called in order to signal to the OS that your task is complete
BackgroundFetch.finish(taskId)
}
const onTimeout = async () => {
// The timeout function is called when the OS signals that the task has reached its maximum execution time.
// ADD CLEANUP WORK HERE (IF NEEDED)
BackgroundFetch.finish(taskId)
}
initBackgroundFetch()
Manually determined task schedule (Android Only)
This is an example of how to implement a worker that allows the application or user to manually schedule tasks instead of relying on the OS to determine when a task will be worked on. For example, this type of worker can be triggered to handle a task by pressing a button (or some other manual event). IMPORTANT: In this type of worker, if you set periodic: true
in the config, the worker will continuously handle tasks over and over again. Here is an example timeline of how this type of worker would function:
- Call
initBackgroundFetch()
to start worker in background. - User presses a button that triggers
scheduleTask()
. - The
scheduleTask()
function schedules a task to be worked on. If you have includeddelay
in the config, that delay will specify the time between when the button is pressed and when the worker will begin handling the task. - After an optionally specified delay, RNBF starts working on the task.
- If
periodic: true
is set in the config, steps 3 - 4 will occur over and over again.
// Example of a manually determined task schedule
import BackgroundFetch from 'react-native-background-fetch'
export default MyComponent = () => {
// Start the background worker
const initBackgroundFetch = async () => {
const status = await BackgroundFetch.configure({
minimumFetchInterval: 15, // minutes
// ADDITIONAL CONFIG HERE
}, handleTask, onTimeout)
console.log('[ RNBF STATUS ]', status)
}
// handleTask is called periodically when RNBF triggers an event
const handleTask = async (taskId) => {
console.log('[ RNBF TASK ID ]', taskId)
// DO BACKGROUND WORK HERE
// This MUST be called in order to signal to the OS that your task is complete
BackgroundFetch.finish(taskId)
}
const onTimeout = async () => {
// The timeout function is called when the OS signals that the task has reached its maximum execution time.
// ADD CLEANUP WORK HERE (IF NEEDED)
BackgroundFetch.finish(taskId)
}
// Schedule task to be handled by background worker
const scheduleTask = async () => {
await BackgroundFetch.scheduleTask({
taskId: 'uuid.v4()',
delay: 5000,
forceAlarmManager: true
})
}
return (
<>
<Button
onPress={scheduleTask}
title='Do background work'
/>
</>
)
}
Top comments (0)