1414import androidx .work .ExistingWorkPolicy ;
1515import androidx .work .NetworkType ;
1616import androidx .work .OneTimeWorkRequest ;
17+ import androidx .work .OutOfQuotaPolicy ;
1718import androidx .work .WorkInfo ;
1819import androidx .work .WorkManager ;
1920import androidx .work .WorkQuery ;
3738import java .util .Map ;
3839import java .util .UUID ;
3940import java .util .concurrent .ExecutionException ;
41+ import java .util .concurrent .Executors ;
42+ import java .util .concurrent .ScheduledExecutorService ;
4043import java .util .concurrent .TimeUnit ;
4144
4245public class FileTransferBackground extends CordovaPlugin {
@@ -52,6 +55,8 @@ public class FileTransferBackground extends CordovaPlugin {
5255 private static String currentTag ;
5356 private static long currentTagFetchedAt ;
5457
58+ private ScheduledExecutorService executorService = null ;
59+
5560 public void sendCallback (JSONObject obj ) {
5661 /* we check the webview has been initialized */
5762 if (ready ) {
@@ -116,7 +121,11 @@ private void sendError(final String id, final String reason, boolean userCancele
116121
117122 @ Override
118123 public boolean execute (String action , JSONArray args , final CallbackContext callbackContext ) {
119- cordova .getThreadPool ().execute (() -> {
124+ if (executorService == null ) {
125+ executorService = Executors .newScheduledThreadPool (4 );
126+ }
127+
128+ executorService .schedule (() -> {
120129 try {
121130 switch (action ) {
122131 case "initManager" :
@@ -142,7 +151,7 @@ public boolean execute(String action, JSONArray args, final CallbackContext call
142151 callbackContext .sendPluginResult (result );
143152 exception .printStackTrace ();
144153 }
145- });
154+ } , 0 , TimeUnit . MILLISECONDS );
146155
147156 return true ;
148157 }
@@ -181,8 +190,12 @@ private void initManager(String options, final CallbackContext callbackContext)
181190 .uploadEventDao ()
182191 .getAll ();
183192
193+ int ackDelay = 0 ;
184194 for (UploadEvent ack : uploadEvents ) {
185- handleAck (ack .getOutputData ());
195+ executorService .schedule (() -> {
196+ handleAck (ack .getOutputData ());
197+ }, ackDelay , TimeUnit .MILLISECONDS );
198+ ackDelay += 200 ;
186199 }
187200
188201 // Can't use observeForever anywhere else than the main thread
@@ -208,15 +221,15 @@ private void initManager(String options, final CallbackContext callbackContext)
208221 case BLOCKED :
209222 case ENQUEUED :
210223 case SUCCEEDED :
211- completedTasks = completedTasks + 1 ;
224+ completedTasks ++ ;
212225 // No db in main thread
213- cordova . getThreadPool (). execute (() -> {
226+ executorService . schedule (() -> {
214227 // The corresponding ACK is already in the DB, if it not, the task is just a leftover
215228 String id = info .getOutputData ().getString (UploadTask .KEY_OUTPUT_ID );
216229 if (ackDatabase .uploadEventDao ().exists (id )) {
217230 handleAck (info .getOutputData ());
218231 }
219- });
232+ }, 0 , TimeUnit . MILLISECONDS );
220233 break ;
221234 case FAILED :
222235 // The task can't fail completely so something really bad has happened.
@@ -319,7 +332,7 @@ private void addUpload(JSONObject jsonPayload) {
319332 private void startUpload (final String uploadId , final Data payload ) {
320333 Log .d (TAG , "startUpload: Starting work via work manager" );
321334
322- OneTimeWorkRequest workRequest = new OneTimeWorkRequest .Builder (UploadTask .class )
335+ OneTimeWorkRequest . Builder workRequestBuilder = new OneTimeWorkRequest .Builder (UploadTask .class )
323336 .setConstraints (new Constraints .Builder ()
324337 .setRequiredNetworkType (NetworkType .CONNECTED )
325338 .build ()
@@ -328,8 +341,13 @@ private void startUpload(final String uploadId, final Data payload) {
328341 .setBackoffCriteria (BackoffPolicy .LINEAR , 30 , TimeUnit .SECONDS )
329342 .addTag (FileTransferBackground .WORK_TAG_UPLOAD )
330343 .addTag (getCurrentTag (cordova .getContext ()))
331- .setInputData (payload )
332- .build ();
344+ .setInputData (payload );
345+
346+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
347+ workRequestBuilder .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST );
348+ }
349+
350+ OneTimeWorkRequest workRequest = workRequestBuilder .build ();
333351
334352 WorkManager .getInstance (cordova .getContext ())
335353 .enqueueUniqueWork (uploadId , ExistingWorkPolicy .APPEND , workRequest );
@@ -365,7 +383,7 @@ private void removeUpload(String uploadId, CallbackContext context) {
365383 PluginResult result = new PluginResult (PluginResult .Status .OK );
366384 result .setKeepCallback (true );
367385 context .sendPluginResult (result );
368- }, cordova . getThreadPool () );
386+ }, executorService );
369387 }
370388
371389 private void acknowledgeEvent (String eventId , CallbackContext context ) {
0 commit comments