@capacitor/background-runner
Background Runner provides an event-based standalone JavaScript environment for executing your Javascript code outside of the web view.
Install
npm install @capacitor/background-runner
npx cap sync
Background Runner has support for various device APIs that require permission from the user prior to use.
iOS
On iOS you must enable the Background Modes capability.

Once added, you must enable the Background fetch and Background processing modes at a minimum to enable the ability to register and schedule your background tasks.
If you will be making use of Geolocation or Push Notifications, enable Location updates or Remote notifications respectively.

You will also need to add the following entry into your Info.plist file:
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.example.background.task</string>
</array>
Read about Configuring Info.plist in the iOS Guide for more information on setting iOS permissions in Xcode.
Make sure you use the same id that you use for BGTaskSchedulerPermittedIdentifiers (for example "com.example.background.task") in the label field in the plugin configuration.
After enabling the Background Modes capability, add the following to your app's AppDelegate.swift:
At the top of the file, under import Capacitor add:
import CapacitorBackgroundRunner
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// ....
BackgroundRunnerPlugin.registerBackgroundTask()
BackgroundRunnerPlugin.handleApplicationDidFinishLaunching(launchOptions: launchOptions)
// ....
return true
}
To allow the Background Runner to handle remote notifications, add the following:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// ....
BackgroundRunnerPlugin.dispatchEvent(event: "remoteNotification", eventArgs: userInfo) { result in
switch result {
case .success:
completionHandler(.newData)
case .failure:
completionHandler(.failed)
}
}
}
Geolocation
Apple requires privacy descriptions to be specified in Info.plist for location information:
NSLocationAlwaysUsageDescription(Privacy - Location Always Usage Description)NSLocationWhenInUseUsageDescription(Privacy - Location When In Use Usage Description)
Android
Insert the following line to android/app/build.gradle:
...
repositories {
flatDir{
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
+ dirs '../../node_modules/@capacitor/background-runner/android/src/main/libs', 'libs'
}
}
...
If you are upgrading from 1.0.5 with an existing Android project, be sure to delete the android-js-engine-release.aar from android/src/main/libs.
Geolocation
This API requires the following permissions be added to your AndroidManifest.xml:
<!-- Geolocation API -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
The first two permissions ask for location data, both fine and coarse, and the last line is optional but necessary if your app requires GPS to function. You may leave it out, though keep in mind that this may mean your app is installed on devices lacking GPS hardware.
Local Notifications
Android 13 requires a permission check in order to send notifications. You are required to call checkPermissions() and requestPermissions() accordingly.
On Android 12 and older it won't show a prompt and will just return as granted.
Starting on Android 12, scheduled notifications won't be exact unless this permission is added to your AndroidManifest.xml:
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
Note that even if the permission is present, users can still disable exact notifications from the app settings.
Read about Setting Permissions in the Android Guide for more information on setting Android permissions.
About Background Runner
During the course of building complex applications, its sometimes necessary to perform work while the application is not in the foreground. The challenge with standard Capacitor applications is that the webview is not available when these background events occur, requiring you to write native code to handle these events. This is where the Background Runner plugin comes in.
Background Runner makes it easy to write JavaScript code to handle native background events. All you need to do is create your runner JavaScript file and define your configuration, then the Background Runner plugin will automatically configure and schedule a native background task that will be executed according to your config and the rules of the platform. No modification to your UI code is necessary.
Using Background Runner
Background Runner contains a headless JavaScript environment that calls event handlers in javascript file that you designate in your capacitor.config.ts file. If the runner finds a event handler corresponding to incoming event in your runner file, it will execute the event handler, then shutdown once resolve() or reject() are called (or if the OS force kills your process).
Example Runner JS File
addEventListener('myCustomEvent', (resolve, reject, args) => {
console.log('do something to update the system here');
resolve();
});
addEventListener('myCustomEventWithReturnData', (resolve, reject, args) => {
try {
console.log('accepted this data: ' + JSON.stringify(args.user));
const updatedUser = args.user;
updatedUser.firstName = updatedUser.firstName + ' HELLO';
updatedUser.lastName = updatedUser.lastName + ' WORLD';
resolve(updatedUser);
} catch (err) {
reject(err);
}
});
addEventListener('remoteNotification', (resolve, reject, args) => {
try {
console.log('received silent push notification');
CapacitorNotifications.schedule([
{
id: 100,
title: 'Enterprise Background Runner',
body: 'Received silent push notification',
},
]);
resolve();
} catch (err) {
reject();
}
});
Calling resolve() \ reject() is required within every event handler called by the runner. Failure to do this could result in your runner being killed by the OS if your event is called while the app is in the background. If the app is in the foreground, async calls to dispatchEvent may not resolve.
For more real world examples of using Background Runner, check out the Background Runner Test App.
Configuring Background Runner
On load, Background Runner will automatically register a background task that will be scheduled and run once your app is backgrounded.
| Prop | Type | Description | Since |
|---|---|---|---|
label | string | The name of the runner, used in logs. | 1.0.0 |
src | string | The path to the runner JavaScript file, relative to the app bundle. | 1.0.0 |
event | string | The name of the event that will be called when the OS executes the background task. | 1.0.0 |
repeat | boolean | If background task should repeat based on the interval set in interval. | 1.0.0 |
interval | number | The number of minutes after the the app is put into the background in which the background task should begin. If repeat is true, this also specifies the number of minutes between each execution. | 1.0.0 |
autoStart | boolean | Automatically register and schedule background task on app load. | 1.0.0 |
Examples
In capacitor.config.json:
{
"plugins": {
"BackgroundRunner": {
"label": "com.example.background.task",
"src": "runners/background.js",
"event": "myCustomEvent",
"repeat": true,
"interval": 15,
"autoStart": true
}
}
}
In capacitor.config.ts:
/// <reference types="@capacitor/background-runner" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
BackgroundRunner: {
label: "com.example.background.task",
src: "runners/background.js",
event: "myCustomEvent",
repeat: true,
interval: 15,
autoStart: true,
},
},
};
export default config;