@kesha-antonov/react-native-background-downloader 3.2.0 → 3.2.2
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
CHANGED
|
@@ -330,6 +330,29 @@ Stops the download for good and removes the file that was written so far
|
|
|
330
330
|
|
|
331
331
|
An absolute path to the app's documents directory. It is recommended that you use this path as the target of downloaded files.
|
|
332
332
|
|
|
333
|
+
## Rules for proguard-rules.pro
|
|
334
|
+
|
|
335
|
+
In case of error `java.lang.IllegalStateException: TypeToken must be created with a type argument: new TypeToken<...>()` in Android release add this to `proguard-rules.pro`:
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
# Application classes that will be serialized/deserialized over Gson
|
|
339
|
+
-keep class com.yourapplicationname.model.api.** { *; }
|
|
340
|
+
|
|
341
|
+
# Gson uses generic type information stored in a class file when working with
|
|
342
|
+
# fields. Proguard removes such information by default, keep it.
|
|
343
|
+
-keepattributes Signature
|
|
344
|
+
|
|
345
|
+
# This is also needed for R8 in compat mode since multiple
|
|
346
|
+
# optimizations will remove the generic signature such as class
|
|
347
|
+
# merging and argument removal. See:
|
|
348
|
+
# https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson
|
|
349
|
+
-keep class com.google.gson.reflect.TypeToken { *; }
|
|
350
|
+
-keep class * extends com.google.gson.reflect.TypeToken
|
|
351
|
+
|
|
352
|
+
# Optional. For using GSON @Expose annotation
|
|
353
|
+
-keepattributes AnnotationDefault,RuntimeVisibleAnnotations
|
|
354
|
+
```
|
|
355
|
+
|
|
333
356
|
## TODO
|
|
334
357
|
|
|
335
358
|
- [ ] Write better examples - current kinda old and shallow
|
package/android/build.gradle
CHANGED
|
@@ -189,10 +189,18 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
compatRegisterReceiver(context, downloadReceiver, filter, true);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// TAKEN FROM
|
|
196
|
+
// https://github.com/facebook/react-native/pull/38256/files#diff-d5e21477eeadeb0c536d5870f487a8528f9a16ae928c397fec7b255805cc8ad3
|
|
197
|
+
private void compatRegisterReceiver(Context context, BroadcastReceiver receiver, IntentFilter filter,
|
|
198
|
+
boolean exported) {
|
|
199
|
+
if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
|
|
200
|
+
context.registerReceiver(
|
|
201
|
+
receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED);
|
|
194
202
|
} else {
|
|
195
|
-
context.registerReceiver(
|
|
203
|
+
context.registerReceiver(receiver, filter);
|
|
196
204
|
}
|
|
197
205
|
}
|
|
198
206
|
|
|
@@ -485,11 +493,18 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
|
485
493
|
|
|
486
494
|
private void loadDownloadIdToConfigMap() {
|
|
487
495
|
synchronized (sharedLock) {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
496
|
+
try {
|
|
497
|
+
String str = mmkv.decodeString(getName() + "_downloadIdToConfig");
|
|
498
|
+
if (str != null) {
|
|
499
|
+
Gson gson = new Gson();
|
|
500
|
+
|
|
501
|
+
TypeToken<Map<Long, RNBGDTaskConfig>> mapType = new TypeToken<Map<Long, RNBGDTaskConfig>>() {
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
downloadIdToConfig = (Map<Long, RNBGDTaskConfig>) gson.fromJson(str, mapType);
|
|
505
|
+
}
|
|
506
|
+
} catch (Exception e) {
|
|
507
|
+
Log.e(getName(), "loadDownloadIdToConfigMap: " + Log.getStackTraceString(e));
|
|
493
508
|
}
|
|
494
509
|
}
|
|
495
510
|
}
|
package/index.d.ts
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
#define ID_TO_CONFIG_MAP_KEY @"com.eko.bgdownloadidmap"
|
|
6
6
|
#define PROGRESS_INTERVAL_KEY @"progressInterval"
|
|
7
7
|
|
|
8
|
+
// DISABLES LOGS IN RELEASE MODE. NSLOG IS SLOW: https://stackoverflow.com/a/17738695/3452513
|
|
9
|
+
#ifdef DEBUG
|
|
10
|
+
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
|
|
11
|
+
#else
|
|
12
|
+
#define DLog( s, ... )
|
|
13
|
+
#endif
|
|
14
|
+
|
|
8
15
|
static CompletionHandler storedCompletionHandler;
|
|
9
16
|
|
|
10
17
|
@implementation RNBackgroundDownloader {
|
|
@@ -55,7 +62,7 @@ RCT_EXPORT_MODULE();
|
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
- (id)init {
|
|
58
|
-
|
|
65
|
+
DLog(@"[RNBackgroundDownloader] - [init]");
|
|
59
66
|
self = [super init];
|
|
60
67
|
if (self) {
|
|
61
68
|
[MMKV initializeMMKV:nil];
|
|
@@ -98,19 +105,19 @@ RCT_EXPORT_MODULE();
|
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
- (void)dealloc {
|
|
101
|
-
|
|
108
|
+
DLog(@"[RNBackgroundDownloader] - [dealloc]");
|
|
102
109
|
[self unregisterSession];
|
|
103
110
|
[self unregisterBridgeListener];
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
- (void)handleBridgeHotReload:(NSNotification *) note {
|
|
107
|
-
|
|
114
|
+
DLog(@"[RNBackgroundDownloader] - [handleBridgeHotReload]");
|
|
108
115
|
[self unregisterSession];
|
|
109
116
|
[self unregisterBridgeListener];
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
- (void)lazyRegisterSession {
|
|
113
|
-
|
|
120
|
+
DLog(@"[RNBackgroundDownloader] - [lazyRegisterSession]");
|
|
114
121
|
@synchronized (sharedLock) {
|
|
115
122
|
if (urlSession == nil) {
|
|
116
123
|
urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
|
|
@@ -119,7 +126,7 @@ RCT_EXPORT_MODULE();
|
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
- (void)unregisterSession {
|
|
122
|
-
|
|
129
|
+
DLog(@"[RNBackgroundDownloader] - [unregisterSession]");
|
|
123
130
|
if (urlSession) {
|
|
124
131
|
[urlSession invalidateAndCancel];
|
|
125
132
|
urlSession = nil;
|
|
@@ -127,7 +134,7 @@ RCT_EXPORT_MODULE();
|
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
- (void)registerBridgeListener {
|
|
130
|
-
|
|
137
|
+
DLog(@"[RNBackgroundDownloader] - [registerBridgeListener]");
|
|
131
138
|
@synchronized (sharedLock) {
|
|
132
139
|
if (isBridgeListenerInited != YES) {
|
|
133
140
|
isBridgeListenerInited = YES;
|
|
@@ -150,7 +157,7 @@ RCT_EXPORT_MODULE();
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
- (void)unregisterBridgeListener {
|
|
153
|
-
|
|
160
|
+
DLog(@"[RNBackgroundDownloader] - [unregisterBridgeListener]");
|
|
154
161
|
if (isBridgeListenerInited == YES) {
|
|
155
162
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
156
163
|
isBridgeListenerInited = NO;
|
|
@@ -158,18 +165,18 @@ RCT_EXPORT_MODULE();
|
|
|
158
165
|
}
|
|
159
166
|
|
|
160
167
|
- (void)handleBridgeJavascriptLoad:(NSNotification *) note {
|
|
161
|
-
|
|
168
|
+
DLog(@"[RNBackgroundDownloader] - [handleBridgeJavascriptLoad]");
|
|
162
169
|
isJavascriptLoaded = YES;
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
- (void)handleBridgeAppEnterForeground:(NSNotification *) note {
|
|
166
|
-
|
|
173
|
+
DLog(@"[RNBackgroundDownloader] - [handleBridgeAppEnterForeground]");
|
|
167
174
|
[self resumeTasks];
|
|
168
175
|
}
|
|
169
176
|
|
|
170
177
|
- (void)resumeTasks {
|
|
171
178
|
@synchronized (sharedLock) {
|
|
172
|
-
|
|
179
|
+
DLog(@"[RNBackgroundDownloader] - [resumeTasks]");
|
|
173
180
|
[urlSession getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {
|
|
174
181
|
for (NSURLSessionDownloadTask *task in downloadTasks) {
|
|
175
182
|
// running - 0
|
|
@@ -186,7 +193,7 @@ RCT_EXPORT_MODULE();
|
|
|
186
193
|
}
|
|
187
194
|
|
|
188
195
|
- (void)removeTaskFromMap: (NSURLSessionTask *)task {
|
|
189
|
-
|
|
196
|
+
DLog(@"[RNBackgroundDownloader] - [removeTaskFromMap]");
|
|
190
197
|
@synchronized (sharedLock) {
|
|
191
198
|
NSNumber *taskId = @(task.taskIdentifier);
|
|
192
199
|
RNBGDTaskConfig *taskConfig = taskToConfigMap[taskId];
|
|
@@ -203,7 +210,7 @@ RCT_EXPORT_MODULE();
|
|
|
203
210
|
|
|
204
211
|
#pragma mark - JS exported methods
|
|
205
212
|
RCT_EXPORT_METHOD(download: (NSDictionary *) options) {
|
|
206
|
-
|
|
213
|
+
DLog(@"[RNBackgroundDownloader] - [download]");
|
|
207
214
|
NSString *identifier = options[@"id"];
|
|
208
215
|
NSString *url = options[@"url"];
|
|
209
216
|
NSString *destination = options[@"destination"];
|
|
@@ -218,14 +225,14 @@ RCT_EXPORT_METHOD(download: (NSDictionary *) options) {
|
|
|
218
225
|
|
|
219
226
|
NSString *destinationRelative = [self getRelativeFilePathFromPath:destination];
|
|
220
227
|
|
|
221
|
-
|
|
228
|
+
DLog(@"[RNBackgroundDownloader] - [download] url %@ destination %@ progressInterval %f", url, destination, progressInterval);
|
|
222
229
|
if (identifier == nil || url == nil || destination == nil) {
|
|
223
|
-
|
|
230
|
+
DLog(@"[RNBackgroundDownloader] - [Error] id, url and destination must be set");
|
|
224
231
|
return;
|
|
225
232
|
}
|
|
226
233
|
|
|
227
234
|
if (destinationRelative == nil) {
|
|
228
|
-
|
|
235
|
+
DLog(@"[RNBackgroundDownloader] - [Error] destination is not valid");
|
|
229
236
|
return;
|
|
230
237
|
}
|
|
231
238
|
|
|
@@ -243,7 +250,7 @@ RCT_EXPORT_METHOD(download: (NSDictionary *) options) {
|
|
|
243
250
|
|
|
244
251
|
NSURLSessionDownloadTask __strong *task = [urlSession downloadTaskWithRequest:request];
|
|
245
252
|
if (task == nil) {
|
|
246
|
-
|
|
253
|
+
DLog(@"[RNBackgroundDownloader] - [Error] failed to create download task");
|
|
247
254
|
return;
|
|
248
255
|
}
|
|
249
256
|
|
|
@@ -266,7 +273,7 @@ RCT_EXPORT_METHOD(download: (NSDictionary *) options) {
|
|
|
266
273
|
}
|
|
267
274
|
|
|
268
275
|
RCT_EXPORT_METHOD(pauseTask: (NSString *)identifier) {
|
|
269
|
-
|
|
276
|
+
DLog(@"[RNBackgroundDownloader] - [pauseTask]");
|
|
270
277
|
@synchronized (sharedLock) {
|
|
271
278
|
NSURLSessionDownloadTask *task = self->idToTaskMap[identifier];
|
|
272
279
|
if (task != nil && task.state == NSURLSessionTaskStateRunning) {
|
|
@@ -276,7 +283,7 @@ RCT_EXPORT_METHOD(pauseTask: (NSString *)identifier) {
|
|
|
276
283
|
}
|
|
277
284
|
|
|
278
285
|
RCT_EXPORT_METHOD(resumeTask: (NSString *)identifier) {
|
|
279
|
-
|
|
286
|
+
DLog(@"[RNBackgroundDownloader] - [resumeTask]");
|
|
280
287
|
@synchronized (sharedLock) {
|
|
281
288
|
NSURLSessionDownloadTask *task = self->idToTaskMap[identifier];
|
|
282
289
|
if (task != nil && task.state == NSURLSessionTaskStateSuspended) {
|
|
@@ -286,7 +293,7 @@ RCT_EXPORT_METHOD(resumeTask: (NSString *)identifier) {
|
|
|
286
293
|
}
|
|
287
294
|
|
|
288
295
|
RCT_EXPORT_METHOD(stopTask: (NSString *)identifier) {
|
|
289
|
-
|
|
296
|
+
DLog(@"[RNBackgroundDownloader] - [stopTask]");
|
|
290
297
|
@synchronized (sharedLock) {
|
|
291
298
|
NSURLSessionDownloadTask *task = self->idToTaskMap[identifier];
|
|
292
299
|
if (task != nil) {
|
|
@@ -297,7 +304,7 @@ RCT_EXPORT_METHOD(stopTask: (NSString *)identifier) {
|
|
|
297
304
|
}
|
|
298
305
|
|
|
299
306
|
RCT_EXPORT_METHOD(completeHandler:(nonnull NSString *)jobId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
300
|
-
|
|
307
|
+
DLog(@"[RNBackgroundDownloader] - [completeHandlerIOS]");
|
|
301
308
|
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
|
302
309
|
if (storedCompletionHandler) {
|
|
303
310
|
storedCompletionHandler();
|
|
@@ -309,7 +316,7 @@ RCT_EXPORT_METHOD(completeHandler:(nonnull NSString *)jobId resolver:(RCTPromise
|
|
|
309
316
|
}
|
|
310
317
|
|
|
311
318
|
RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
312
|
-
|
|
319
|
+
DLog(@"[RNBackgroundDownloader] - [checkForExistingDownloads]");
|
|
313
320
|
[self lazyRegisterSession];
|
|
314
321
|
[urlSession getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {
|
|
315
322
|
NSMutableArray *foundTasks = [[NSMutableArray alloc] init];
|
|
@@ -381,7 +388,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
381
388
|
|
|
382
389
|
#pragma mark - NSURLSessionDownloadDelegate methods
|
|
383
390
|
- (void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location {
|
|
384
|
-
|
|
391
|
+
DLog(@"[RNBackgroundDownloader] - [didFinishDownloadingToURL]");
|
|
385
392
|
@synchronized (sharedLock) {
|
|
386
393
|
RNBGDTaskConfig *taskConfig = taskToConfigMap[@(downloadTask.taskIdentifier)];
|
|
387
394
|
|
|
@@ -417,7 +424,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
417
424
|
}
|
|
418
425
|
|
|
419
426
|
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedbytesTotal:(int64_t)expectedbytesTotal {
|
|
420
|
-
|
|
427
|
+
DLog(@"[RNBackgroundDownloader] - [didResumeAtOffset]");
|
|
421
428
|
}
|
|
422
429
|
|
|
423
430
|
- (void)URLSession:(NSURLSession *)session
|
|
@@ -426,7 +433,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
426
433
|
totalBytesWritten:(int64_t)bytesTotalWritten
|
|
427
434
|
totalBytesExpectedToWrite:(int64_t)bytesTotalExpectedToWrite
|
|
428
435
|
{
|
|
429
|
-
|
|
436
|
+
DLog(@"[RNBackgroundDownloader] - [didWriteData]");
|
|
430
437
|
@synchronized (sharedLock) {
|
|
431
438
|
RNBGDTaskConfig *taskConfig = taskToConfigMap[@(downloadTask.taskIdentifier)];
|
|
432
439
|
if (taskConfig != nil) {
|
|
@@ -466,7 +473,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
466
473
|
}
|
|
467
474
|
|
|
468
475
|
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
|
469
|
-
|
|
476
|
+
DLog(@"[RNBackgroundDownloader] - [didCompleteWithError]");
|
|
470
477
|
@synchronized (sharedLock) {
|
|
471
478
|
if (error == nil) {
|
|
472
479
|
return;
|
|
@@ -494,11 +501,11 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
494
501
|
}
|
|
495
502
|
|
|
496
503
|
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
|
|
497
|
-
|
|
504
|
+
DLog(@"[RNBackgroundDownloader] - [URLSessionDidFinishEventsForBackgroundURLSession]");
|
|
498
505
|
}
|
|
499
506
|
|
|
500
507
|
+ (void)setCompletionHandlerWithIdentifier: (NSString *)identifier completionHandler: (CompletionHandler)completionHandler {
|
|
501
|
-
|
|
508
|
+
DLog(@"[RNBackgroundDownloader] - [setCompletionHandlerWithIdentifier]");
|
|
502
509
|
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
|
|
503
510
|
NSString *sessionIdentifier = [bundleIdentifier stringByAppendingString:@".backgrounddownloadtask"];
|
|
504
511
|
if ([sessionIdentifier isEqualToString:identifier]) {
|
|
@@ -507,7 +514,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
507
514
|
}
|
|
508
515
|
|
|
509
516
|
- (NSError *)getServerError: (nonnull NSURLSessionDownloadTask *)downloadTask {
|
|
510
|
-
|
|
517
|
+
DLog(@"[RNBackgroundDownloader] - [getServerError]");
|
|
511
518
|
NSError *serverError;
|
|
512
519
|
NSInteger httpStatusCode = [((NSHTTPURLResponse *)downloadTask.response) statusCode];
|
|
513
520
|
|
|
@@ -524,7 +531,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
524
531
|
}
|
|
525
532
|
|
|
526
533
|
- (BOOL)saveFile: (nonnull RNBGDTaskConfig *) taskConfig downloadURL:(nonnull NSURL *)location error:(NSError **)saveError {
|
|
527
|
-
|
|
534
|
+
DLog(@"[RNBackgroundDownloader] - [saveFile]");
|
|
528
535
|
// taskConfig.destination is absolute path.
|
|
529
536
|
// The absolute path may change when the application is restarted.
|
|
530
537
|
// But the relative path remains the same.
|
|
@@ -547,7 +554,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
547
554
|
NSData *taskMapRaw = [NSKeyedArchiver archivedDataWithRootObject:taskMap requiringSecureCoding:YES error:&error];
|
|
548
555
|
|
|
549
556
|
if (error) {
|
|
550
|
-
|
|
557
|
+
DLog(@"[RNBackgroundDownloader] Serialization error: %@", error);
|
|
551
558
|
return nil;
|
|
552
559
|
}
|
|
553
560
|
|
|
@@ -561,7 +568,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
|
|
|
561
568
|
NSMutableDictionary<NSNumber *, RNBGDTaskConfig *> *taskMap = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:taskMapRaw error:&error];
|
|
562
569
|
|
|
563
570
|
if (error) {
|
|
564
|
-
|
|
571
|
+
DLog(@"[RNBackgroundDownloader] Deserialization error: %@", error);
|
|
565
572
|
return nil;
|
|
566
573
|
}
|
|
567
574
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kesha-antonov/react-native-background-downloader",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.2",
|
|
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",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"scripts": {
|
|
41
41
|
"bump": "npm version patch",
|
|
42
42
|
"lint": "eslint .",
|
|
43
|
+
"prepublishOnly": "jest && npm run lint",
|
|
43
44
|
"publish": "npm publish",
|
|
44
45
|
"test": "jest"
|
|
45
46
|
},
|