@kesha-antonov/react-native-background-downloader 2.10.0 → 3.0.0-alpha.0
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 +20 -60
- package/android/build.gradle +0 -9
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/java/com/eko/Downloader.java +157 -0
- package/android/src/main/java/com/eko/OnBegin.java +49 -0
- package/android/src/main/java/com/eko/OnProgress.java +132 -0
- package/android/src/main/java/com/eko/RNBGDTaskConfig.java +3 -1
- package/android/src/main/java/com/eko/RNBackgroundDownloaderModule.java +297 -301
- package/index.d.ts +8 -22
- package/index.ts +37 -28
- package/ios/RNBackgroundDownloader.h +1 -1
- package/ios/RNBackgroundDownloader.m +8 -8
- package/lib/DownloadTask.ts +8 -8
- package/package.json +1 -1
|
@@ -8,27 +8,14 @@ import com.facebook.react.bridge.Promise;
|
|
|
8
8
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
9
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
10
10
|
import com.facebook.react.bridge.ReactMethod;
|
|
11
|
-
import com.facebook.react.bridge.Arguments;
|
|
12
11
|
import com.facebook.react.bridge.ReadableMap;
|
|
13
12
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
14
13
|
import com.facebook.react.bridge.WritableArray;
|
|
15
14
|
import com.facebook.react.bridge.WritableMap;
|
|
16
15
|
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
17
|
-
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import com.tonyodev.fetch2.Error;
|
|
21
|
-
import com.tonyodev.fetch2.Fetch;
|
|
22
|
-
import com.tonyodev.fetch2.FetchConfiguration;
|
|
23
|
-
import com.tonyodev.fetch2.FetchListener;
|
|
24
|
-
import com.tonyodev.fetch2.NetworkType;
|
|
25
|
-
import com.tonyodev.fetch2.Priority;
|
|
26
|
-
import com.tonyodev.fetch2.Request;
|
|
27
|
-
import com.tonyodev.fetch2.Status;
|
|
28
|
-
import com.tonyodev.fetch2core.DownloadBlock;
|
|
29
|
-
import com.tonyodev.fetch2core.Func;
|
|
30
|
-
import com.tonyodev.fetch2.HttpUrlConnectionDownloader;
|
|
31
|
-
import com.tonyodev.fetch2core.Downloader;
|
|
16
|
+
|
|
17
|
+
import android.app.DownloadManager;
|
|
18
|
+
import android.app.DownloadManager.Request;
|
|
32
19
|
|
|
33
20
|
import org.jetbrains.annotations.NotNull;
|
|
34
21
|
|
|
@@ -42,16 +29,33 @@ import java.util.Date;
|
|
|
42
29
|
import java.util.HashMap;
|
|
43
30
|
import java.util.List;
|
|
44
31
|
import java.util.Map;
|
|
32
|
+
import java.util.Scanner;
|
|
45
33
|
|
|
46
34
|
import javax.annotation.Nullable;
|
|
47
35
|
|
|
48
|
-
import okhttp3.OkHttpClient;
|
|
49
|
-
|
|
50
36
|
import java.util.Set;
|
|
51
37
|
import java.net.URL;
|
|
52
38
|
import java.net.URLConnection;
|
|
39
|
+
import java.nio.file.Files;
|
|
40
|
+
import java.nio.file.StandardCopyOption;
|
|
41
|
+
|
|
42
|
+
import android.content.BroadcastReceiver;
|
|
43
|
+
import android.content.Context;
|
|
44
|
+
import android.content.Intent;
|
|
45
|
+
import android.content.IntentFilter;
|
|
46
|
+
import android.util.LongSparseArray;
|
|
47
|
+
|
|
48
|
+
import com.facebook.react.bridge.Callback;
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
import java.util.ArrayList;
|
|
51
|
+
import java.util.Arrays;
|
|
52
|
+
import android.net.Uri;
|
|
53
|
+
import android.webkit.MimeTypeMap;
|
|
54
|
+
import android.database.Cursor;
|
|
55
|
+
import android.os.Build;
|
|
56
|
+
import android.os.Environment;
|
|
57
|
+
|
|
58
|
+
public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule {
|
|
55
59
|
|
|
56
60
|
private static final int TASK_RUNNING = 0;
|
|
57
61
|
private static final int TASK_SUSPENDED = 1;
|
|
@@ -64,37 +68,117 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule imp
|
|
|
64
68
|
private static final int ERR_FILE_NOT_FOUND = 3;
|
|
65
69
|
private static final int ERR_OTHERS = 100;
|
|
66
70
|
|
|
67
|
-
private static Map<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
private
|
|
80
|
-
private Map<
|
|
81
|
-
@SuppressLint("UseSparseArrays")
|
|
82
|
-
private Map<Integer, RNBGDTaskConfig> requestIdToConfig = new HashMap<>();
|
|
71
|
+
private static Map<Integer, Integer> stateMap = new HashMap<Integer, Integer>() {
|
|
72
|
+
{
|
|
73
|
+
put(DownloadManager.STATUS_FAILED, TASK_CANCELING);
|
|
74
|
+
put(DownloadManager.STATUS_PAUSED, TASK_SUSPENDED);
|
|
75
|
+
put(DownloadManager.STATUS_PENDING, TASK_RUNNING);
|
|
76
|
+
put(DownloadManager.STATUS_RUNNING, TASK_RUNNING);
|
|
77
|
+
put(DownloadManager.STATUS_SUCCESSFUL, TASK_COMPLETED);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
private Downloader downloader;
|
|
82
|
+
|
|
83
|
+
private Map<String, Long> condigIdToDownloadId = new HashMap<>();
|
|
84
|
+
private Map<Long, RNBGDTaskConfig> downloadIdToConfig = new HashMap<>();
|
|
83
85
|
private DeviceEventManagerModule.RCTDeviceEventEmitter ee;
|
|
84
|
-
private
|
|
85
|
-
|
|
86
|
+
private Map<String, OnProgress> onProgressThreads = new HashMap<>();
|
|
87
|
+
|
|
86
88
|
private static Object sharedLock = new Object();
|
|
87
89
|
|
|
90
|
+
BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
|
91
|
+
@Override
|
|
92
|
+
public void onReceive(Context context, Intent intent) {
|
|
93
|
+
Log.d(getName(), "RNBD: onReceive-1");
|
|
94
|
+
try {
|
|
95
|
+
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
|
|
96
|
+
Log.d(getName(), "RNBD: onReceive-2 " + downloadId);
|
|
97
|
+
|
|
98
|
+
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
99
|
+
|
|
100
|
+
if (config != null) {
|
|
101
|
+
Log.d(getName(), "RNBD: onReceive-3");
|
|
102
|
+
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
103
|
+
int status = downloadStatus.getInt("status");
|
|
104
|
+
|
|
105
|
+
Log.d(getName(), "RNBD: onReceive: status - " + status);
|
|
106
|
+
|
|
107
|
+
stopTrackingProgress(config.id);
|
|
108
|
+
|
|
109
|
+
synchronized (sharedLock) {
|
|
110
|
+
switch (status) {
|
|
111
|
+
case DownloadManager.STATUS_SUCCESSFUL: {
|
|
112
|
+
// MOVES FILE TO DESTINATION
|
|
113
|
+
String localUri = downloadStatus.getString("localUri");
|
|
114
|
+
Log.d(getName(), "RNBD: onReceive: localUri " + localUri + " destination " + config.destination);
|
|
115
|
+
File file = new File(localUri);
|
|
116
|
+
Log.d(getName(), "RNBD: onReceive: file exists " + file.exists());
|
|
117
|
+
File dest = new File(config.destination);
|
|
118
|
+
Log.d(getName(), "RNBD: onReceive: dest exists " + dest.exists());
|
|
119
|
+
Files.move(file.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
120
|
+
|
|
121
|
+
WritableMap params = Arguments.createMap();
|
|
122
|
+
params.putString("id", config.id);
|
|
123
|
+
params.putString("location", config.destination);
|
|
124
|
+
|
|
125
|
+
ee.emit("downloadComplete", params);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case DownloadManager.STATUS_FAILED: {
|
|
129
|
+
Log.e(getName(), "Error in enqueue: " + downloadStatus.getInt("status") + ":"
|
|
130
|
+
+ downloadStatus.getInt("reason") + ":" + downloadStatus.getString("reasonText"));
|
|
131
|
+
|
|
132
|
+
WritableMap params = Arguments.createMap();
|
|
133
|
+
params.putString("id", config.id);
|
|
134
|
+
params.putInt("errorCode", downloadStatus.getInt("reason"));
|
|
135
|
+
params.putString("error", downloadStatus.getString("reasonText"));
|
|
136
|
+
ee.emit("downloadFailed", params);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (Exception e) {
|
|
143
|
+
Log.e(getName(), "downloadReceiver: onReceive. " + Log.getStackTraceString(e));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
88
148
|
public RNBackgroundDownloaderModule(ReactApplicationContext reactContext) {
|
|
89
149
|
super(reactContext);
|
|
90
150
|
|
|
91
151
|
ReadableMap emptyMap = Arguments.createMap();
|
|
92
152
|
this.initDownloader(emptyMap);
|
|
153
|
+
|
|
154
|
+
downloader = new Downloader(reactContext);
|
|
155
|
+
|
|
156
|
+
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
|
|
157
|
+
compatRegisterReceiver(reactContext, downloadReceiver, filter, true);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// TAKEN FROM
|
|
161
|
+
// https://github.com/facebook/react-native/pull/38256/files#diff-d5e21477eeadeb0c536d5870f487a8528f9a16ae928c397fec7b255805cc8ad3
|
|
162
|
+
private void compatRegisterReceiver(Context context, BroadcastReceiver receiver, IntentFilter filter,
|
|
163
|
+
boolean exported) {
|
|
164
|
+
if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
|
|
165
|
+
context.registerReceiver(
|
|
166
|
+
receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED);
|
|
167
|
+
} else {
|
|
168
|
+
context.registerReceiver(receiver, filter);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private void stopTrackingProgress(String configId) {
|
|
173
|
+
OnProgress onProgressTh = onProgressThreads.get(configId);
|
|
174
|
+
if (onProgressTh != null) {
|
|
175
|
+
onProgressTh.interrupt();
|
|
176
|
+
onProgressThreads.remove(configId);
|
|
177
|
+
}
|
|
93
178
|
}
|
|
94
179
|
|
|
95
180
|
@Override
|
|
96
181
|
public void onCatalystInstanceDestroy() {
|
|
97
|
-
fetch.close();
|
|
98
182
|
}
|
|
99
183
|
|
|
100
184
|
@Override
|
|
@@ -132,46 +216,27 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule imp
|
|
|
132
216
|
constants.put("TaskSuspended", TASK_SUSPENDED);
|
|
133
217
|
constants.put("TaskCanceling", TASK_CANCELING);
|
|
134
218
|
constants.put("TaskCompleted", TASK_COMPLETED);
|
|
135
|
-
|
|
136
|
-
constants.put("PriorityNormal", Priority.NORMAL.getValue());
|
|
137
|
-
constants.put("PriorityLow", Priority.LOW.getValue());
|
|
138
|
-
constants.put("OnlyWifi", NetworkType.WIFI_ONLY.getValue());
|
|
139
|
-
constants.put("AllNetworks", NetworkType.ALL.getValue());
|
|
219
|
+
|
|
140
220
|
return constants;
|
|
141
221
|
}
|
|
142
222
|
|
|
143
223
|
@ReactMethod
|
|
144
224
|
public void initDownloader(ReadableMap options) {
|
|
145
|
-
|
|
146
|
-
fetch.close();
|
|
147
|
-
fetch = null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
Downloader.FileDownloaderType downloaderType = options.getString("type") == "parallel"
|
|
151
|
-
? Downloader.FileDownloaderType.PARALLEL
|
|
152
|
-
: Downloader.FileDownloaderType.SEQUENTIAL;
|
|
153
|
-
|
|
154
|
-
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
|
|
155
|
-
final Downloader okHttpDownloader = new OkHttpDownloader(okHttpClient,
|
|
156
|
-
downloaderType);
|
|
225
|
+
Log.d(getName(), "RNBD: initDownloader");
|
|
157
226
|
|
|
158
227
|
loadConfigMap();
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
.setHttpDownloader(okHttpDownloader)
|
|
162
|
-
.enableRetryOnNetworkGain(true)
|
|
163
|
-
.setHttpDownloader(new HttpUrlConnectionDownloader(downloaderType))
|
|
164
|
-
.build();
|
|
165
|
-
fetch = Fetch.Impl.getInstance(fetchConfiguration);
|
|
166
|
-
fetch.addListener(this);
|
|
228
|
+
|
|
229
|
+
// TODO. MAYBE REINIT DOWNLOADER
|
|
167
230
|
}
|
|
168
231
|
|
|
169
|
-
private void removeFromMaps(
|
|
170
|
-
|
|
171
|
-
|
|
232
|
+
private void removeFromMaps(long downloadId) {
|
|
233
|
+
Log.d(getName(), "RNBD: removeFromMaps");
|
|
234
|
+
|
|
235
|
+
synchronized (sharedLock) {
|
|
236
|
+
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
172
237
|
if (config != null) {
|
|
173
|
-
|
|
174
|
-
|
|
238
|
+
condigIdToDownloadId.remove(config.id);
|
|
239
|
+
downloadIdToConfig.remove(downloadId);
|
|
175
240
|
|
|
176
241
|
saveConfigMap();
|
|
177
242
|
}
|
|
@@ -179,11 +244,13 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule imp
|
|
|
179
244
|
}
|
|
180
245
|
|
|
181
246
|
private void saveConfigMap() {
|
|
182
|
-
|
|
247
|
+
Log.d(getName(), "RNBD: saveConfigMap");
|
|
248
|
+
|
|
249
|
+
synchronized (sharedLock) {
|
|
183
250
|
File file = new File(this.getReactApplicationContext().getFilesDir(), "RNFileBackgroundDownload_configMap");
|
|
184
251
|
try {
|
|
185
252
|
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
|
|
186
|
-
outputStream.writeObject(
|
|
253
|
+
outputStream.writeObject(downloadIdToConfig);
|
|
187
254
|
outputStream.flush();
|
|
188
255
|
outputStream.close();
|
|
189
256
|
} catch (IOException e) {
|
|
@@ -193,31 +260,17 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule imp
|
|
|
193
260
|
}
|
|
194
261
|
|
|
195
262
|
private void loadConfigMap() {
|
|
263
|
+
Log.d(getName(), "RNBD: loadConfigMap");
|
|
264
|
+
|
|
196
265
|
File file = new File(this.getReactApplicationContext().getFilesDir(), "RNFileBackgroundDownload_configMap");
|
|
197
266
|
try {
|
|
198
267
|
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
|
|
199
|
-
|
|
268
|
+
downloadIdToConfig = (Map<Long, RNBGDTaskConfig>) inputStream.readObject();
|
|
200
269
|
} catch (IOException | ClassNotFoundException e) {
|
|
201
270
|
e.printStackTrace();
|
|
202
271
|
}
|
|
203
272
|
}
|
|
204
273
|
|
|
205
|
-
private int convertErrorCode(Error error) {
|
|
206
|
-
if ((error == Error.FILE_NOT_CREATED)
|
|
207
|
-
|| (error == Error.WRITE_PERMISSION_DENIED)) {
|
|
208
|
-
return ERR_NO_WRITE_PERMISSION;
|
|
209
|
-
} else if ((error == Error.CONNECTION_TIMED_OUT)
|
|
210
|
-
|| (error == Error.NO_NETWORK_CONNECTION)) {
|
|
211
|
-
return ERR_NO_INTERNET;
|
|
212
|
-
} else if (error == Error.NO_STORAGE_SPACE) {
|
|
213
|
-
return ERR_STORAGE_FULL;
|
|
214
|
-
} else if (error == Error.FILE_NOT_FOUND) {
|
|
215
|
-
return ERR_FILE_NOT_FOUND;
|
|
216
|
-
} else {
|
|
217
|
-
return ERR_OTHERS;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
274
|
// JS Methods
|
|
222
275
|
@ReactMethod
|
|
223
276
|
public void download(ReadableMap options) {
|
|
@@ -226,277 +279,220 @@ public class RNBackgroundDownloaderModule extends ReactContextBaseJavaModule imp
|
|
|
226
279
|
String destination = options.getString("destination");
|
|
227
280
|
ReadableMap headers = options.getMap("headers");
|
|
228
281
|
String metadata = options.getString("metadata");
|
|
282
|
+
int progressInterval = options.getInt("progressInterval");
|
|
283
|
+
|
|
284
|
+
boolean isAllowedOverRoaming = options.getBoolean("isAllowedOverRoaming");
|
|
285
|
+
boolean isAllowedOverMetered = options.getBoolean("isAllowedOverMetered");
|
|
286
|
+
|
|
287
|
+
Log.d(getName(), "RNBD: download " + id + " " + url + " " + destination + " " + metadata);
|
|
229
288
|
|
|
230
289
|
if (id == null || url == null || destination == null) {
|
|
231
290
|
Log.e(getName(), "id, url and destination must be set");
|
|
232
291
|
return;
|
|
233
292
|
}
|
|
234
293
|
|
|
235
|
-
RNBGDTaskConfig config = new RNBGDTaskConfig(id, destination, metadata);
|
|
236
|
-
final Request request = new Request(url
|
|
294
|
+
RNBGDTaskConfig config = new RNBGDTaskConfig(id, url, destination, metadata);
|
|
295
|
+
final Request request = new Request(Uri.parse(url));
|
|
296
|
+
request.setAllowedOverRoaming(isAllowedOverRoaming);
|
|
297
|
+
request.setAllowedOverMetered(isAllowedOverMetered);
|
|
298
|
+
request.setNotificationVisibility(Request.VISIBILITY_HIDDEN);
|
|
299
|
+
request.setRequiresCharging(false);
|
|
300
|
+
|
|
301
|
+
int uuid = (int) (System.currentTimeMillis() & 0xfffffff);
|
|
302
|
+
// GETS THE FILE EXTENSION FROM PATH
|
|
303
|
+
String extension = MimeTypeMap.getFileExtensionFromUrl(destination);
|
|
304
|
+
|
|
305
|
+
String fileName = uuid + "." + extension;
|
|
306
|
+
request.setDestinationInExternalFilesDir(this.getReactApplicationContext(), null, fileName);
|
|
307
|
+
|
|
308
|
+
// TOREMOVE
|
|
309
|
+
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS.toString(), fileName);
|
|
310
|
+
// request.setDestinationUri(Uri.parse(destination));
|
|
311
|
+
|
|
237
312
|
if (headers != null) {
|
|
238
313
|
ReadableMapKeySetIterator it = headers.keySetIterator();
|
|
239
314
|
while (it.hasNextKey()) {
|
|
240
315
|
String headerKey = it.nextKey();
|
|
241
|
-
request.
|
|
316
|
+
request.addRequestHeader(headerKey, headers.getString(headerKey));
|
|
242
317
|
}
|
|
243
318
|
}
|
|
244
|
-
request.setPriority(options.hasKey("priority") ? Priority.valueOf(options.getInt("priority")) : Priority.NORMAL);
|
|
245
|
-
request.setNetworkType(options.hasKey("network") ? NetworkType.valueOf(options.getInt("network")) : NetworkType.ALL);
|
|
246
319
|
|
|
247
|
-
|
|
248
|
-
@Override
|
|
249
|
-
public void call(Request download) {
|
|
250
|
-
}
|
|
251
|
-
}, new Func<Error>() {
|
|
252
|
-
@Override
|
|
253
|
-
public void call(Error error) {
|
|
254
|
-
//An error occurred when enqueuing a request.
|
|
320
|
+
long downloadId = downloader.queueDownload(request);
|
|
255
321
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
322
|
+
synchronized (sharedLock) {
|
|
323
|
+
condigIdToDownloadId.put(id, downloadId);
|
|
324
|
+
downloadIdToConfig.put(downloadId, config);
|
|
325
|
+
saveConfigMap();
|
|
259
326
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
ee.emit("downloadFailed", params);
|
|
327
|
+
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
328
|
+
int status = downloadStatus.getInt("status");
|
|
263
329
|
|
|
264
|
-
|
|
265
|
-
fetch.remove(request.getId());
|
|
330
|
+
Log.d(getName(), "RNBD: download-1. status: " + status + " downloadId: " + downloadId);
|
|
266
331
|
|
|
267
|
-
|
|
268
|
-
|
|
332
|
+
if (config.reportedBegin) {
|
|
333
|
+
return;
|
|
269
334
|
}
|
|
270
|
-
);
|
|
271
335
|
|
|
272
|
-
|
|
273
|
-
lastProgressReport = new Date();
|
|
274
|
-
idToRequestId.put(id, request.getId());
|
|
275
|
-
requestIdToConfig.put(request.getId(), config);
|
|
336
|
+
config.reportedBegin = true;
|
|
276
337
|
saveConfigMap();
|
|
338
|
+
|
|
339
|
+
Log.d(getName(), "RNBD: download-2 downloadId: " + downloadId);
|
|
340
|
+
// report begin & progress
|
|
341
|
+
//
|
|
342
|
+
// overlaped with thread to not block main thread
|
|
343
|
+
new Thread(new Runnable() {
|
|
344
|
+
public void run() {
|
|
345
|
+
try {
|
|
346
|
+
Log.d(getName(), "RNBD: download-3 downloadId: " + downloadId);
|
|
347
|
+
|
|
348
|
+
while (true) {
|
|
349
|
+
WritableMap downloadStatus = downloader.checkDownloadStatus(downloadId);
|
|
350
|
+
int status = downloadStatus.getInt("status");
|
|
351
|
+
|
|
352
|
+
Log.d(getName(), "RNBD: download-3.1 " + status + " downloadId: " + downloadId);
|
|
353
|
+
|
|
354
|
+
if (status == DownloadManager.STATUS_RUNNING) {
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
if (status == DownloadManager.STATUS_FAILED || status == DownloadManager.STATUS_SUCCESSFUL) {
|
|
358
|
+
Log.d(getName(), "RNBD: download-3.2 " + status + " downloadId: " + downloadId);
|
|
359
|
+
Thread.currentThread().interrupt();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
Thread.sleep(500);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// EMIT BEGIN
|
|
366
|
+
OnBegin onBeginTh = new OnBegin(config, ee);
|
|
367
|
+
onBeginTh.start();
|
|
368
|
+
// wait for onBeginTh to finish
|
|
369
|
+
onBeginTh.join();
|
|
370
|
+
|
|
371
|
+
Log.d(getName(), "RNBD: download-4 downloadId: " + downloadId);
|
|
372
|
+
OnProgress onProgressTh = new OnProgress(config, downloadId, ee, downloader, progressInterval);
|
|
373
|
+
onProgressThreads.put(config.id, onProgressTh);
|
|
374
|
+
onProgressTh.start();
|
|
375
|
+
Log.d(getName(), "RNBD: download-5 downloadId: " + downloadId);
|
|
376
|
+
} catch (Exception e) {
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}).start();
|
|
380
|
+
Log.d(getName(), "RNBD: download-6 downloadId: " + downloadId);
|
|
277
381
|
}
|
|
278
382
|
}
|
|
279
383
|
|
|
384
|
+
// TODO: NOT WORKING WITH DownloadManager FOR NOW
|
|
280
385
|
@ReactMethod
|
|
281
|
-
public void pauseTask(String
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
386
|
+
public void pauseTask(String configId) {
|
|
387
|
+
Log.d(getName(), "RNBD: pauseTask " + configId);
|
|
388
|
+
|
|
389
|
+
synchronized (sharedLock) {
|
|
390
|
+
Long downloadId = condigIdToDownloadId.get(configId);
|
|
391
|
+
if (downloadId != null) {
|
|
392
|
+
downloader.pauseDownload(downloadId);
|
|
286
393
|
}
|
|
287
394
|
}
|
|
288
395
|
}
|
|
289
396
|
|
|
397
|
+
// TODO: NOT WORKING WITH DownloadManager FOR NOW
|
|
290
398
|
@ReactMethod
|
|
291
|
-
public void resumeTask(String
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
399
|
+
public void resumeTask(String configId) {
|
|
400
|
+
Log.d(getName(), "RNBD: resumeTask " + configId);
|
|
401
|
+
|
|
402
|
+
synchronized (sharedLock) {
|
|
403
|
+
Long downloadId = condigIdToDownloadId.get(configId);
|
|
404
|
+
if (downloadId != null) {
|
|
405
|
+
downloader.resumeDownload(downloadId);
|
|
296
406
|
}
|
|
297
407
|
}
|
|
298
408
|
}
|
|
299
409
|
|
|
300
410
|
@ReactMethod
|
|
301
|
-
public void stopTask(String
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
411
|
+
public void stopTask(String configId) {
|
|
412
|
+
Log.d(getName(), "RNBD: stopTask-1 " + configId);
|
|
413
|
+
|
|
414
|
+
synchronized (sharedLock) {
|
|
415
|
+
Long downloadId = condigIdToDownloadId.get(configId);
|
|
416
|
+
Log.d(getName(), "RNBD: stopTask-2 " + configId + " downloadId " + downloadId);
|
|
417
|
+
if (downloadId != null) {
|
|
418
|
+
// DELETES CONFIG HERE SO receiver WILL NOT THROW ERROR DOWNLOAD_FAILED TO THE
|
|
419
|
+
// USER
|
|
420
|
+
removeFromMaps(downloadId);
|
|
421
|
+
stopTrackingProgress(configId);
|
|
422
|
+
|
|
423
|
+
downloader.cancelDownload(downloadId);
|
|
306
424
|
}
|
|
307
425
|
}
|
|
308
426
|
}
|
|
309
427
|
|
|
310
428
|
@ReactMethod
|
|
311
|
-
public void
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
WritableMap params = Arguments.createMap();
|
|
322
|
-
params.putString("id", config.id);
|
|
323
|
-
params.putString("metadata", config.metadata);
|
|
324
|
-
params.putInt("state", stateMap.get(download.getStatus()));
|
|
325
|
-
params.putInt("bytesWritten", (int)download.getDownloaded());
|
|
326
|
-
params.putInt("totalBytes", (int)download.getTotal());
|
|
327
|
-
params.putDouble("percent", ((double)download.getProgress()) / 100);
|
|
328
|
-
|
|
329
|
-
foundIds.pushMap(params);
|
|
330
|
-
|
|
331
|
-
// TODO: MAYBE ADD headers
|
|
332
|
-
|
|
333
|
-
idToRequestId.put(config.id, download.getId());
|
|
334
|
-
config.reportedBegin = true;
|
|
335
|
-
} else {
|
|
336
|
-
fetch.delete(download.getId());
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
promise.resolve(foundIds);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Fetch API
|
|
347
|
-
@Override
|
|
348
|
-
public void onCompleted(Download download) {
|
|
349
|
-
synchronized(sharedLock) {
|
|
350
|
-
RNBGDTaskConfig config = requestIdToConfig.get(download.getId());
|
|
351
|
-
if (config != null) {
|
|
352
|
-
WritableMap params = Arguments.createMap();
|
|
353
|
-
params.putString("id", config.id);
|
|
354
|
-
params.putString("location", config.destination);
|
|
355
|
-
|
|
356
|
-
ee.emit("downloadComplete", params);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
removeFromMaps(download.getId());
|
|
360
|
-
if (!fetch.isClosed()) {
|
|
361
|
-
fetch.remove(download.getId());
|
|
429
|
+
public void completeHandler(String configId, final Promise promise) {
|
|
430
|
+
Log.d(getName(), "RNBD: completeHandler-1 " + configId);
|
|
431
|
+
|
|
432
|
+
synchronized (sharedLock) {
|
|
433
|
+
Long downloadId = condigIdToDownloadId.get(configId);
|
|
434
|
+
Log.d(getName(), "RNBD: completeHandler-2 " + configId + " downloadId " + downloadId);
|
|
435
|
+
if (downloadId != null) {
|
|
436
|
+
removeFromMaps(downloadId);
|
|
437
|
+
// REMOVES DOWNLOAD FROM DownloadManager SO IT WOULD NOT BE RETURNED IN checkForExistingDownloads
|
|
438
|
+
downloader.cancelDownload(downloadId);
|
|
362
439
|
}
|
|
363
440
|
}
|
|
364
441
|
}
|
|
365
442
|
|
|
366
|
-
@
|
|
367
|
-
public void
|
|
368
|
-
|
|
369
|
-
RNBGDTaskConfig config = requestIdToConfig.get(download.getId());
|
|
370
|
-
if (config == null) {
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
WritableMap params = Arguments.createMap();
|
|
375
|
-
params.putString("id", config.id);
|
|
376
|
-
|
|
377
|
-
if (!config.reportedBegin) {
|
|
378
|
-
config.reportedBegin = true;
|
|
379
|
-
|
|
380
|
-
params.putInt("expectedBytes", (int)download.getTotal());
|
|
443
|
+
@ReactMethod
|
|
444
|
+
public void checkForExistingDownloads(final Promise promise) {
|
|
445
|
+
Log.d(getName(), "RNBD: checkForExistingDownloads-1");
|
|
381
446
|
|
|
382
|
-
|
|
383
|
-
// https://github.com/tonyofrancis/Fetch/issues/347#issuecomment-478349299
|
|
384
|
-
Thread th = new Thread(() -> {
|
|
385
|
-
try {
|
|
386
|
-
WritableMap headersMap = Arguments.createMap();
|
|
447
|
+
WritableArray foundIds = Arguments.createArray();
|
|
387
448
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
for (String key : keys) {
|
|
393
|
-
String val = con.getHeaderField(key);
|
|
394
|
-
headersMap.putString(key, val);
|
|
395
|
-
}
|
|
396
|
-
params.putMap("headers", headersMap);
|
|
397
|
-
|
|
398
|
-
ee.emit("downloadBegin", params);
|
|
399
|
-
} catch (IOException e) {
|
|
400
|
-
e.printStackTrace();
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
new Thread(new Runnable() {
|
|
404
|
-
public void run() {
|
|
405
|
-
try {
|
|
406
|
-
th.start();
|
|
407
|
-
th.join();
|
|
408
|
-
} catch (InterruptedException e) {
|
|
409
|
-
e.printStackTrace();
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}).start();
|
|
413
|
-
} else {
|
|
414
|
-
params.putInt("written", (int)download.getDownloaded());
|
|
415
|
-
params.putInt("total", (int)download.getTotal());
|
|
416
|
-
params.putDouble("percent", ((double)download.getProgress()) / 100);
|
|
417
|
-
progressReports.put(config.id, params);
|
|
418
|
-
Date now = new Date();
|
|
419
|
-
if (now.getTime() - lastProgressReport.getTime() > 250) {
|
|
420
|
-
WritableArray reportsArray = Arguments.createArray();
|
|
421
|
-
for (WritableMap report : progressReports.values()) {
|
|
422
|
-
reportsArray.pushMap(report);
|
|
423
|
-
}
|
|
424
|
-
ee.emit("downloadProgress", reportsArray);
|
|
425
|
-
lastProgressReport = now;
|
|
426
|
-
progressReports.clear();
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
449
|
+
synchronized (sharedLock) {
|
|
450
|
+
try {
|
|
451
|
+
DownloadManager.Query downloadQuery = new DownloadManager.Query();
|
|
452
|
+
Cursor cursor = downloader.downloadManager.query(downloadQuery);
|
|
431
453
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
454
|
+
if (cursor.moveToFirst()) {
|
|
455
|
+
do {
|
|
456
|
+
WritableMap result = downloader.getDownloadStatus(cursor);
|
|
457
|
+
Long downloadId = Long.parseLong(result.getString("downloadId"));
|
|
435
458
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
459
|
+
if (downloadIdToConfig.containsKey(downloadId)) {
|
|
460
|
+
Log.d(getName(), "RNBD: checkForExistingDownloads-2");
|
|
461
|
+
RNBGDTaskConfig config = downloadIdToConfig.get(downloadId);
|
|
462
|
+
WritableMap params = Arguments.createMap();
|
|
463
|
+
params.putString("id", config.id);
|
|
464
|
+
params.putString("metadata", config.metadata);
|
|
465
|
+
params.putInt("state", stateMap.get(result.getInt("status")));
|
|
439
466
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
synchronized(sharedLock) {
|
|
443
|
-
removeFromMaps(download.getId());
|
|
444
|
-
fetch.delete(download.getId());
|
|
445
|
-
}
|
|
446
|
-
}
|
|
467
|
+
int bytesDownloaded = result.getInt("bytesDownloaded");
|
|
468
|
+
params.putInt("bytesDownloaded", bytesDownloaded);
|
|
447
469
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
470
|
+
int bytesTotal = result.getInt("bytesTotal");
|
|
471
|
+
params.putInt("bytesTotal", bytesTotal);
|
|
451
472
|
|
|
452
|
-
|
|
453
|
-
public void onDeleted(Download download) {
|
|
454
|
-
}
|
|
473
|
+
params.putDouble("percent", ((double) bytesDownloaded / bytesTotal));
|
|
455
474
|
|
|
456
|
-
|
|
457
|
-
public void onAdded(Download download) {
|
|
458
|
-
}
|
|
475
|
+
foundIds.pushMap(params);
|
|
459
476
|
|
|
460
|
-
|
|
461
|
-
public void onQueued(Download download, boolean b) {
|
|
462
|
-
}
|
|
477
|
+
// TODO: MAYBE ADD headers
|
|
463
478
|
|
|
464
|
-
|
|
465
|
-
public void onWaitingNetwork(Download download) {
|
|
466
|
-
}
|
|
479
|
+
condigIdToDownloadId.put(config.id, downloadId);
|
|
467
480
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
params.putString("id", config.id);
|
|
476
|
-
|
|
477
|
-
int convertedErrCode = convertErrorCode(error);
|
|
478
|
-
params.putInt("errorcode", convertedErrCode);
|
|
479
|
-
|
|
480
|
-
if (error == Error.UNKNOWN && throwable != null) {
|
|
481
|
-
params.putString("error", throwable.getLocalizedMessage());
|
|
482
|
-
Log.e(getName(), "UNKNOWN Error in download: " + throwable.getLocalizedMessage());
|
|
483
|
-
} else {
|
|
484
|
-
params.putString("error", error.toString());
|
|
485
|
-
Log.e(getName(), "Error in download: " + error.toString() + ":" + error.getValue());
|
|
481
|
+
// TOREMOVE
|
|
482
|
+
// config.reportedBegin = true;
|
|
483
|
+
} else {
|
|
484
|
+
Log.d(getName(), "RNBD: checkForExistingDownloads-3");
|
|
485
|
+
downloader.cancelDownload(downloadId);
|
|
486
|
+
}
|
|
487
|
+
} while (cursor.moveToNext());
|
|
486
488
|
}
|
|
487
|
-
ee.emit("downloadFailed", params);
|
|
488
|
-
}
|
|
489
489
|
|
|
490
|
-
|
|
491
|
-
|
|
490
|
+
cursor.close();
|
|
491
|
+
} catch (Exception e) {
|
|
492
|
+
Log.e(getName(), "Error in checkForExistingDownloads: " + e.getLocalizedMessage());
|
|
493
|
+
}
|
|
492
494
|
}
|
|
493
|
-
}
|
|
494
495
|
|
|
495
|
-
|
|
496
|
-
public void onDownloadBlockUpdated(Download download, DownloadBlock downloadBlock, int i) {
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
@Override
|
|
500
|
-
public void onStarted(Download download, List<? extends DownloadBlock> list, int i) {
|
|
496
|
+
promise.resolve(foundIds);
|
|
501
497
|
}
|
|
502
498
|
}
|