vikeri / react-native-background-job

Schedule background jobs in React Native that run your JavaScript when your app is in the background/killed.
MIT License
747 stars 109 forks source link
background-jobs react-native scheduled-jobs

react-native-background-job npm version CircleCI

Schedule background jobs that run your JavaScript when your app is in the background or if you feel brave even in foreground.

The jobs will run even if the app has been closed and, by default, also persists over restarts.

This library relies on React Native's HeadlessJS which is currently only supported on Android.

On the native side it uses either Firebase JobDispatcher or a AlarmManager.

Requirements

Supported platforms

Want iOS? Go in and vote for Headless JS to be implemented for iOS: Product pains

Getting started

$ yarn add react-native-background-job

or

$ npm install react-native-background-job --save

Mostly automatic installation

$ react-native link react-native-background-job

Manual installation

Android

  1. Open up android/app/src/main/java/[...]/MainApplication.java

    • Add import com.pilloxa.backgroundjob.BackgroundJobPackage; to the imports at the top of the file.
    • Add new BackgroundJobPackage() to the list returned by the getPackages() method.
  2. Append the following lines to android/settings.gradle:

    include ':react-native-background-job'
    project(':react-native-background-job').projectDir = new File(rootProject.projectDir,   '../node_modules/react-native-background-job/android')
  3. Insert the following lines inside the dependencies block in android/app/build.gradle and bump the minSdkVersion to 21:

    compile project(':react-native-background-job')

Usage

The jobs have to be registered each time React Native starts, this is done using the register function. Since HeadlessJS does not mount any components the register function must be run outside of any class definitions (see example/index.android.js)

Registering the job does not mean that the job is scheduled, it just informs React Native that this job function should be tied to this jobKey. The job is then scheduled using the schedule function. By default, the job will not fire while the app is in the foreground. This is since the job is run on the only JavaScript thread and if running the job when app is in the foreground it would freeze the app. By setting allowExecutionInForeground to true you allow this behavior. It is recommended that you do't use this, but for quick jobs should be fine.

For a full example check out example/index.android.js

API

Table of Contents

register

index.js:39-55

Registers the job and the functions they should run.

This has to run on each initialization of React Native and it has to run in the global scope and not inside any component life cycle methods. See example project. Only registering the job will not schedule the job. It has to be scheduled by schedule to start running.

Parameters

Examples

import BackgroundJob from 'react-native-background-job';

const backgroundJob = {
 jobKey: "myJob",
 job: () => console.log("Running in background")
};

BackgroundJob.register(backgroundJob);

schedule

index.js:95-142

Schedules a new job.

This only has to be run once while register has to be run on each initialization of React Native.

Parameters

Examples

import BackgroundJob from 'react-native-background-job';

const backgroundJob = {
 jobKey: "myJob",
 job: () => console.log("Running in background")
};

BackgroundJob.register(backgroundJob);

var backgroundSchedule = {
 jobKey: "myJob",
}

BackgroundJob.schedule(backgroundSchedule)
  .then(() => console.log("Success"))
  .catch(err => console.err(err));

cancel

index.js:156-166

Cancel a specific job

Parameters

Examples

import BackgroundJob from 'react-native-background-job';

BackgroundJob.cancel({jobKey: 'myJob'})
  .then(() => console.log("Success"))
  .catch(err => console.err(err));

cancelAll

index.js:177-187

Cancels all the scheduled jobs

Examples

import BackgroundJob from 'react-native-background-job';

BackgroundJob.cancelAll()
  .then(() => console.log("Success"))
  .catch(err => console.err(err));

setGlobalWarnings

index.js:199-201

Sets the global warning level

Parameters

Examples

import BackgroundJob from 'react-native-background-job';

BackgroundJob.setGlobalWarnings(false);

isAppIgnoringBatteryOptimization

index.js:213-229

Checks Whether app is optimising battery using Doze,returns Boolean.

Parameters

Examples

import BackgroundJob from 'react-native-background-job';

BackgroundJob.isAppIgnoringBatteryOptimization((err, isIgnoring) => console.log(`Callback: isIgnoring = ${isIgnoring}`))
  .then(isIgnoring => console.log(`Promise: isIgnoring = ${isIgnoring}`))
  .catch(err => console.err(err));

Troubleshooting

No task registered for key myJob

Make sure you call the register function at the global scope (i.e. not in any component life cycle methods (render, iDidMount etc)). Since the components are not rendered in Headless mode if you run the register function there it will not run in the background and hence the library will not find which function to run.

See example project

AppState.currentState is "active" when I'm running my Headless task in the background

This is a React Native issue, you can get around it by calling NativeModules.AppState.getCurrentAppState directly instead.

My job always runs in the background even if I specified requiresCharging, requiresDeviceIdle or a specific networkType

This is an Android issue, it seems that you can not have these restrictions at the same time as you have a periodic interval for pre Android N devices.

Pull Request Details

Included function for checking if the app is ignoring battery optimizations. #62

In Android SDK versions greater than 23, Doze is being used by apps by default, in order to optimize battery by temporarily turning off background tasks when the phone is left undisturbed for some hours.

But, some apps may require background tasks to keep running, ignoring doze and not optimizing battery (this means battery needs to be traded off for performance as per required). Apps that require continuous syncing of data to the server at short intervals of time are examples of such apps.

It would be good if the developer can check whether the app is optimizing battery. If it is, the user can be notified that the app would not perform as per expected and it will work properly only if the user manually removes it from the battery optimizing apps list which can be found in Settings-> Battery -> Options (button on top right) -> Battery Optimization and then selecting "All Apps" to change the battery optimization settings for the particular app.

The Changes that have been made are specifically for that purpose, a function (isAppIgnoringBatteryOptimization) has been included. It checks if the app is ignoring battery optimization and returns false if it is optimizing battery (in which case the user has to manually remove it from battery settings) and true otherwise.

Logic has also been added for scheduling the task by ignoring battery optimizations, if the app has been manually removed from the battery optimization list in settings (by the User).

Sponsored by

pilloxa