@huddle01/react-native-background-actions
Version:
React Native background service library for running background tasks forever in Android & iOS
174 lines (161 loc) • 5.49 kB
JavaScript
import { Platform, AppRegistry } from 'react-native';
import { RNBackgroundActions, nativeEventEmitter } from './RNBackgroundActionsModule';
import EventEmitter from 'eventemitter3';
export const Priority = Object.freeze({
MIN: -2,
LOW: -1,
DEFAULT: 0,
HIGHT: 1,
MAX: 2,
});
export const Importance = Object.freeze({
DEFAULT: 3,
MAX: 5,
HIGHT: 4,
LOW: 2,
MIN: 1,
NONE: 0,
});
/**
* @typedef {{taskName: string,
* taskTitle: string,
* taskDesc: string,
* taskIcon: {name: string, type: string, package?: string},
* color?: string
* linkingURI?: string,
* priority?: number,
* importance?: number,
* ongoing?: boolean,
* autoCancel?: boolean,
* stopOnTerminate?: boolean,
* serviceTypes?: string,
* progressBar?: {max: number, value: number, indeterminate?: boolean},
* }} BackgroundTaskOptions
* @extends EventEmitter<'expiration',any>
*/
class BackgroundServer extends EventEmitter {
constructor() {
super();
/** @private */
this._runnedTasks = 0;
/** @private @type {(arg0?: any) => void} */
this._stopTask = () => {};
/** @private */
this._isRunning = false;
/** @private @type {BackgroundTaskOptions} */
this._currentOptions;
this._addListeners();
}
/**
* @private
*/
_addListeners() {
nativeEventEmitter.addListener('expiration', () => this.emit('expiration'));
}
/**
* **ANDROID ONLY**
*
* Updates the task notification.
*
* *On iOS this method will return immediately*
*
* @param {{taskTitle?: string,
* taskDesc?: string,
* taskIcon?: {name: string, type: string, package?: string},
* color?: string,
* linkingURI?: string,
* priority?: number,
* importance?: number,
* ongoing?: boolean,
* autoCancel?: boolean,
* stopOnTerminate?: boolean,
* serviceTypes?: string,
* progressBar?: {max: number, value: number, indeterminate?: boolean}}} taskData
*/
async updateNotification(taskData) {
if (Platform.OS !== 'android') return;
if (!this.isRunning())
throw new Error('A BackgroundAction must be running before updating the notification');
this._currentOptions = this._normalizeOptions({ ...this._currentOptions, ...taskData });
await RNBackgroundActions.updateNotification(this._currentOptions);
}
/**
* Returns if the current background task is running.
*
* It returns `true` if `start()` has been called and the task has not finished.
*
* It returns `false` if `stop()` has been called, **even if the task has not finished**.
*/
isRunning() {
return this._isRunning;
}
/**
* @template T
*
* @param {(taskData?: T) => Promise<void>} task
* @param {BackgroundTaskOptions & {parameters?: T}} options
* @returns {Promise<void>}
*/
async start(task, options) {
this._runnedTasks++;
this._currentOptions = this._normalizeOptions(options);
const finalTask = this._generateTask(task, options.parameters);
if (Platform.OS === 'android') {
AppRegistry.registerHeadlessTask(this._currentOptions.taskName, () => finalTask);
await RNBackgroundActions.start(this._currentOptions);
this._isRunning = true;
} else {
await RNBackgroundActions.start(this._currentOptions);
this._isRunning = true;
finalTask();
}
}
/**
* @private
* @template T
* @param {(taskData?: T) => Promise<void>} task
* @param {T} [parameters]
*/
_generateTask(task, parameters) {
const self = this;
return async () => {
await new Promise((resolve) => {
self._stopTask = resolve;
task(parameters).then(() => self.stop());
});
};
}
/**
* @private
* @param {BackgroundTaskOptions} options
*/
_normalizeOptions(options) {
return {
taskName: options.taskName + this._runnedTasks,
taskTitle: options.taskTitle,
taskDesc: options.taskDesc,
taskIcon: { ...options.taskIcon },
color: options.color || '#ffffff',
linkingURI: options.linkingURI,
progressBar: options.progressBar,
priority: options.priority || Priority.DEFAULT,
importance: options.importance || Importance.DEFAULT,
ongoing: options.ongoing || true,
autoCancel: options.autoCancel || false,
stopOnTerminate: options.stopOnTerminate || false,
serviceTypes: options.serviceTypes,
};
}
/**
* Stops the background task.
*
* @returns {Promise<void>}
*/
async stop() {
this._stopTask();
await RNBackgroundActions.stop();
this._isRunning = false;
}
}
const backgroundServer = new BackgroundServer();
export default backgroundServer;