DEV Community 👩‍💻👨‍💻

Cover image for A Close Look at "React Native Background Fetch"
Chris Dougherty
Chris Dougherty

Posted on

A Close Look at "React Native Background Fetch"

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

  1. Main features
  2. Platform implementation comparison
  3. Comparison with other modules
  4. The native technology behind RNBF
  5. Benchmark tests (Coming Soon)
  6. Configurations for iOS and Android
  7. Configurations for Android only
  8. Methods
  9. 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)
Enter fullscreen mode Exit fullscreen mode

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({ ... })
Enter fullscreen mode Exit fullscreen mode

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
})
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Call initBackgroundFetch() to start worker in background.
  2. Worker waits for a minimum of 15 minutes.
  3. Worker triggers handleTask() to do background work.
  4. The task finishes.
  5. The worker waits again for another minimum of 15 minutes.
  6. The worker triggers handleTask() a second time to do more background work.
  7. The second task finishes.
  8. 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()
Enter fullscreen mode Exit fullscreen mode

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:

  1. Call initBackgroundFetch() to start worker in background.
  2. User presses a button that triggers scheduleTask().
  3. The scheduleTask() function schedules a task to be worked on. If you have included delay in the config, that delay will specify the time between when the button is pressed and when the worker will begin handling the task.
  4. After an optionally specified delay, RNBF starts working on the task.
  5. 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'
      />
    </>
  )

}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.