From 9bce65b91046b0cb281c87e1232024baa53e054c Mon Sep 17 00:00:00 2001 From: Kesha Antonov Date: Sun, 29 Jan 2023 22:32:49 +0300 Subject: [PATCH] add method ensureDownloadsAreRunning + explanation in readme. v2.6.0 --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ index.js | 38 ++++++++++++++++++++++++++------------ package.json | 2 +- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d6c9936..2280690 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,51 @@ A class representing a download task created by `RNBackgroundDownloader.download Finishes download job on iOS and informs OS that app can be closed in background if needed. After finishing download in background you have some time to process your JS logic and finish the job. +### `ensureDownloadsAreRunning` + +Pauses and resumes all downloads - this is fix for stuck downloads. Use it when your app loaded and is ready for handling downloads (all your logic loaded and ready to handle download callbacks). + +Here's example of how you can use it: + +1. When your app just loaded + +Either stop all tasks: + +```javascript +const tasks = await checkForExistingDownloads() +for (const task of tasks) + task.stop() +``` + +Or re-attach them: + +```javascript +const tasks = await checkForExistingDownloads() +for (const task of tasks) { + task.pause() + // + // YOUR LOGIC OF RE-ATTACHING DOWLOADS TO YOUR STUFF + // ... + // +} +``` + +2. Prepare your app to handle downloads... (load your state etc.) + +3. Add listener to handle when your app goes foreground (be sure to do it only after you stopped all tasks or re-attached them!) + +```javascript + +function handleAppStateChange (appState) { + if (appState !== 'active') + return + + ensureDownloadsAreRunning() +} + +const appStateChangeListener = AppState.addEventListener('change', handleAppStateChange) +``` + ### `Callback Methods` Use these methods to stay updated on what's happening with the task. diff --git a/index.js b/index.js index 4fca2ee..635a270 100644 --- a/index.js +++ b/index.js @@ -32,14 +32,14 @@ RNBackgroundDownloaderEmitter.addListener('downloadBegin', ({ id, expectedBytes, task?.onBegin({ expectedBytes, headers }) }) -export function setHeaders (h = {}) { +export function setHeaders(h = {}) { if (typeof h !== 'object') throw new Error('[RNBackgroundDownloader] headers must be an object') headers = h } -export function checkForExistingDownloads () { +export function checkForExistingDownloads() { return RNBackgroundDownloader.checkForExistingDownloads() .then(foundTasks => { return foundTasks.map(taskInfo => { @@ -55,7 +55,7 @@ export function checkForExistingDownloads () { if (taskInfo.bytesWritten === taskInfo.totalBytes) task.state = 'DONE' else - // IOS completed the download but it was not done. + // IOS completed the download but it was not done. return null } tasksMap.set(taskInfo.id, task) @@ -64,25 +64,38 @@ export function checkForExistingDownloads () { }) } -export function completeHandler (jobId) { +export function ensureDownloadsAreRunning() { + return checkForExistingDownloads() + .then(tasks => { + for (const task of tasks) + if (task.state === 'DOWNLOADING') { + task.pause() + task.resume() + } + }) +} + +export function completeHandler(jobId) { return RNBackgroundDownloader.completeHandler(jobId) } -export function download (options) { +export function download(options) { if (!options.id || !options.url || !options.destination) throw new Error('[RNBackgroundDownloader] id, url and destination are required') - options.headers = options.headers && typeof options.headers === 'object' - ? { ...headers, ...options.headers } - : headers + options.headers = { ...headers, ...(options.headers || {}) } - options.metadata = options.metadata && typeof options.metadata === 'object' - ? JSON.stringify(options.metadata) - : JSON.stringify({}) + options.metadata = JSON.stringify( + options.metadata && typeof options.metadata === 'object' + ? options.metadata + : {} + ) - RNBackgroundDownloader.download(options) const task = new DownloadTask({ id: options.id, metadata: options.metadata }) tasksMap.set(options.id, task) + + RNBackgroundDownloader.download(options) + return task } @@ -104,6 +117,7 @@ export const Priority = { export default { download, checkForExistingDownloads, + ensureDownloadsAreRunning, completeHandler, setHeaders, directories, diff --git a/package.json b/package.json index aa745d4..b887f3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-background-downloader", - "version": "2.5.1", + "version": "2.6.0", "description": "A library for React-Native to help you download large files on iOS and Android both in the foreground and most importantly in the background.", "keywords": [ "react-native",