@kesha-antonov/react-native-background-downloader 2.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ This software is licensed under the Apache 2 license, quoted below.
2
+
3
+ Copyright 2018 Eko <https://helloeko.com>
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ use this file except in compliance with the License. You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ License for the specific language governing permissions and limitations under the License.
package/README.md ADDED
@@ -0,0 +1,349 @@
1
+ ![react-native-background-downloader banner](https://d1w2zhnqcy4l8f.cloudfront.net/content/falcon/production/projects/V5EEOX_fast/RNBD-190702083358.png)
2
+
3
+ [![npm version](https://badge.fury.io/js/react-native-background-downloader.svg)](https://badge.fury.io/js/react-native-background-downloader)
4
+
5
+ # react-native-background-downloader
6
+ ## *Note - This is fork of https://github.com/EkoLabs/react-native-background-downloader maintained by https://github.com/kesha-antonov * ##
7
+
8
+ 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.
9
+
10
+ ### Why?
11
+ On iOS, if you want to download big files no matter the state of your app, wether it's in the background or terminated by the OS, you have to use a system API called `NSURLSession`.
12
+
13
+ This API handles your downloads separately from your app and only keeps it informed using delegates (Read: [Downloading Files in the Background](https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_in_the_background)).
14
+
15
+ On Android we are simulating this process with a wonderful library called [Fetch2](https://github.com/tonyofrancis/Fetch)
16
+
17
+ The real challenge of using this method is making sure the app's UI is always up-to-date with the downloads that are happening in another process because your app might startup from scratch while the downloads are still running.
18
+
19
+ `react-native-background-downloader` gives you an easy API to both downloading large files and re-attaching to those downloads once your app launches again.
20
+
21
+ > **Please Note** - This library was created to better facilitate background downloading on iOS. If you're not aiming to to use the download-in-background functionality, there are better solutions like [RNFS.downloadFile()](https://github.com/itinance/react-native-fs#downloadfileoptions-downloadfileoptions--jobid-number-promise-promisedownloadresult-) which will results in a more stable download experience for your app.
22
+
23
+ ## ToC
24
+
25
+ - [Usage](#usage)
26
+ - [API](#api)
27
+ - [Constants](#constants)
28
+
29
+ ## Getting started
30
+
31
+ ```Terminal
32
+ $ yarn add github:kesha-antonov/react-native-background-downloader
33
+ ```
34
+ (or for Yarn v2+):
35
+ ```Terminal
36
+ $ yarn add react-native-background-downloader@github:kesha-antonov/react-native-background-downloader
37
+ ```
38
+ or
39
+ ```Terminal
40
+ npm i github:kesha-antonov/react-native-background-downloader
41
+ ```
42
+
43
+
44
+ For **`RN <= 0.57.0`** use `$ yarn add react-native-background-downloader@1.1.0`
45
+
46
+ Then `pod install`:
47
+ ```Terminal
48
+ cd ios && pod install
49
+ ```
50
+
51
+ ### Mostly automatic installation
52
+ Any React Native version **`>= 0.60`** supports autolinking so nothing should be done.
53
+
54
+ For anything **`< 0.60`** run the following link command
55
+
56
+ `$ react-native link react-native-background-downloader`
57
+
58
+ ### Manual installation
59
+
60
+
61
+ #### iOS
62
+
63
+ 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
64
+ 2. Go to `node_modules` ➜ `react-native-background-downloader` and add `RNBackgroundDownloader.xcodeproj`
65
+ 3. In XCode, in the project navigator, select your project. Add `libRNBackgroundDownloader.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
66
+ 4. Run your project (`Cmd+R`)
67
+
68
+ #### Android
69
+
70
+ 1. Open up `android/app/src/main/java/[...]/MainActivity.java`
71
+ - Add `import com.eko.RNBackgroundDownloaderPackage;` to the imports at the top of the file
72
+ - Add `new RNBackgroundDownloaderPackage()` to the list returned by the `getPackages()` method
73
+ 2. Append the following lines to `android/settings.gradle`:
74
+ ```
75
+ include ':react-native-background-downloader'
76
+ project(':react-native-background-downloader').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-downloader/android')
77
+ ```
78
+ 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
79
+ ```
80
+ compile project(':react-native-background-downloader')
81
+ ```
82
+
83
+ ### iOS - Extra Mandatory Step
84
+ In your `AppDelegate.m` add the following code:
85
+ ```objc
86
+ ...
87
+ #import <RNBackgroundDownloader.h>
88
+
89
+ ...
90
+
91
+ - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler
92
+ {
93
+ [RNBackgroundDownloader setCompletionHandlerWithIdentifier:identifier completionHandler:completionHandler];
94
+ }
95
+
96
+ ...
97
+ ```
98
+ Failing to add this code will result in canceled background downloads. If Xcode complains that RNBackgroundDownloader.h is missing, you might have forgotten to `pod install` first.
99
+
100
+ ## Usage
101
+
102
+ ### Downloading a file
103
+
104
+ ```javascript
105
+ import { Platform } from 'react-native'
106
+ import { download, completeHandler } from 'react-native-background-downloader'
107
+
108
+ const jobId = 'file123'
109
+
110
+ let task = download({
111
+ id: jobId,
112
+ url: 'https://link-to-very.large/file.zip',
113
+ destination: `${RNBackgroundDownloader.directories.documents}/file.zip`,
114
+ metadata: {}
115
+ }).begin(({ expectedBytes, headers }) => {
116
+ console.log(`Going to download ${expectedBytes} bytes!`)
117
+ }).progress(percent => {
118
+ console.log(`Downloaded: ${percent * 100}%`)
119
+ }).done(() => {
120
+ console.log('Download is done!')
121
+
122
+ // PROCESS YOUR STUFF
123
+
124
+ // FINISH DOWNLOAD JOB ON IOS
125
+ if (Platform.OS === 'ios')
126
+ completeHandler(jobId)
127
+ }).error(error => {
128
+ console.log('Download canceled due to error: ', error);
129
+ })
130
+
131
+ // Pause the task
132
+ task.pause()
133
+
134
+ // Resume after pause
135
+ task.resume()
136
+
137
+ // Cancel the task
138
+ task.stop()
139
+ ```
140
+
141
+ ### Re-Attaching to background downloads
142
+
143
+ This is the main selling point of this library (but it's free!).
144
+
145
+ What happens to your downloads after the OS stopped your app? Well, they are still running, we just need to re-attach to them.
146
+
147
+ Add this code to app's init stage, and you'll never lose a download again!
148
+
149
+ ```javascript
150
+ import RNBackgroundDownloader from 'react-native-background-downloader'
151
+
152
+ let lostTasks = await RNBackgroundDownloader.checkForExistingDownloads()
153
+ for (let task of lostTasks) {
154
+ console.log(`Task ${task.id} was found!`)
155
+ task.progress(percent => {
156
+ console.log(`Downloaded: ${percent * 100}%`)
157
+ }).done(() => {
158
+ console.log('Download is done!')
159
+ }).error(error => {
160
+ console.log('Download canceled due to error: ', error)
161
+ })
162
+ }
163
+ ```
164
+
165
+ `task.id` is very important for re-attaching the download task with any UI component representing that task. This is why you need to make sure to give sensible IDs that you know what to do with, try to avoid using random IDs.
166
+
167
+ ### Using custom headers
168
+ If you need to send custom headers with your download request, you can do in it 2 ways:
169
+
170
+ 1) Globally using `RNBackgroundDownloader.setHeaders()`:
171
+ ```javascript
172
+ RNBackgroundDownloader.setHeaders({
173
+ Authorization: 'Bearer 2we$@$@Ddd223'
174
+ })
175
+ ```
176
+ This way, all downloads with have the given headers.
177
+
178
+ 2) Per download by passing a headers object in the options of `RNBackgroundDownloader.download()`:
179
+ ```javascript
180
+ let task = RNBackgroundDownloader.download({
181
+ id: 'file123',
182
+ url: 'https://link-to-very.large/file.zip'
183
+ destination: `${RNBackgroundDownloader.directories.documents}/file.zip`,
184
+ headers: {
185
+ Authorization: 'Bearer 2we$@$@Ddd223'
186
+ }
187
+ }).begin(({ expectedBytes, headers }) => {
188
+ console.log(`Going to download ${expectedBytes} bytes!`)
189
+ }).progress(percent => {
190
+ console.log(`Downloaded: ${percent * 100}%`)
191
+ }).done(() => {
192
+ console.log('Download is done!')
193
+ }).error(error => {
194
+ console.log('Download canceled due to error: ', error)
195
+ })
196
+ ```
197
+ Headers given in the `download` function are **merged** with the ones given in `setHeaders`.
198
+
199
+ ## API
200
+
201
+ ### RNBackgroundDownloader
202
+
203
+ ### `download(options)`
204
+
205
+ Download a file to destination
206
+
207
+ **options**
208
+
209
+ An object containing options properties
210
+
211
+ | Property | Type | Required | Platforms | Info |
212
+ | ------------- | ------------------------------------------------ | :------: | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
213
+ | `id` | String | ✅ | All | A Unique ID to provide for this download. This ID will help to identify the download task when the app re-launches |
214
+ | `url` | String | ✅ | All | URL to file you want to download |
215
+ | `destination` | String | ✅ | All | Where to copy the file to once the download is done |
216
+ | `metadata` | Object | | All | Data to be preserved on reboot. |
217
+ | `headers` | Object | | All | Costume headers to add to the download request. These are merged with the headers given in the `setHeaders` function
218
+ | `priority` | [Priority (enum)](#priority-enum---android-only) | | Android | The priority of the download. On Android, downloading is limited to 4 simultaneous instances where further downloads are queued. Priority helps in deciding which download to pick next from the queue. **Default:** Priority.MEDIUM |
219
+ | `network` | [Network (enum)](#network-enum---android-only) | | Android | Give your the ability to limit the download to WIFI only. **Default:** Network.ALL |
220
+
221
+ **returns**
222
+
223
+ `DownloadTask` - The download task to control and monitor this download
224
+
225
+ ### `checkForExistingDownloads()`
226
+
227
+ Checks for downloads that ran in background while you app was terminated. Recommended to run at the init stage of the app.
228
+
229
+ **returns**
230
+
231
+ `DownloadTask[]` - Array of tasks that were running in the background so you can re-attach callbacks to them
232
+
233
+ ### `setHeaders(headers)`
234
+
235
+ Sets headers to use in all future downloads.
236
+
237
+ **headers** - Object
238
+
239
+ ### DownloadTask
240
+
241
+ A class representing a download task created by `RNBackgroundDownloader.download`
242
+
243
+ ### `Members`
244
+ | Name | Type | Info |
245
+ | -------------- | ------ | ---------------------------------------------------------------------------------------------------- |
246
+ | `id` | String | The id you gave the task when calling `RNBackgroundDownloader.download` |
247
+ | `metadata` | Object | The metadata you gave the task when calling `RNBackgroundDownloader.download` |
248
+ | `percent` | Number | The current percent of completion of the task between 0 and 1 |
249
+ | `bytesWritten` | Number | The number of bytes currently written by the task |
250
+ | `totalBytes` | Number | The number bytes expected to be written by this task or more plainly, the file size being downloaded |
251
+
252
+ ### `completeHandler(jobId)`
253
+
254
+ Finishes download job on iOS and informs OS that app can be closed in background if needed.
255
+ After finishing download in background you have some time to process your JS logic and finish the job.
256
+
257
+ ### `ensureDownloadsAreRunning`
258
+
259
+ 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).
260
+
261
+ Here's example of how you can use it:
262
+
263
+ 1. When your app just loaded
264
+
265
+ Either stop all tasks:
266
+
267
+ ```javascript
268
+ const tasks = await checkForExistingDownloads()
269
+ for (const task of tasks)
270
+ task.stop()
271
+ ```
272
+
273
+ Or re-attach them:
274
+
275
+ ```javascript
276
+ const tasks = await checkForExistingDownloads()
277
+ for (const task of tasks) {
278
+ task.pause()
279
+ //
280
+ // YOUR LOGIC OF RE-ATTACHING DOWLOADS TO YOUR STUFF
281
+ // ...
282
+ //
283
+ }
284
+ ```
285
+
286
+ 2. Prepare your app to handle downloads... (load your state etc.)
287
+
288
+ 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!)
289
+
290
+ ```javascript
291
+
292
+ function handleAppStateChange (appState) {
293
+ if (appState !== 'active')
294
+ return
295
+
296
+ ensureDownloadsAreRunning()
297
+ }
298
+
299
+ const appStateChangeListener = AppState.addEventListener('change', handleAppStateChange)
300
+ ```
301
+
302
+ ### `Callback Methods`
303
+ Use these methods to stay updated on what's happening with the task.
304
+
305
+ All callback methods return the current instance of the `DownloadTask` for chaining.
306
+
307
+ | Function | Callback Arguments | Info |
308
+ | ---------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
309
+ | `begin` | { expectedBytes, headers } | Called when the first byte is received. 💡: this is good place to check if the device has enough storage space for this download |
310
+ | `progress` | percent, bytesWritten, totalBytes | Called at max every 1.5s so you can update your progress bar accordingly |
311
+ | `done` | | Called when the download is done, the file is at the destination you've set |
312
+ | `error` | error | Called when the download stops due to an error |
313
+
314
+ ### `pause()`
315
+ Pauses the download
316
+
317
+ ### `resume()`
318
+ Resumes a pause download
319
+
320
+ ### `stop()`
321
+ Stops the download for good and removes the file that was written so far
322
+
323
+ ## Constants
324
+
325
+ ### directories
326
+
327
+ ### `documents`
328
+
329
+ An absolute path to the app's documents directory. It is recommended that you use this path as the target of downloaded files.
330
+
331
+ ### Priority (enum) - Android only
332
+
333
+ `Priority.HIGH`
334
+
335
+ `Priority.MEDIUM` - Default ✅
336
+
337
+ `Priority.LOW`
338
+
339
+ ### Network (enum) - Android only
340
+
341
+ `Network.WIFI_ONLY`
342
+
343
+ `Network.ALL` - Default ✅
344
+
345
+ ## Author
346
+ Developed by [Elad Gil](https://github.com/ptelad) of [Eko](http://www.helloeko.com)
347
+
348
+ ## License
349
+ Apache 2
@@ -0,0 +1,31 @@
1
+ apply plugin: 'com.android.library'
2
+
3
+ def safeExtGet(prop, fallback) {
4
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
5
+ }
6
+
7
+ android {
8
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
9
+
10
+ defaultConfig {
11
+ minSdkVersion safeExtGet('minSdkVersion', 21)
12
+ targetSdkVersion safeExtGet('targetSdkVersion', 33)
13
+ versionCode 1
14
+ versionName "1.0"
15
+ ndk {
16
+ abiFilters "armeabi-v7a", "x86"
17
+ }
18
+ }
19
+ }
20
+
21
+ dependencies {
22
+ //noinspection GradleDynamicVersion
23
+ implementation 'com.facebook.react:react-native:+'
24
+ if (project.properties['android.useAndroidX'] == 'true' || project.properties['android.useAndroidX'] == true) {
25
+ api "com.github.tonyofrancis.Fetch:xfetch2:3.1.6"
26
+ implementation "com.github.tonyofrancis.Fetch:xfetch2okhttp:3.1.6"
27
+ } else {
28
+ api "com.tonyodev.fetch2:fetch2:3.0.12"
29
+ implementation "com.tonyodev.fetch2okhttp:fetch2okhttp:3.0.12"
30
+ }
31
+ }
@@ -0,0 +1,6 @@
1
+
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.eko">
4
+
5
+ </manifest>
6
+
@@ -0,0 +1,17 @@
1
+ package com.eko;
2
+
3
+ import java.io.Serializable;
4
+
5
+ public class RNBGDTaskConfig implements Serializable {
6
+ public String id;
7
+ public String destination;
8
+ public String metadata;
9
+ public boolean reportedBegin;
10
+
11
+ public RNBGDTaskConfig(String id, String destination, String metadata) {
12
+ this.id = id;
13
+ this.destination = destination;
14
+ this.metadata = metadata;
15
+ this.reportedBegin = false;
16
+ }
17
+ }