@ammarahmed/react-native-upload 6.16.0 → 6.17.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.
@@ -0,0 +1,384 @@
1
+ package com.appfolio.uploader
2
+
3
+ import android.app.Application
4
+ import android.app.NotificationChannel
5
+ import android.app.NotificationManager
6
+ import android.content.Context
7
+ import android.os.Build
8
+ import android.util.Log
9
+ import android.webkit.MimeTypeMap
10
+ import androidx.work.WorkInfo
11
+ import androidx.work.WorkManager
12
+ import com.appfolio.work.UploadManager
13
+ import com.appfolio.work.UploadWorker
14
+ import com.facebook.react.BuildConfig
15
+ import com.facebook.react.bridge.*
16
+ import net.gotev.uploadservice.UploadServiceConfig.httpStack
17
+ import net.gotev.uploadservice.UploadServiceConfig.initialize
18
+ import net.gotev.uploadservice.data.UploadNotificationConfig
19
+ import net.gotev.uploadservice.data.UploadNotificationStatusConfig
20
+ import net.gotev.uploadservice.observer.request.GlobalRequestObserver
21
+ import net.gotev.uploadservice.okhttp.OkHttpStack
22
+ import okhttp3.OkHttpClient
23
+ import java.io.File
24
+ import java.util.concurrent.TimeUnit
25
+
26
+ class UploaderModule(val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
27
+ private val TAG = "UploaderBridge"
28
+ private var notificationChannelID = "BackgroundUploadChannel"
29
+ private var isGlobalRequestObserver = false
30
+ private var limitNetwork = false
31
+
32
+ override fun getName(): String {
33
+ return "RNFileUploader"
34
+ }
35
+
36
+ /*
37
+ Sets uploading network limit to unmetered network.
38
+ */
39
+ @ReactMethod
40
+ fun shouldLimitNetwork(limit: Boolean) {
41
+ limitNetwork = limit;
42
+ }
43
+
44
+ /*
45
+ Gets file information for the path specified. Example valid path is: /storage/extSdCard/DCIM/Camera/20161116_074726.mp4
46
+ Returns an object such as: {extension: "mp4", size: "3804316", exists: true, mimeType: "video/mp4", name: "20161116_074726.mp4"}
47
+ */
48
+ @ReactMethod
49
+ fun getFileInfo(path: String?, promise: Promise) {
50
+ try {
51
+ val params = Arguments.createMap()
52
+ val fileInfo = File(path)
53
+ params.putString("name", fileInfo.name)
54
+ if (!fileInfo.exists() || !fileInfo.isFile) {
55
+ params.putBoolean("exists", false)
56
+ } else {
57
+ params.putBoolean("exists", true)
58
+ params.putString("size", fileInfo.length().toString()) //use string form of long because there is no putLong and converting to int results in a max size of 17.2 gb, which could happen. Javascript will need to convert it to a number
59
+ val extension = MimeTypeMap.getFileExtensionFromUrl(path)
60
+ params.putString("extension", extension)
61
+ val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase())
62
+ params.putString("mimeType", mimeType)
63
+ }
64
+ promise.resolve(params)
65
+ } catch (exc: Exception) {
66
+ exc.printStackTrace()
67
+ Log.e(TAG, exc.message, exc)
68
+ promise.reject(exc)
69
+ }
70
+ }
71
+
72
+ private fun configureUploadServiceHTTPStack(options: ReadableMap, promise: Promise) {
73
+ var followRedirects = true
74
+ var followSslRedirects = true
75
+ var retryOnConnectionFailure = true
76
+ var connectTimeout = 45
77
+ var writeTimeout = 90
78
+ var readTimeout = 90
79
+ //TODO: make 'cache' customizable
80
+ if (options.hasKey("followRedirects")) {
81
+ if (options.getType("followRedirects") != ReadableType.Boolean) {
82
+ promise.reject(IllegalArgumentException("followRedirects must be a boolean."))
83
+ return
84
+ }
85
+ followRedirects = options.getBoolean("followRedirects")
86
+ }
87
+ if (options.hasKey("followSslRedirects")) {
88
+ if (options.getType("followSslRedirects") != ReadableType.Boolean) {
89
+ promise.reject(IllegalArgumentException("followSslRedirects must be a boolean."))
90
+ return
91
+ }
92
+ followSslRedirects = options.getBoolean("followSslRedirects")
93
+ }
94
+ if (options.hasKey("retryOnConnectionFailure")) {
95
+ if (options.getType("retryOnConnectionFailure") != ReadableType.Boolean) {
96
+ promise.reject(IllegalArgumentException("retryOnConnectionFailure must be a boolean."))
97
+ return
98
+ }
99
+ retryOnConnectionFailure = options.getBoolean("retryOnConnectionFailure")
100
+ }
101
+ if (options.hasKey("connectTimeout")) {
102
+ if (options.getType("connectTimeout") != ReadableType.Number) {
103
+ promise.reject(IllegalArgumentException("connectTimeout must be a number."))
104
+ return
105
+ }
106
+ connectTimeout = options.getInt("connectTimeout")
107
+ }
108
+ if (options.hasKey("writeTimeout")) {
109
+ if (options.getType("writeTimeout") != ReadableType.Number) {
110
+ promise.reject(IllegalArgumentException("writeTimeout must be a number."))
111
+ return
112
+ }
113
+ writeTimeout = options.getInt("writeTimeout")
114
+ }
115
+ if (options.hasKey("readTimeout")) {
116
+ if (options.getType("readTimeout") != ReadableType.Number) {
117
+ promise.reject(IllegalArgumentException("readTimeout must be a number."))
118
+ return
119
+ }
120
+ readTimeout = options.getInt("readTimeout")
121
+ }
122
+ httpStack = OkHttpStack(OkHttpClient().newBuilder()
123
+ .followRedirects(followRedirects)
124
+ .followSslRedirects(followSslRedirects)
125
+ .retryOnConnectionFailure(retryOnConnectionFailure)
126
+ .connectTimeout(connectTimeout.toLong(), TimeUnit.SECONDS)
127
+ .writeTimeout(writeTimeout.toLong(), TimeUnit.SECONDS)
128
+ .readTimeout(readTimeout.toLong(), TimeUnit.SECONDS)
129
+ .cache(null)
130
+ .build())
131
+ }
132
+
133
+ /*
134
+ * Starts a file upload.
135
+ * Returns a promise with the string ID of the upload.
136
+ */
137
+ @ReactMethod
138
+ fun startUpload(options: ReadableMap, promise: Promise) {
139
+ for (key in arrayOf("url", "path")) {
140
+ if (!options.hasKey(key)) {
141
+ promise.reject(java.lang.IllegalArgumentException("Missing '$key' field."))
142
+ return
143
+ }
144
+ if (options.getType(key) != ReadableType.String) {
145
+ promise.reject(java.lang.IllegalArgumentException("$key must be a string."))
146
+ return
147
+ }
148
+ }
149
+ if (options.hasKey("headers") && options.getType("headers") != ReadableType.Map) {
150
+ promise.reject(java.lang.IllegalArgumentException("headers must be a hash."))
151
+ return
152
+ }
153
+ if (options.hasKey("notification") && options.getType("notification") != ReadableType.Map) {
154
+ promise.reject(java.lang.IllegalArgumentException("notification must be a hash."))
155
+ return
156
+ }
157
+ configureUploadServiceHTTPStack(options, promise)
158
+ var requestType: String? = "raw"
159
+ if (options.hasKey("type")) {
160
+ requestType = options.getString("type")
161
+ if (requestType == null) {
162
+ promise.reject(java.lang.IllegalArgumentException("type must be string."))
163
+ return
164
+ }
165
+ if (requestType != "raw" && requestType != "multipart") {
166
+ promise.reject(java.lang.IllegalArgumentException("type should be string: raw or multipart."))
167
+ return
168
+ }
169
+ }
170
+ val notification: WritableMap = WritableNativeMap()
171
+ notification.putBoolean("enabled", true)
172
+ if (options.hasKey("notification")) {
173
+ notification.merge(options.getMap("notification")!!)
174
+ }
175
+
176
+ val application = reactContext.applicationContext as Application
177
+
178
+ reactContext.addLifecycleEventListener(this)
179
+
180
+ if (notification.hasKey("notificationChannel")) {
181
+ notificationChannelID = notification.getString("notificationChannel")!!
182
+ }
183
+
184
+ createNotificationChannel()
185
+
186
+ initialize(application, notificationChannelID, BuildConfig.DEBUG)
187
+
188
+ if(!isGlobalRequestObserver) {
189
+ isGlobalRequestObserver = true
190
+ GlobalRequestObserver(application, GlobalRequestObserverDelegate(reactContext))
191
+ }
192
+
193
+ val url = options.getString("url")
194
+ val filePath = options.getString("path")
195
+ val method = if (options.hasKey("method") && options.getType("method") == ReadableType.String) options.getString("method") else "POST"
196
+ val maxRetries = if (options.hasKey("maxRetries") && options.getType("maxRetries") == ReadableType.Number) options.getInt("maxRetries") else 2
197
+ val customUploadId = if (options.hasKey("customUploadId") && options.getType("method") == ReadableType.String) options.getString("customUploadId") else null
198
+ try {
199
+ val request = if (requestType == "raw") {
200
+ ModifiedBinaryUploadRequest(this.reactApplicationContext, url!!, limitNetwork)
201
+ .setFileToUpload(filePath!!)
202
+ } else {
203
+ if (!options.hasKey("field")) {
204
+ promise.reject(java.lang.IllegalArgumentException("field is required field for multipart type."))
205
+ return
206
+ }
207
+ if (options.getType("field") != ReadableType.String) {
208
+ promise.reject(java.lang.IllegalArgumentException("field must be string."))
209
+ return
210
+ }
211
+ ModifiedMultipartUploadRequest(this.reactApplicationContext, url!!, limitNetwork)
212
+ .addFileToUpload(filePath!!, options.getString("field")!!)
213
+ }
214
+ request.setMethod(method!!)
215
+ .setMaxRetries(maxRetries)
216
+ if (notification.getBoolean("enabled")) {
217
+ val notificationConfig = UploadNotificationConfig(
218
+ notificationChannelId = notificationChannelID,
219
+ isRingToneEnabled = notification.hasKey("enableRingTone") && notification.getBoolean("enableRingTone"),
220
+ progress = UploadNotificationStatusConfig(
221
+ title = if (notification.hasKey("onProgressTitle")) notification.getString("onProgressTitle")!! else "",
222
+ message = if (notification.hasKey("onProgressMessage")) notification.getString("onProgressMessage")!! else ""
223
+ ),
224
+ success = UploadNotificationStatusConfig(
225
+ title = if (notification.hasKey("onCompleteTitle")) notification.getString("onCompleteTitle")!! else "",
226
+ message = if (notification.hasKey("onCompleteMessage")) notification.getString("onCompleteMessage")!! else "",
227
+ autoClear = notification.hasKey("autoClear") && notification.getBoolean("autoClear")
228
+ ),
229
+ error = UploadNotificationStatusConfig(
230
+ title = if (notification.hasKey("onErrorTitle")) notification.getString("onErrorTitle")!! else "",
231
+ message = if (notification.hasKey("onErrorMessage")) notification.getString("onErrorMessage")!! else ""
232
+ ),
233
+ cancelled = UploadNotificationStatusConfig(
234
+ title = if (notification.hasKey("onCancelledTitle")) notification.getString("onCancelledTitle")!! else "",
235
+ message = if (notification.hasKey("onCancelledMessage")) notification.getString("onCancelledMessage")!! else ""
236
+ )
237
+ )
238
+ request.setNotificationConfig { _, _ ->
239
+ notificationConfig
240
+ }
241
+ }
242
+ if (options.hasKey("parameters")) {
243
+ if (requestType == "raw") {
244
+ promise.reject(java.lang.IllegalArgumentException("Parameters supported only in multipart type"))
245
+ return
246
+ }
247
+ val parameters = options.getMap("parameters")
248
+ val keys = parameters!!.keySetIterator()
249
+ while (keys.hasNextKey()) {
250
+ val key = keys.nextKey()
251
+ if (parameters.getType(key) != ReadableType.String) {
252
+ promise.reject(java.lang.IllegalArgumentException("Parameters must be string key/values. Value was invalid for '$key'"))
253
+ return
254
+ }
255
+ request.addParameter(key, parameters.getString(key)!!)
256
+ }
257
+ }
258
+ if (options.hasKey("headers")) {
259
+ val headers = options.getMap("headers")
260
+ val keys = headers!!.keySetIterator()
261
+ while (keys.hasNextKey()) {
262
+ val key = keys.nextKey()
263
+ if (headers.getType(key) != ReadableType.String) {
264
+ promise.reject(java.lang.IllegalArgumentException("Headers must be string key/values. Value was invalid for '$key'"))
265
+ return
266
+ }
267
+ request.addHeader(key, headers.getString(key)!!)
268
+ }
269
+ }
270
+ if (customUploadId != null)
271
+ request.setCustomUploadID(customUploadId)
272
+
273
+ val uploadId = request.startUpload()
274
+ promise.resolve(uploadId)
275
+ } catch (exc: java.lang.Exception) {
276
+ exc.printStackTrace()
277
+ Log.e(TAG, exc.message, exc)
278
+ promise.reject(exc)
279
+ }
280
+ }
281
+
282
+ /*
283
+ * Cancels file upload
284
+ * Accepts upload ID as a first argument, this upload will be cancelled
285
+ * Event "cancelled" will be fired when upload is cancelled.
286
+ */
287
+ @ReactMethod
288
+ fun cancelUpload(cancelUploadId: String?, promise: Promise) {
289
+ if (cancelUploadId !is String) {
290
+ promise.reject(java.lang.IllegalArgumentException("Upload ID must be a string"))
291
+ return
292
+ }
293
+ try {
294
+ UploadManager.stopUpload(cancelUploadId)
295
+ promise.resolve(true)
296
+ } catch (exc: java.lang.Exception) {
297
+ exc.printStackTrace()
298
+ Log.e(TAG, exc.message, exc)
299
+ promise.reject(exc)
300
+ }
301
+ }
302
+
303
+ /*
304
+ * Cancels all file uploads
305
+ */
306
+ @ReactMethod
307
+ fun stopAllUploads(promise: Promise) {
308
+ try {
309
+ UploadManager.stopAllUploads()
310
+ promise.resolve(true)
311
+ } catch (exc: java.lang.Exception) {
312
+ exc.printStackTrace()
313
+ Log.e(TAG, exc.message, exc)
314
+ promise.reject(exc)
315
+ }
316
+ }
317
+
318
+ /*
319
+ * Gets all file uploads with their state
320
+ */
321
+ @ReactMethod
322
+ fun getAllUploads(promise: Promise) {
323
+ val workManager: WorkManager = WorkManager.getInstance(reactContext)
324
+ val workInfos = workManager.getWorkInfosByTag(UploadWorker::class.java.name).get()
325
+ val uploads = Arguments.createArray()
326
+
327
+ for (info in workInfos) {
328
+ // Ignore 'SUCCEEDED' state from WorkManager since that only means that the uploads have started
329
+ if (info.state === WorkInfo.State.SUCCEEDED) {
330
+ continue
331
+ }
332
+
333
+ val upload = Arguments.createMap()
334
+
335
+ val idTag = info.tags.toTypedArray().find { it.startsWith(UploadWorker::class.java.simpleName) }
336
+ upload.putString("id", idTag?.removePrefix("${UploadWorker::class.java.simpleName}-"))
337
+
338
+ when(info.state) {
339
+ WorkInfo.State.RUNNING ->
340
+ upload.putString("state", "running")
341
+ WorkInfo.State.CANCELLED, WorkInfo.State.FAILED ->
342
+ upload.putString("state", "cancelled")
343
+ WorkInfo.State.BLOCKED, WorkInfo.State.ENQUEUED ->
344
+ upload.putString("state", "pending")
345
+ else ->
346
+ continue
347
+ }
348
+
349
+ uploads.pushMap(upload)
350
+ }
351
+
352
+ val uploadTaskList = UploadManager.taskList
353
+ for (task in uploadTaskList) {
354
+ val upload = Arguments.createMap()
355
+ upload.putString("id", task)
356
+ upload.putString("state", "running")
357
+ uploads.pushMap(upload)
358
+ }
359
+
360
+ promise.resolve(uploads)
361
+ }
362
+
363
+ // Customize the notification channel as you wish. This is only for a bare minimum example
364
+ private fun createNotificationChannel() {
365
+ if (Build.VERSION.SDK_INT >= 26) {
366
+ val channel = NotificationChannel(
367
+ notificationChannelID,
368
+ "Background Upload Channel",
369
+ NotificationManager.IMPORTANCE_LOW
370
+ )
371
+ val manager = reactApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
372
+ manager.createNotificationChannel(channel)
373
+ }
374
+ }
375
+
376
+ override fun onHostResume() {
377
+ }
378
+
379
+ override fun onHostPause() {
380
+ }
381
+
382
+ override fun onHostDestroy() {
383
+ }
384
+ }
@@ -0,0 +1,32 @@
1
+ package com.appfolio.uploader;
2
+
3
+ import com.facebook.react.ReactPackage;
4
+ import com.facebook.react.bridge.JavaScriptModule;
5
+ import com.facebook.react.bridge.NativeModule;
6
+ import com.facebook.react.bridge.ReactApplicationContext;
7
+ import com.facebook.react.uimanager.ViewManager;
8
+
9
+ import java.util.ArrayList;
10
+ import java.util.Collections;
11
+ import java.util.List;
12
+
13
+ public class UploaderReactPackage implements ReactPackage {
14
+
15
+ // Deprecated in RN 0.47, @todo remove after < 0.47 support remove
16
+ public List<Class<? extends JavaScriptModule>> createJSModules() {
17
+ return Collections.emptyList();
18
+ }
19
+
20
+ @Override
21
+ public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
22
+ return Collections.emptyList();
23
+ }
24
+
25
+ @Override
26
+ public List<NativeModule> createNativeModules(
27
+ ReactApplicationContext reactContext) {
28
+ List<NativeModule> modules = new ArrayList<>();
29
+ modules.add(new UploaderModule(reactContext));
30
+ return modules;
31
+ }
32
+ }
@@ -0,0 +1,47 @@
1
+ package com.appfolio.work
2
+
3
+ import net.gotev.uploadservice.data.UploadInfo
4
+ import net.gotev.uploadservice.data.UploadNotificationConfig
5
+ import net.gotev.uploadservice.network.ServerResponse
6
+ import net.gotev.uploadservice.observer.task.UploadTaskObserver
7
+
8
+ class TaskCompletionNotifier : UploadTaskObserver {
9
+ override fun onStart(
10
+ info: UploadInfo,
11
+ notificationId: Int,
12
+ notificationConfig: UploadNotificationConfig
13
+ ) {
14
+ }
15
+
16
+ override fun onProgress(
17
+ info: UploadInfo,
18
+ notificationId: Int,
19
+ notificationConfig: UploadNotificationConfig
20
+ ) {
21
+ }
22
+
23
+ override fun onSuccess(
24
+ info: UploadInfo,
25
+ notificationId: Int,
26
+ notificationConfig: UploadNotificationConfig,
27
+ response: ServerResponse
28
+ ) {
29
+ }
30
+
31
+ override fun onError(
32
+ info: UploadInfo,
33
+ notificationId: Int,
34
+ notificationConfig: UploadNotificationConfig,
35
+ exception: Throwable
36
+ ) {
37
+ UploadManager.taskFailed(info.uploadId)
38
+ }
39
+
40
+ override fun onCompleted(
41
+ info: UploadInfo,
42
+ notificationId: Int,
43
+ notificationConfig: UploadNotificationConfig
44
+ ) {
45
+ UploadManager.taskCompleted(info.uploadId)
46
+ }
47
+ }
@@ -0,0 +1,109 @@
1
+ package com.appfolio.work
2
+
3
+ import android.content.Context
4
+ import com.appfolio.extensions.UploadTaskCreationParameters
5
+ import com.appfolio.extensions.getUploadTask
6
+ import net.gotev.uploadservice.UploadTask
7
+ import net.gotev.uploadservice.data.UploadNotificationConfig
8
+ import net.gotev.uploadservice.data.UploadTaskParameters
9
+ import net.gotev.uploadservice.logger.UploadServiceLogger
10
+ import java.util.concurrent.*
11
+
12
+ class UploadManager {
13
+
14
+ companion object {
15
+ /**
16
+ * Sets the Thread Pool to use for upload operations.
17
+ * By default a thread pool with size equal to the number of processors is created.
18
+ */
19
+ @JvmStatic
20
+ var threadPool: AbstractExecutorService = ThreadPoolExecutor(
21
+ Runtime.getRuntime().availableProcessors(), // Initial pool size
22
+ Runtime.getRuntime().availableProcessors(), // Max pool size
23
+ 5.toLong(), // Keep Alive Time
24
+ TimeUnit.SECONDS,
25
+ LinkedBlockingQueue<Runnable>()
26
+ )
27
+
28
+ val TAG: String = UploadManager::class.java.simpleName
29
+
30
+ private const val UPLOAD_NOTIFICATION_BASE_ID = 1234 // Something unique
31
+
32
+ private var notificationIncrementalId = 0
33
+ private val uploadTasksMap = ConcurrentHashMap<String, UploadTask>()
34
+
35
+ /**
36
+ * Stops the upload task with the given uploadId.
37
+ * @param uploadId The unique upload id
38
+ */
39
+ @Synchronized
40
+ @JvmStatic
41
+ fun stopUpload(uploadId: String) {
42
+ uploadTasksMap[uploadId]?.cancel()
43
+ }
44
+
45
+ /**
46
+ * Gets the list of the currently active upload tasks.
47
+ * @return list of uploadIDs or an empty list if no tasks are currently running
48
+ */
49
+ @JvmStatic
50
+ val taskList: List<String>
51
+ @Synchronized get() = if (uploadTasksMap.isEmpty()) {
52
+ emptyList()
53
+ } else {
54
+ uploadTasksMap.keys().toList()
55
+ }
56
+
57
+ /**
58
+ * Stop all the active uploads.
59
+ */
60
+ @Synchronized
61
+ @JvmStatic
62
+ fun stopAllUploads() {
63
+ val iterator = uploadTasksMap.keys.iterator()
64
+
65
+ while (iterator.hasNext()) {
66
+ uploadTasksMap[iterator.next()]?.cancel()
67
+ }
68
+ }
69
+
70
+ fun startUpload(context: Context, params: UploadTaskParameters, notificationConfig: UploadNotificationConfig) {
71
+ val taskCreationParameters = UploadTaskCreationParameters(params, notificationConfig)
72
+
73
+ if (uploadTasksMap.containsKey(taskCreationParameters.params.id)) {
74
+ UploadServiceLogger.error(TAG, taskCreationParameters.params.id) {
75
+ "Preventing upload! An upload with the same ID is already in progress. " +
76
+ "Every upload must have unique ID. Please check your code and fix it!"
77
+ }
78
+ return
79
+ }
80
+
81
+ val currentTask = context.getUploadTask(
82
+ creationParameters = taskCreationParameters,
83
+ notificationId = UPLOAD_NOTIFICATION_BASE_ID + notificationIncrementalId,
84
+ ) ?: return
85
+
86
+ uploadTasksMap[currentTask.params.id] = currentTask
87
+ threadPool.execute(currentTask)
88
+ }
89
+
90
+ /**
91
+ * Called by each task when it errors out.
92
+ * @param uploadId the uploadID of the task with error
93
+ */
94
+ @Synchronized
95
+ fun taskFailed(uploadId: String) {
96
+ uploadTasksMap.remove(uploadId)
97
+ }
98
+
99
+ /**
100
+ * Called by each task when it is completed (either successfully, with an error or due to
101
+ * user cancellation).
102
+ * @param uploadId the uploadID of the finished task
103
+ */
104
+ @Synchronized
105
+ fun taskCompleted(uploadId: String) {
106
+ uploadTasksMap.remove(uploadId)
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,20 @@
1
+ package com.appfolio.work
2
+
3
+ import android.content.Context
4
+ import androidx.work.Worker
5
+ import androidx.work.WorkerParameters
6
+ import com.appfolio.extensions.PARAM_KEY_NOTIF_CONFIG
7
+ import com.appfolio.extensions.PARAM_KEY_TASK_PARAMS
8
+ import com.appfolio.extensions.toUploadNotificationConfig
9
+ import com.appfolio.extensions.toUploadTaskParameters
10
+
11
+ class UploadWorker(val context: Context, params: WorkerParameters): Worker(context, params) {
12
+
13
+ override fun doWork(): Result {
14
+ val taskParamsStr = inputData.getString(PARAM_KEY_TASK_PARAMS) ?: return Result.failure()
15
+ val notifConfigStr = inputData.getString(PARAM_KEY_NOTIF_CONFIG) ?: return Result.failure()
16
+
17
+ UploadManager.startUpload(context, taskParamsStr.toUploadTaskParameters(), notifConfigStr.toUploadNotificationConfig())
18
+ return Result.success()
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ammarahmed/react-native-upload",
3
- "version": "6.16.0",
3
+ "version": "6.17.0",
4
4
  "description": "Cross platform http post file uploader with Android and iOS background support.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",