@kesha-antonov/react-native-background-downloader 3.0.0-beta.1 → 3.0.1
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/README.md +24 -20
- package/android/src/main/java/com/eko/Downloader.java +0 -1
- package/android/src/main/java/com/eko/OnBegin.java +3 -1
- package/android/src/main/java/com/eko/OnProgress.java +2 -12
- package/android/src/main/java/com/eko/RNBackgroundDownloaderModule.java +70 -93
- package/index.ts +5 -4
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -100,14 +100,14 @@ Failing to add this code will result in canceled background downloads. If Xcode
|
|
|
100
100
|
|
|
101
101
|
```javascript
|
|
102
102
|
import { Platform } from 'react-native'
|
|
103
|
-
import { download, completeHandler } from '@kesha-antonov/react-native-background-downloader'
|
|
103
|
+
import { download, completeHandler, directories } from '@kesha-antonov/react-native-background-downloader'
|
|
104
104
|
|
|
105
105
|
const jobId = 'file123'
|
|
106
106
|
|
|
107
107
|
let task = download({
|
|
108
108
|
id: jobId,
|
|
109
109
|
url: 'https://link-to-very.large/file.zip',
|
|
110
|
-
destination: `${
|
|
110
|
+
destination: `${directories.documents}/file.zip`,
|
|
111
111
|
metadata: {}
|
|
112
112
|
}).begin(({ expectedBytes, headers }) => {
|
|
113
113
|
console.log(`Going to download ${expectedBytes} bytes!`)
|
|
@@ -120,8 +120,8 @@ let task = download({
|
|
|
120
120
|
|
|
121
121
|
// FINISH DOWNLOAD JOB
|
|
122
122
|
completeHandler(jobId)
|
|
123
|
-
}).error(error => {
|
|
124
|
-
console.log('Download canceled due to error: ', error);
|
|
123
|
+
}).error(({ error, errorCode }) => {
|
|
124
|
+
console.log('Download canceled due to error: ', { error, errorCode });
|
|
125
125
|
})
|
|
126
126
|
|
|
127
127
|
// Pause the task
|
|
@@ -152,8 +152,8 @@ for (let task of lostTasks) {
|
|
|
152
152
|
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
|
|
153
153
|
}).done(({ bytesDownloaded, bytesTotal }) => {
|
|
154
154
|
console.log('Download is done!', { bytesDownloaded, bytesTotal })
|
|
155
|
-
}).error(error => {
|
|
156
|
-
console.log('Download canceled due to error: ', error)
|
|
155
|
+
}).error(({ error, errorCode }) => {
|
|
156
|
+
console.log('Download canceled due to error: ', { error, errorCode })
|
|
157
157
|
})
|
|
158
158
|
}
|
|
159
159
|
```
|
|
@@ -163,10 +163,12 @@ for (let task of lostTasks) {
|
|
|
163
163
|
### Using custom headers
|
|
164
164
|
If you need to send custom headers with your download request, you can do in it 2 ways:
|
|
165
165
|
|
|
166
|
-
1) Globally using `RNBackgroundDownloader.
|
|
166
|
+
1) Globally using `RNBackgroundDownloader.setConfig()`:
|
|
167
167
|
```javascript
|
|
168
|
-
RNBackgroundDownloader.
|
|
169
|
-
|
|
168
|
+
RNBackgroundDownloader.setConfig({
|
|
169
|
+
headers: {
|
|
170
|
+
Authorization: 'Bearer 2we$@$@Ddd223',
|
|
171
|
+
}
|
|
170
172
|
})
|
|
171
173
|
```
|
|
172
174
|
This way, all downloads with have the given headers.
|
|
@@ -186,11 +188,11 @@ let task = RNBackgroundDownloader.download({
|
|
|
186
188
|
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
|
|
187
189
|
}).done(({ bytesDownloaded, bytesTotal }) => {
|
|
188
190
|
console.log('Download is done!', { bytesDownloaded, bytesTotal })
|
|
189
|
-
}).error(error => {
|
|
190
|
-
console.log('Download canceled due to error: ', error)
|
|
191
|
+
}).error(({ error, errorCode }) => {
|
|
192
|
+
console.log('Download canceled due to error: ', { error, errorCode })
|
|
191
193
|
})
|
|
192
194
|
```
|
|
193
|
-
Headers given in the `download` function are **merged** with the ones given in `
|
|
195
|
+
Headers given in the `download` function are **merged** with the ones given in `setConfig({ headers: { ... } })`.
|
|
194
196
|
|
|
195
197
|
## API
|
|
196
198
|
|
|
@@ -210,7 +212,7 @@ An object containing options properties
|
|
|
210
212
|
| `url` | String | ✅ | All | URL to file you want to download |
|
|
211
213
|
| `destination` | String | ✅ | All | Where to copy the file to once the download is done |
|
|
212
214
|
| `metadata` | Object | | All | Data to be preserved on reboot. |
|
|
213
|
-
| `headers` | Object | | All | Costume headers to add to the download request. These are merged with the headers given in the `
|
|
215
|
+
| `headers` | Object | | All | Costume headers to add to the download request. These are merged with the headers given in the `setConfig({ headers: { ... } })` function |
|
|
214
216
|
| `isAllowedOverRoaming` | Boolean | | Android | whether this download may proceed over a roaming connection. By default, roaming is allowed |
|
|
215
217
|
| `isAllowedOverMetered` | Boolean | | Android | Whether this download may proceed over a metered network connection. By default, metered networks are allowed |
|
|
216
218
|
|
|
@@ -228,11 +230,13 @@ Recommended to run at the init stage of the app.
|
|
|
228
230
|
|
|
229
231
|
`DownloadTask[]` - Array of tasks that were running in the background so you can re-attach callbacks to them
|
|
230
232
|
|
|
231
|
-
### `
|
|
233
|
+
### `setConfig({})`
|
|
232
234
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
235
|
+
| Name | Type | Info |
|
|
236
|
+
| -------------- | ------ | ---------------------------------------------------------------------------------------------------- |
|
|
237
|
+
| `headers` | Object | optional headers to use in all future downloads |
|
|
238
|
+
| `progressInterval` | Number | Interval in which download progress sent from downloader. Number should be >= 250. It's in ms |
|
|
239
|
+
| `isLogsEnabled` | Boolean | Enables/disables logs in library |
|
|
236
240
|
|
|
237
241
|
### DownloadTask
|
|
238
242
|
|
|
@@ -251,7 +255,7 @@ A class representing a download task created by `RNBackgroundDownloader.download
|
|
|
251
255
|
Finishes download job and informs OS that app can be closed in background if needed.
|
|
252
256
|
After finishing download in background you have some time to process your JS logic and finish the job.
|
|
253
257
|
|
|
254
|
-
### `ensureDownloadsAreRunning`
|
|
258
|
+
### `ensureDownloadsAreRunning` (iOS only)
|
|
255
259
|
|
|
256
260
|
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).
|
|
257
261
|
|
|
@@ -310,10 +314,10 @@ All callback methods return the current instance of the `DownloadTask` for chain
|
|
|
310
314
|
| `done` | { bytesDownloaded, bytesTotal } | Called when the download is done, the file is at the destination you've set |
|
|
311
315
|
| `error` | { error, errorCode } | Called when the download stops due to an error |
|
|
312
316
|
|
|
313
|
-
### `pause()`
|
|
317
|
+
### `pause()` (iOS only)
|
|
314
318
|
Pauses the download
|
|
315
319
|
|
|
316
|
-
### `resume()`
|
|
320
|
+
### `resume()` (iOS only)
|
|
317
321
|
Resumes a pause download
|
|
318
322
|
|
|
319
323
|
### `stop()`
|
|
@@ -37,9 +37,11 @@ public class OnBegin extends Thread {
|
|
|
37
37
|
con.getInputStream().close();
|
|
38
38
|
|
|
39
39
|
WritableMap params = Arguments.createMap();
|
|
40
|
+
int contentLength = Integer.valueOf(headersMap.getString("Content-Length"));
|
|
41
|
+
|
|
40
42
|
params.putString("id", config.id);
|
|
41
43
|
params.putMap("headers", headersMap);
|
|
42
|
-
params.putInt("expectedBytes",
|
|
44
|
+
params.putInt("expectedBytes", contentLength);
|
|
43
45
|
|
|
44
46
|
ee.emit("downloadBegin", params);
|
|
45
47
|
} catch (Exception e) {
|
|
@@ -38,7 +38,6 @@ public class OnProgress extends Thread {
|
|
|
38
38
|
|
|
39
39
|
private void handleInterrupt() {
|
|
40
40
|
try {
|
|
41
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress handleInterrupt. downloadId " + downloadId);
|
|
42
41
|
if (cursor != null) {
|
|
43
42
|
cursor.close();
|
|
44
43
|
}
|
|
@@ -50,11 +49,8 @@ public class OnProgress extends Thread {
|
|
|
50
49
|
|
|
51
50
|
@Override
|
|
52
51
|
public void run() {
|
|
53
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-1. downloadId " + downloadId);
|
|
54
52
|
while (downloadId > 0) {
|
|
55
53
|
try {
|
|
56
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-2. downloadId " + downloadId + " destination " + config.destination);
|
|
57
|
-
|
|
58
54
|
cursor = downloader.downloadManager.query(query);
|
|
59
55
|
|
|
60
56
|
if (!cursor.moveToFirst()) {
|
|
@@ -67,13 +63,10 @@ public class OnProgress extends Thread {
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
if (status == DownloadManager.STATUS_PAUSED) {
|
|
70
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-2.1. downloadId " + downloadId);
|
|
71
66
|
Thread.sleep(5000);
|
|
72
67
|
} else if (status == DownloadManager.STATUS_PENDING) {
|
|
73
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-2.2. downloadId " + downloadId);
|
|
74
68
|
Thread.sleep(1000);
|
|
75
69
|
} else {
|
|
76
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-2.3. downloadId " + downloadId);
|
|
77
70
|
Thread.sleep(250);
|
|
78
71
|
}
|
|
79
72
|
|
|
@@ -90,9 +83,6 @@ public class OnProgress extends Thread {
|
|
|
90
83
|
lastBytesDownloaded = bytesDownloaded;
|
|
91
84
|
}
|
|
92
85
|
|
|
93
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-3. downloadId " + downloadId + " bytesDownloaded "
|
|
94
|
-
+ bytesDownloaded + " bytesTotal " + bytesTotal);
|
|
95
|
-
|
|
96
86
|
if (lastBytesDownloaded > 0 && bytesTotal > 0) {
|
|
97
87
|
callback.onProgress(config.id, lastBytesDownloaded, bytesTotal);
|
|
98
88
|
}
|
|
@@ -102,11 +92,11 @@ public class OnProgress extends Thread {
|
|
|
102
92
|
|
|
103
93
|
try {
|
|
104
94
|
if (cursor != null) {
|
|
105
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-5. downloadId " + downloadId);
|
|
106
95
|
cursor.close();
|
|
107
|
-
Log.d("RNBackgroundDownloader", "RNBD: OnProgress-6. downloadId " + downloadId);
|
|
108
96
|
}
|
|
109
97
|
} catch (Exception e) {
|
|
98
|
+
e.printStackTrace();
|
|
99
|
+
Log.e("RNBackgroundDownloader", "RNBD: OnProgress e: " + Log.getStackTraceString(e));
|
|
110
100
|
return;
|
|
111
101
|
}
|
|
112
102
|
}
|
|
@@ -25,6 +25,7 @@ import java.io.FileOutputStream;
|
|
|
25
25
|
import java.io.IOException;
|
|
26
26
|
import java.io.ObjectInputStream;
|
|
27
27
|
import java.io.ObjectOutputStream;
|
|
28
|
+
import java.nio.channels.FileChannel;
|
|
28
29
|
import java.util.Date;
|
|
29
30
|
import java.util.HashMap;
|
|
30
31
|
import java.util.List;
|
|
@@ -36,8 +37,6 @@ import javax.annotation.Nullable;
|
|
|
36
37
|
import java.util.Set;
|
|
37
38
|
import java.net.URL;
|
|
38
39
|
import java.net.URLConnection;
|
|
39
|
-
import java.nio.file.Files;
|
|
40
|
-
import java.nio.file.StandardCopyOption;
|
|
41
40
|
|
|
42
41
|
import android.content.BroadcastReceiver;
|
|
43
42
|
import android.content.Context;
|
|
@@ -91,23 +90,31 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
91
90
|
|
|
92
91
|
private static Object sharedLock = new Object();
|
|
93
92
|
|
|
93
|
+
private static void copyFile(File src, File dst) throws IOException {
|
|
94
|
+
FileChannel inChannel = new FileInputStream(src).getChannel();
|
|
95
|
+
FileChannel outChannel = new FileOutputStream(dst).getChannel();
|
|
96
|
+
try {
|
|
97
|
+
inChannel.transferTo(0, inChannel.size(), outChannel);
|
|
98
|
+
} finally {
|
|
99
|
+
if (inChannel != null)
|
|
100
|
+
inChannel.close();
|
|
101
|
+
if (outChannel != null)
|
|
102
|
+
outChannel.close();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
94
106
|
BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
|
95
107
|
@Override
|
|
96
108
|
public void onReceive(Context context, Intent intent) {
|
|
97
|
-
Log.d(getName(), "RNBD: onReceive-1");
|
|
98
109
|
try {
|
|
99
110
|
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
|
|
100
|
-
Log.d(getName(), "RNBD: onReceive-2 " + downloadId);
|
|
101
111
|
|
|
102
112
|
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
103
113
|
|
|
104
114
|
if (config != null) {
|
|
105
|
-
Log.d(getName(), "RNBD: onReceive-3");
|
|
106
115
|
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
107
116
|
int status = downloadStatus.getInt("status");
|
|
108
117
|
|
|
109
|
-
Log.d(getName(), "RNBD: onReceive: status - " + status);
|
|
110
|
-
|
|
111
118
|
stopTrackingProgress(config.id);
|
|
112
119
|
|
|
113
120
|
synchronized (sharedLock) {
|
|
@@ -115,12 +122,23 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
115
122
|
case DownloadManager.STATUS_SUCCESSFUL: {
|
|
116
123
|
// MOVES FILE TO DESTINATION
|
|
117
124
|
String localUri = downloadStatus.getString("localUri");
|
|
118
|
-
Log.d(getName(), "RNBD: onReceive: localUri " + localUri + " destination " + config.destination);
|
|
119
125
|
File file = new File(localUri);
|
|
120
|
-
Log.d(getName(), "RNBD: onReceive: file exists " + file.exists());
|
|
121
126
|
File dest = new File(config.destination);
|
|
122
|
-
|
|
123
|
-
|
|
127
|
+
|
|
128
|
+
// REMOVE DEST FILE IF EXISTS
|
|
129
|
+
if (dest.exists()) {
|
|
130
|
+
dest.delete();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// CREATE DESTINATION DIR IF NOT EXISTS
|
|
134
|
+
File destDir = new File(dest.getParent());
|
|
135
|
+
if (!destDir.exists()) {
|
|
136
|
+
destDir.mkdirs();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// MOVE FILE
|
|
140
|
+
copyFile(file, dest);
|
|
141
|
+
file.delete();
|
|
124
142
|
|
|
125
143
|
WritableMap params = Arguments.createMap();
|
|
126
144
|
params.putString("id", config.id);
|
|
@@ -146,6 +164,7 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
146
164
|
}
|
|
147
165
|
}
|
|
148
166
|
} catch (Exception e) {
|
|
167
|
+
e.printStackTrace();
|
|
149
168
|
Log.e(getName(), "downloadReceiver: onReceive. " + Log.getStackTraceString(e));
|
|
150
169
|
}
|
|
151
170
|
}
|
|
@@ -163,7 +182,7 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
163
182
|
compatRegisterReceiver(reactContext, downloadReceiver, filter, true);
|
|
164
183
|
|
|
165
184
|
// iterate over downloadIdToConfig
|
|
166
|
-
for(Map.Entry<Long, RNBGDTaskConfig> entry : downloadIdToConfig.entrySet()) {
|
|
185
|
+
for (Map.Entry<Long, RNBGDTaskConfig> entry : downloadIdToConfig.entrySet()) {
|
|
167
186
|
Long downloadId = entry.getKey();
|
|
168
187
|
RNBGDTaskConfig config = entry.getValue();
|
|
169
188
|
|
|
@@ -236,8 +255,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
236
255
|
}
|
|
237
256
|
|
|
238
257
|
private void removeFromMaps(long downloadId) {
|
|
239
|
-
Log.d(getName(), "RNBD: removeFromMaps");
|
|
240
|
-
|
|
241
258
|
synchronized (sharedLock) {
|
|
242
259
|
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
243
260
|
if (config != null) {
|
|
@@ -251,8 +268,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
251
268
|
}
|
|
252
269
|
|
|
253
270
|
private void saveDownloadIdToConfigMap() {
|
|
254
|
-
Log.d(getName(), "RNBD: saveDownloadIdToConfigMap");
|
|
255
|
-
|
|
256
271
|
synchronized (sharedLock) {
|
|
257
272
|
File file = new File(this.getReactApplicationContext().getFilesDir(), getName() + "_downloadIdToConfig");
|
|
258
273
|
try {
|
|
@@ -267,8 +282,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
267
282
|
}
|
|
268
283
|
|
|
269
284
|
private void loadDownloadIdToConfigMap() {
|
|
270
|
-
Log.d(getName(), "RNBD: loadDownloadIdToConfigMap");
|
|
271
|
-
|
|
272
285
|
File file = new File(this.getReactApplicationContext().getFilesDir(), getName() + "_downloadIdToConfig");
|
|
273
286
|
if (file.exists()) {
|
|
274
287
|
try {
|
|
@@ -280,9 +293,7 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
280
293
|
}
|
|
281
294
|
}
|
|
282
295
|
|
|
283
|
-
private void saveConfigMap
|
|
284
|
-
Log.d(getName(), "RNBD: saveConfigMap");
|
|
285
|
-
|
|
296
|
+
private void saveConfigMap() {
|
|
286
297
|
synchronized (sharedLock) {
|
|
287
298
|
File file = new File(this.getReactApplicationContext().getFilesDir(), getName() + "_config");
|
|
288
299
|
try {
|
|
@@ -299,20 +310,17 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
299
310
|
}
|
|
300
311
|
}
|
|
301
312
|
|
|
302
|
-
private void loadConfigMap
|
|
303
|
-
Log.d(getName(), "RNBD: loadConfigMap");
|
|
304
|
-
|
|
313
|
+
private void loadConfigMap() {
|
|
305
314
|
File file = new File(this.getReactApplicationContext().getFilesDir(), getName() + "_config");
|
|
306
315
|
if (file.exists()) {
|
|
307
316
|
try {
|
|
308
317
|
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
|
|
309
318
|
Map<String, Object> config = (HashMap<String, Object>) inputStream.readObject();
|
|
310
319
|
// iterate over config
|
|
311
|
-
for(Map.Entry<String, Object> entry : config.entrySet()) {
|
|
320
|
+
for (Map.Entry<String, Object> entry : config.entrySet()) {
|
|
312
321
|
String key = entry.getKey();
|
|
313
322
|
|
|
314
323
|
Object valueObj = entry.getValue();
|
|
315
|
-
Log.d(getName(), "RNBD: loadConfigMap-1 " + " key " + key + " valueObj " + valueObj);
|
|
316
324
|
String value = null;
|
|
317
325
|
if (valueObj instanceof Long) {
|
|
318
326
|
value = Long.toString((Long) valueObj);
|
|
@@ -354,8 +362,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
354
362
|
boolean isAllowedOverRoaming = options.getBoolean("isAllowedOverRoaming");
|
|
355
363
|
boolean isAllowedOverMetered = options.getBoolean("isAllowedOverMetered");
|
|
356
364
|
|
|
357
|
-
Log.d(getName(), "RNBD: download " + id + " " + url + " " + destination + " " + metadata + " " + progressInterval);
|
|
358
|
-
|
|
359
365
|
if (id == null || url == null || destination == null) {
|
|
360
366
|
Log.e(getName(), "id, url and destination must be set");
|
|
361
367
|
return;
|
|
@@ -376,7 +382,8 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
376
382
|
request.setDestinationInExternalFilesDir(this.getReactApplicationContext(), null, fileName);
|
|
377
383
|
|
|
378
384
|
// TOREMOVE
|
|
379
|
-
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS.toString(),
|
|
385
|
+
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS.toString(),
|
|
386
|
+
// fileName);
|
|
380
387
|
// request.setDestinationUri(Uri.parse(destination));
|
|
381
388
|
|
|
382
389
|
if (headers != null) {
|
|
@@ -398,8 +405,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
398
405
|
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
399
406
|
int status = downloadStatus.getInt("status");
|
|
400
407
|
|
|
401
|
-
Log.d(getName(), "RNBD: download-1. status: " + status + " downloadId: " + downloadId);
|
|
402
|
-
|
|
403
408
|
if (config.reportedBegin) {
|
|
404
409
|
return;
|
|
405
410
|
}
|
|
@@ -409,31 +414,24 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
409
414
|
}
|
|
410
415
|
|
|
411
416
|
private void startReportingTasks(Long downloadId, RNBGDTaskConfig config) {
|
|
412
|
-
Log.d(getName(), "RNBD: startReportingTasks-1 downloadId " + downloadId + " config.id " + config.id);
|
|
413
417
|
config.reportedBegin = true;
|
|
414
418
|
downloadIdToConfig.put(downloadId, config);
|
|
415
419
|
saveDownloadIdToConfigMap();
|
|
416
420
|
|
|
417
|
-
Log.d(getName(), "RNBD: startReportingTasks-2 downloadId: " + downloadId);
|
|
418
421
|
// report begin & progress
|
|
419
422
|
//
|
|
420
423
|
// overlaped with thread to not block main thread
|
|
421
424
|
new Thread(new Runnable() {
|
|
422
425
|
public void run() {
|
|
423
426
|
try {
|
|
424
|
-
Log.d(getName(), "RNBD: startReportingTasks-3 downloadId: " + downloadId);
|
|
425
|
-
|
|
426
427
|
while (true) {
|
|
427
428
|
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
428
429
|
int status = downloadStatus.getInt("status");
|
|
429
430
|
|
|
430
|
-
Log.d(getName(), "RNBD: startReportingTasks-3.1 " + status + " downloadId: " + downloadId);
|
|
431
|
-
|
|
432
431
|
if (status == DownloadManager.STATUS_RUNNING) {
|
|
433
432
|
break;
|
|
434
433
|
}
|
|
435
434
|
if (status == DownloadManager.STATUS_FAILED || status == DownloadManager.STATUS_SUCCESSFUL) {
|
|
436
|
-
Log.d(getName(), "RNBD: startReportingTasks-3.2 " + status + " downloadId: " + downloadId);
|
|
437
435
|
Thread.currentThread().interrupt();
|
|
438
436
|
}
|
|
439
437
|
|
|
@@ -446,62 +444,51 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
446
444
|
// wait for onBeginTh to finish
|
|
447
445
|
onBeginTh.join();
|
|
448
446
|
|
|
449
|
-
Log.d(getName(), "RNBD: startReportingTasks-4 downloadId: " + downloadId);
|
|
450
447
|
OnProgress onProgressTh = new OnProgress(
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
progressReports.put(configId, params);
|
|
469
|
-
configIdToPercent.put(configId, percent);
|
|
470
|
-
}
|
|
448
|
+
config,
|
|
449
|
+
downloadId,
|
|
450
|
+
downloader,
|
|
451
|
+
new ProgressCallback() {
|
|
452
|
+
@Override
|
|
453
|
+
public void onProgress(String configId, int bytesDownloaded, int bytesTotal) {
|
|
454
|
+
double prevPercent = configIdToPercent.get(configId);
|
|
455
|
+
double percent = (double) bytesDownloaded / bytesTotal;
|
|
456
|
+
if (percent - prevPercent > 0.01) {
|
|
457
|
+
WritableMap params = Arguments.createMap();
|
|
458
|
+
params.putString("id", configId);
|
|
459
|
+
params.putInt("bytesDownloaded", bytesDownloaded);
|
|
460
|
+
params.putInt("bytesTotal", bytesTotal);
|
|
461
|
+
|
|
462
|
+
progressReports.put(configId, params);
|
|
463
|
+
configIdToPercent.put(configId, percent);
|
|
464
|
+
}
|
|
471
465
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
466
|
+
Date now = new Date();
|
|
467
|
+
if (now.getTime() - lastProgressReportedAt.getTime() > progressInterval &&
|
|
468
|
+
progressReports.size() > 0) {
|
|
469
|
+
WritableArray reportsArray = Arguments.createArray();
|
|
470
|
+
for (Object report : progressReports.values()) {
|
|
471
|
+
reportsArray.pushMap((WritableMap) report);
|
|
472
|
+
}
|
|
473
|
+
ee.emit("downloadProgress", reportsArray);
|
|
474
|
+
lastProgressReportedAt = now;
|
|
475
|
+
progressReports.clear();
|
|
481
476
|
}
|
|
482
|
-
ee.emit("downloadProgress", reportsArray);
|
|
483
|
-
lastProgressReportedAt = now;
|
|
484
|
-
progressReports.clear();
|
|
485
477
|
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
);
|
|
478
|
+
});
|
|
489
479
|
onProgressThreads.put(config.id, onProgressTh);
|
|
490
480
|
onProgressTh.start();
|
|
491
|
-
Log.d(getName(), "RNBD: startReportingTasks-5 downloadId: " + downloadId);
|
|
492
481
|
} catch (Exception e) {
|
|
493
|
-
|
|
482
|
+
e.printStackTrace();
|
|
483
|
+
Log.e(getName(), "RNBD: Runnable e: " + Log.getStackTraceString(e));
|
|
494
484
|
}
|
|
495
485
|
}
|
|
496
486
|
}).start();
|
|
497
|
-
Log.d(getName(), "RNBD: startReportingTasks-6 downloadId: " + downloadId);
|
|
498
487
|
}
|
|
499
488
|
|
|
500
489
|
// TODO: NOT WORKING WITH DownloadManager FOR NOW
|
|
501
490
|
@ReactMethod
|
|
502
491
|
public void pauseTask(String configId) {
|
|
503
|
-
Log.d(getName(), "RNBD: pauseTask " + configId);
|
|
504
|
-
|
|
505
492
|
synchronized (sharedLock) {
|
|
506
493
|
Long downloadId = configIdToDownloadId.get(configId);
|
|
507
494
|
if (downloadId != null) {
|
|
@@ -513,8 +500,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
513
500
|
// TODO: NOT WORKING WITH DownloadManager FOR NOW
|
|
514
501
|
@ReactMethod
|
|
515
502
|
public void resumeTask(String configId) {
|
|
516
|
-
Log.d(getName(), "RNBD: resumeTask " + configId);
|
|
517
|
-
|
|
518
503
|
synchronized (sharedLock) {
|
|
519
504
|
Long downloadId = configIdToDownloadId.get(configId);
|
|
520
505
|
if (downloadId != null) {
|
|
@@ -525,11 +510,8 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
525
510
|
|
|
526
511
|
@ReactMethod
|
|
527
512
|
public void stopTask(String configId) {
|
|
528
|
-
Log.d(getName(), "RNBD: stopTask-1 " + configId);
|
|
529
|
-
|
|
530
513
|
synchronized (sharedLock) {
|
|
531
514
|
Long downloadId = configIdToDownloadId.get(configId);
|
|
532
|
-
Log.d(getName(), "RNBD: stopTask-2 " + configId + " downloadId " + downloadId);
|
|
533
515
|
if (downloadId != null) {
|
|
534
516
|
// DELETES CONFIG HERE SO receiver WILL NOT THROW ERROR DOWNLOAD_FAILED TO THE
|
|
535
517
|
// USER
|
|
@@ -543,14 +525,12 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
543
525
|
|
|
544
526
|
@ReactMethod
|
|
545
527
|
public void completeHandler(String configId, final Promise promise) {
|
|
546
|
-
Log.d(getName(), "RNBD: completeHandler-1 " + configId);
|
|
547
|
-
|
|
548
528
|
synchronized (sharedLock) {
|
|
549
529
|
Long downloadId = configIdToDownloadId.get(configId);
|
|
550
|
-
Log.d(getName(), "RNBD: completeHandler-2 " + configId + " downloadId " + downloadId);
|
|
551
530
|
if (downloadId != null) {
|
|
552
531
|
removeFromMaps(downloadId);
|
|
553
|
-
// REMOVES DOWNLOAD FROM DownloadManager SO IT WOULD NOT BE RETURNED IN
|
|
532
|
+
// REMOVES DOWNLOAD FROM DownloadManager SO IT WOULD NOT BE RETURNED IN
|
|
533
|
+
// checkForExistingDownloads
|
|
554
534
|
downloader.cancelDownload(downloadId);
|
|
555
535
|
}
|
|
556
536
|
}
|
|
@@ -558,8 +538,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
558
538
|
|
|
559
539
|
@ReactMethod
|
|
560
540
|
public void checkForExistingDownloads(final Promise promise) {
|
|
561
|
-
Log.d(getName(), "RNBD: checkForExistingDownloads-1");
|
|
562
|
-
|
|
563
541
|
WritableArray foundIds = Arguments.createArray();
|
|
564
542
|
|
|
565
543
|
synchronized (sharedLock) {
|
|
@@ -573,7 +551,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
573
551
|
Long downloadId = Long.parseLong(downloadStatus.getString("downloadId"));
|
|
574
552
|
|
|
575
553
|
if (downloadIdToConfig.containsKey(downloadId)) {
|
|
576
|
-
Log.d(getName(), "RNBD: checkForExistingDownloads-2");
|
|
577
554
|
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
578
555
|
WritableMap params = Arguments.createMap();
|
|
579
556
|
params.putString("id", config.id);
|
|
@@ -596,7 +573,6 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
596
573
|
// TOREMOVE
|
|
597
574
|
// config.reportedBegin = true;
|
|
598
575
|
} else {
|
|
599
|
-
Log.d(getName(), "RNBD: checkForExistingDownloads-3");
|
|
600
576
|
downloader.cancelDownload(downloadId);
|
|
601
577
|
}
|
|
602
578
|
} while (cursor.moveToNext());
|
|
@@ -604,7 +580,8 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
604
580
|
|
|
605
581
|
cursor.close();
|
|
606
582
|
} catch (Exception e) {
|
|
607
|
-
|
|
583
|
+
e.printStackTrace();
|
|
584
|
+
Log.e(getName(), "CheckForExistingDownloads e: " + Log.getStackTraceString(e));
|
|
608
585
|
}
|
|
609
586
|
}
|
|
610
587
|
|
package/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import DownloadTask from './lib/DownloadTask'
|
|
|
4
4
|
const { RNBackgroundDownloader } = NativeModules
|
|
5
5
|
const RNBackgroundDownloaderEmitter = new NativeEventEmitter(RNBackgroundDownloader)
|
|
6
6
|
|
|
7
|
+
const MIN_PROGRESS_INTERVAL = 250
|
|
7
8
|
const tasksMap = new Map()
|
|
8
9
|
|
|
9
10
|
const config = {
|
|
@@ -24,11 +25,11 @@ RNBackgroundDownloaderEmitter.addListener('downloadBegin', ({ id, ...rest }) =>
|
|
|
24
25
|
})
|
|
25
26
|
|
|
26
27
|
RNBackgroundDownloaderEmitter.addListener('downloadProgress', events => {
|
|
27
|
-
|
|
28
|
+
log('[RNBackgroundDownloader] downloadProgress-1', events, tasksMap)
|
|
28
29
|
for (const event of events) {
|
|
29
30
|
const { id, ...rest } = event
|
|
30
31
|
const task = tasksMap.get(id)
|
|
31
|
-
|
|
32
|
+
log('[RNBackgroundDownloader] downloadProgress-2', id, task)
|
|
32
33
|
task?.onProgress(rest)
|
|
33
34
|
}
|
|
34
35
|
})
|
|
@@ -53,10 +54,10 @@ export function setConfig({ headers, progressInterval, isLogsEnabled }) {
|
|
|
53
54
|
if (typeof headers === 'object') config.headers = headers
|
|
54
55
|
|
|
55
56
|
if (progressInterval != null)
|
|
56
|
-
if (typeof progressInterval === 'number' && progressInterval >=
|
|
57
|
+
if (typeof progressInterval === 'number' && progressInterval >= MIN_PROGRESS_INTERVAL)
|
|
57
58
|
config.progressInterval = progressInterval
|
|
58
59
|
else
|
|
59
|
-
console.warn(`[RNBackgroundDownloader] progressInterval must be a number >=
|
|
60
|
+
console.warn(`[RNBackgroundDownloader] progressInterval must be a number >= ${MIN_PROGRESS_INTERVAL}. You passed ${progressInterval}`)
|
|
60
61
|
|
|
61
62
|
if (typeof isLogsEnabled === 'boolean') config.isLogsEnabled = isLogsEnabled
|
|
62
63
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kesha-antonov/react-native-background-downloader",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"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.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -55,21 +55,21 @@
|
|
|
55
55
|
]
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@babel/core": "^7.23.
|
|
58
|
+
"@babel/core": "^7.23.7",
|
|
59
59
|
"@babel/eslint-parser": "^7.23.3",
|
|
60
|
-
"@babel/preset-env": "^7.23.
|
|
60
|
+
"@babel/preset-env": "^7.23.7",
|
|
61
61
|
"@babel/preset-typescript": "^7.23.3",
|
|
62
|
-
"@babel/runtime": "^7.23.
|
|
62
|
+
"@babel/runtime": "^7.23.7",
|
|
63
63
|
"@react-native/babel-preset": "^0.74.0",
|
|
64
64
|
"@react-native/eslint-config": "^0.74.0",
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
66
|
-
"@typescript-eslint/parser": "^6.
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
|
66
|
+
"@typescript-eslint/parser": "^6.17.0",
|
|
67
67
|
"babel-jest": "^29.7.0",
|
|
68
68
|
"eslint": "^8.56.0",
|
|
69
69
|
"eslint-config-standard": "^17.1.0",
|
|
70
70
|
"eslint-config-standard-jsx": "^11.0.0",
|
|
71
71
|
"eslint-plugin-import": "^2.29.1",
|
|
72
|
-
"eslint-plugin-n": "^16.
|
|
72
|
+
"eslint-plugin-n": "^16.6.1",
|
|
73
73
|
"eslint-plugin-node": "^11.1.0",
|
|
74
74
|
"eslint-plugin-promise": "^6.1.1",
|
|
75
75
|
"eslint-plugin-react": "^7.33.2",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"lint-staged": ">=15",
|
|
81
81
|
"metro-react-native-babel-preset": "^0.77.0",
|
|
82
82
|
"react": "18.2.0",
|
|
83
|
-
"react-native": "0.73.
|
|
83
|
+
"react-native": "0.73.1",
|
|
84
84
|
"react-native-fs": "^2.20.0",
|
|
85
85
|
"react-native-vector-icons": "^10.0.3",
|
|
86
86
|
"react-test-renderer": "18.2.0",
|