From fca668d87ea8052ab92d3b964ecc83bc9555bfa3 Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 27 Apr 2023 16:40:50 +0400 Subject: [PATCH 01/22] Add Conflict Rules --- src/android/FileTransferBackground.java | 3 ++- src/android/PendingUploadDao.java | 16 ++++++++++++---- src/android/UploadTask.java | 22 +--------------------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index bdd82da4..d89ad5ce 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -226,6 +226,7 @@ private void initManager(String options, final CallbackContext callbackContext) case SUCCEEDED: logMessage("Task succeeded: " + info.getId()); completedTasks++; + break; case FAILED: // The task can't fail completely so something really bad has happened. logMessage("eventLabel='Uploader failed inexplicably' error='" + info.getOutputData() + "'"); @@ -341,7 +342,7 @@ private void startWorkers() { .build() ) .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) - .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.SECONDS) + .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { diff --git a/src/android/PendingUploadDao.java b/src/android/PendingUploadDao.java index a1450265..8a3d0e2e 100644 --- a/src/android/PendingUploadDao.java +++ b/src/android/PendingUploadDao.java @@ -5,6 +5,7 @@ import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; +import androidx.room.Update; import java.util.List; @@ -34,11 +35,18 @@ public interface PendingUploadDao { @Query("SELECT COUNT(*) FROM pending_upload WHERE state = 'UPLOADED'") int getCompletedUploadsCount(); - @Query("UPDATE pending_upload SET state = 'PENDING' WHERE ID = :id") - void markAsPending(final String id); + @Update(onConflict = OnConflictStrategy.REPLACE) + default void markAsPending(final String id) { + setState(id, "PENDING"); + } + + @Update(onConflict = OnConflictStrategy.REPLACE) + default void markAsUploaded(final String id) { + setState(id, "UPLOADED"); + } - @Query("UPDATE pending_upload SET state = 'UPLOADED' WHERE ID = :id") - void markAsUploaded(final String id); + @Query("UPDATE OR REPLACE pending_upload SET state = :state WHERE ID = :id") + void setState(final String id, final String state); default boolean exists(final String id) { return getCountById(id) > 0; diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index f8bbf766..fb2e7186 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -3,6 +3,7 @@ import android.content.Context; import android.net.ConnectivityManager; import android.os.Build; +import android.util.Log; import android.webkit.MimeTypeMap; import androidx.annotation.NonNull; @@ -93,15 +94,6 @@ public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerPara super(context, workerParams); - // Migrating code from 4.0.9 to 4.0.10 - Check if upload comes from another worker and does not exists in table - String oldUploadTaskId = workerParams.getInputData().getString(KEY_INPUT_ID); - if (!firstMigrationFlag && oldUploadTaskId != null && AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getById(oldUploadTaskId) == null) { - FileTransferBackground.logMessage("Migrating upload " + oldUploadTaskId); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().insert(new PendingUpload(oldUploadTaskId, workerParams.getInputData())); - FileTransferBackground.logMessage("Retrying migrated upload " + oldUploadTaskId + " after some seconds..."); - firstMigrationFlag = true; - } - nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); if (httpClient == null) { @@ -142,15 +134,6 @@ public Result doWork() { return Result.retry(); } - // Migrating code from 4.0.9 to 4.0.10 - Check if upload comes from another worker and does not exists in table - String oldUploadTaskId = getInputData().getString(KEY_INPUT_ID); - if (oldUploadTaskId != null && AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getById(oldUploadTaskId) == null && firstMigrationFlag == true) { - FileTransferBackground.logMessage("Migrating upload " + oldUploadTaskId); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().insert(new PendingUpload(oldUploadTaskId, getInputData())); - FileTransferBackground.logMessage("Retrying migrated upload " + oldUploadTaskId + " after some seconds..."); - return Result.success(); - } - do { nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); @@ -303,9 +286,6 @@ private void handleProgress(long bytesWritten, long totalBytes) { float percent = (float) bytesWritten / (float) totalBytes; UploadForegroundNotification.progress(getId(), percent); - - FileTransferBackground.logMessageInfo("handleProgress: " + getId() + " Progress: " + (int) (percent * 100f)); - final Data data = new Data.Builder() .putString(KEY_PROGRESS_ID, nextPendingUpload.getInputData().getString(KEY_INPUT_ID)) .putInt(KEY_PROGRESS_PERCENT, (int) (percent * 100f)) From c0d874252643ddcb3fcef9496732089840bd4eae Mon Sep 17 00:00:00 2001 From: zfir Date: Fri, 28 Apr 2023 14:54:23 +0400 Subject: [PATCH 02/22] Query WorkManager --- src/android/FileTransferBackground.java | 34 +++++++++++++++++++++---- src/android/UploadTask.java | 2 -- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index d89ad5ce..f53eb19c 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -17,6 +17,7 @@ import androidx.work.OutOfQuotaPolicy; import androidx.work.WorkInfo; import androidx.work.WorkManager; +import androidx.work.WorkQuery; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; @@ -46,8 +47,6 @@ public class FileTransferBackground extends CordovaPlugin { private Data httpClientBaseConfig = Data.EMPTY; - public static boolean workerIsStarted; - private ScheduledExecutorService executorService = null; private int ccUpload; @@ -179,6 +178,21 @@ private void initManager(String options, final CallbackContext callbackContext) final AckDatabase ackDatabase = AckDatabase.getInstance(cordova.getContext()); + try { + List workInfoStates = new ArrayList<>(); + workInfoStates.add(WorkInfo.State.BLOCKED); + workInfoStates.add(WorkInfo.State.CANCELLED); + workInfoStates.add(WorkInfo.State.ENQUEUED); + workInfoStates.add(WorkInfo.State.RUNNING); + List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); + if (ackDatabase.pendingUploadDao().getPendingUploadsCount() > 0 && workers.size() == 0) { + startWorkers(); + } + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + logMessage("eventLabel='Uploader could not start worker:'" + e.getMessage() + "'"); + } + // Resend pending ACK at startup (and warmup database) final List uploadEvents = ackDatabase .uploadEventDao() @@ -326,9 +340,19 @@ private void addUpload(JSONObject jsonPayload) { ) ); - if (!workerIsStarted) { - startWorkers(); - workerIsStarted = true; + try { + List workInfoStates = new ArrayList<>(); + workInfoStates.add(WorkInfo.State.BLOCKED); + workInfoStates.add(WorkInfo.State.CANCELLED); + workInfoStates.add(WorkInfo.State.ENQUEUED); + workInfoStates.add(WorkInfo.State.RUNNING); + List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); + if (workers.size() == 0) { + startWorkers(); + } + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + logMessage("eventLabel='Uploader could not start worker:'" + e.getMessage() + "'"); } } diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index fb2e7186..fa7f1ae1 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -268,8 +268,6 @@ public Result doWork() { AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().delete(pendingUpload); } - FileTransferBackground.workerIsStarted = false; - return Result.success(); } From 5b6cc0ea21627ae709bdea74bc4c3e4a4b857a98 Mon Sep 17 00:00:00 2001 From: zfir Date: Fri, 28 Apr 2023 17:31:29 +0400 Subject: [PATCH 03/22] Test --- src/android/UploadTask.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index fa7f1ae1..9ce4cd1f 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -146,15 +146,15 @@ public Result doWork() { } // Check retry count - if (getRunAttemptCount() > MAX_TRIES) { - return Result.success(new Data.Builder() - .putString(KEY_OUTPUT_ID, id) - .putBoolean(KEY_OUTPUT_IS_ERROR, true) - .putString(KEY_OUTPUT_FAILURE_REASON, "Too many retries") - .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) - .build() - ); - } + // if (getRunAttemptCount() > MAX_TRIES) { + // return Result.success(new Data.Builder() + // .putString(KEY_OUTPUT_ID, id) + // .putBoolean(KEY_OUTPUT_IS_ERROR, true) + // .putString(KEY_OUTPUT_FAILURE_REASON, "Too many retries") + // .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) + // .build() + // ); + // } Request request = null; try { From 271bc23bbdf125fbb36e2a50373fab468518d607 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 11:12:13 +0400 Subject: [PATCH 04/22] Uncomment --- src/android/UploadTask.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index 9ce4cd1f..fa7f1ae1 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -146,15 +146,15 @@ public Result doWork() { } // Check retry count - // if (getRunAttemptCount() > MAX_TRIES) { - // return Result.success(new Data.Builder() - // .putString(KEY_OUTPUT_ID, id) - // .putBoolean(KEY_OUTPUT_IS_ERROR, true) - // .putString(KEY_OUTPUT_FAILURE_REASON, "Too many retries") - // .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) - // .build() - // ); - // } + if (getRunAttemptCount() > MAX_TRIES) { + return Result.success(new Data.Builder() + .putString(KEY_OUTPUT_ID, id) + .putBoolean(KEY_OUTPUT_IS_ERROR, true) + .putString(KEY_OUTPUT_FAILURE_REASON, "Too many retries") + .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) + .build() + ); + } Request request = null; try { From 5c38817483a0b213404b499dedea014f846a978e Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 11:25:01 +0400 Subject: [PATCH 05/22] Fix --- src/android/FileTransferBackground.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index f53eb19c..005ce922 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -178,6 +178,21 @@ private void initManager(String options, final CallbackContext callbackContext) final AckDatabase ackDatabase = AckDatabase.getInstance(cordova.getContext()); + // Delete any worker + try { + List workInfoStates = new ArrayList<>(); + workInfoStates.add(WorkInfo.State.FAILED); + workInfoStates.add(WorkInfo.State.SUCCEEDED); + List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); + for (int i = 0; i < workers.size(); i++) { + WorkManager.getInstance(cordova.getContext()).cancelUniqueWork(workers.get(i)); + } + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + logMessage("eventLabel='Uploader could not start worker:'" + e.getMessage() + "'"); + } + + // Start workers if there is pending uploads and no worker is already running try { List workInfoStates = new ArrayList<>(); workInfoStates.add(WorkInfo.State.BLOCKED); @@ -185,6 +200,7 @@ private void initManager(String options, final CallbackContext callbackContext) workInfoStates.add(WorkInfo.State.ENQUEUED); workInfoStates.add(WorkInfo.State.RUNNING); List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); + if (ackDatabase.pendingUploadDao().getPendingUploadsCount() > 0 && workers.size() == 0) { startWorkers(); } From 222bb48759c5717cfc3505c8854b686cb944c0b7 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 12:00:40 +0400 Subject: [PATCH 06/22] Fixes --- src/android/FileTransferBackground.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 005ce922..99a2cf5e 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -185,7 +185,7 @@ private void initManager(String options, final CallbackContext callbackContext) workInfoStates.add(WorkInfo.State.SUCCEEDED); List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); for (int i = 0; i < workers.size(); i++) { - WorkManager.getInstance(cordova.getContext()).cancelUniqueWork(workers.get(i)); + WorkManager.getInstance(cordova.getContext()).cancelAllWork(); } } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); @@ -392,7 +392,7 @@ private void startWorkers() { OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) - .enqueueUniqueWork(FileTransferBackground.WORK_TAG_UPLOAD + "_" + i, ExistingWorkPolicy.KEEP, workRequest); + .enqueueUniqueWork(FileTransferBackground.WORK_TAG_UPLOAD + "_" + i, ExistingWorkPolicy.REPLACE, workRequest); logMessage("eventLabel=Uploader starting uploads via worker" + i); } From f45f44c69b483cf3f49667d1611e87a0fc65247f Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 12:15:18 +0400 Subject: [PATCH 07/22] Fix --- src/android/FileTransferBackground.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 99a2cf5e..792b7c10 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -385,14 +385,14 @@ private void startWorkers() { .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); - } + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); + // } OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) - .enqueueUniqueWork(FileTransferBackground.WORK_TAG_UPLOAD + "_" + i, ExistingWorkPolicy.REPLACE, workRequest); + .enqueueUniqueWork(FileTransferBackground.WORK_TAG_UPLOAD + "_" + i, ExistingWorkPolicy.KEEP, workRequest); logMessage("eventLabel=Uploader starting uploads via worker" + i); } From ba280fdb09bff7b17ca6f5329aaec3383c7fb095 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 12:43:24 +0400 Subject: [PATCH 08/22] Changes --- src/android/FileTransferBackground.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 792b7c10..eab7dc7f 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -178,14 +178,14 @@ private void initManager(String options, final CallbackContext callbackContext) final AckDatabase ackDatabase = AckDatabase.getInstance(cordova.getContext()); - // Delete any worker + // Delete any worker that has been failed or succeeded try { List workInfoStates = new ArrayList<>(); workInfoStates.add(WorkInfo.State.FAILED); workInfoStates.add(WorkInfo.State.SUCCEEDED); List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); for (int i = 0; i < workers.size(); i++) { - WorkManager.getInstance(cordova.getContext()).cancelAllWork(); + WorkManager.getInstance(cordova.getContext()).cancelWorkById(workers.get(i).getId()); } } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); @@ -377,18 +377,14 @@ private void startWorkers() { for (int i = 0; i < ccUpload; i++) { OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(UploadTask.class) - .setConstraints(new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - ) - .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) +// .setConstraints(new Constraints.Builder() +// .setRequiredNetworkType(NetworkType.CONNECTED) +// .build() +// ) +// .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); - // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - // workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); - // } - OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) From 0461eaf5e98e77ea20e6c0f92d32bed7d4ae2617 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 14:40:05 +0400 Subject: [PATCH 09/22] Upgrade Workmanager --- plugin.xml | 4 ++-- src/android/FileTransferBackground.java | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugin.xml b/plugin.xml index a2b5418b..ce78f338 100644 --- a/plugin.xml +++ b/plugin.xml @@ -13,9 +13,9 @@ - + - + diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index eab7dc7f..b9199d5c 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -377,11 +377,11 @@ private void startWorkers() { for (int i = 0; i < ccUpload; i++) { OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(UploadTask.class) -// .setConstraints(new Constraints.Builder() -// .setRequiredNetworkType(NetworkType.CONNECTED) -// .build() -// ) -// .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) + .setConstraints(new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); From 996855d54612e4becd3fbb39a5182f868288790f Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 17:30:18 +0400 Subject: [PATCH 10/22] Delete all workers --- src/android/FileTransferBackground.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index b9199d5c..4f87bb4e 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -178,19 +178,8 @@ private void initManager(String options, final CallbackContext callbackContext) final AckDatabase ackDatabase = AckDatabase.getInstance(cordova.getContext()); - // Delete any worker that has been failed or succeeded - try { - List workInfoStates = new ArrayList<>(); - workInfoStates.add(WorkInfo.State.FAILED); - workInfoStates.add(WorkInfo.State.SUCCEEDED); - List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); - for (int i = 0; i < workers.size(); i++) { - WorkManager.getInstance(cordova.getContext()).cancelWorkById(workers.get(i).getId()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - logMessage("eventLabel='Uploader could not start worker:'" + e.getMessage() + "'"); - } + // Delete any worker + WorkManager.getInstance(cordova.getContext()).cancelAllWork(); // Start workers if there is pending uploads and no worker is already running try { From 2a636fb1f14994701e72e65b1f6aef7bee4ac7f7 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 17:32:09 +0400 Subject: [PATCH 11/22] Delete all workers --- src/android/FileTransferBackground.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 4f87bb4e..5d69c85d 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -180,6 +180,7 @@ private void initManager(String options, final CallbackContext callbackContext) // Delete any worker WorkManager.getInstance(cordova.getContext()).cancelAllWork(); + WorkManager.getInstance(cordova.getContext()).pruneWork(); // Start workers if there is pending uploads and no worker is already running try { From 71c209c38cd9c8a36da041df7522c07cafad79a2 Mon Sep 17 00:00:00 2001 From: zfir Date: Tue, 2 May 2023 18:13:58 +0400 Subject: [PATCH 12/22] Expedited Work --- src/android/FileTransferBackground.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 5d69c85d..569c2541 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -375,6 +375,10 @@ private void startWorkers() { .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); + } + OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) From 7e21bdd600cace762ab47dd9cc8407c9d78d882b Mon Sep 17 00:00:00 2001 From: zfir Date: Wed, 3 May 2023 10:21:17 +0400 Subject: [PATCH 13/22] Fixes --- src/android/FileTransferBackground.java | 26 ++++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 569c2541..a2502a28 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -367,18 +367,14 @@ private void startWorkers() { for (int i = 0; i < ccUpload; i++) { OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(UploadTask.class) - .setConstraints(new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - ) - .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) + .setConstraints(new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); - } - OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) @@ -463,16 +459,18 @@ private void handleAck(final Data ackData) { * Cleanup response file and ACK entry. */ private void cleanupUpload(final String uploadId) { - final UploadEvent ack = AckDatabase.getInstance(cordova.getContext()).uploadEventDao().getById(uploadId); + final PendingUpload pendingUploadAck = AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().getById(uploadId); + final UploadEvent uploadEventAck = AckDatabase.getInstance(cordova.getContext()).uploadEventDao().getById(uploadId); // If the upload is done there is an ACK of it, so get file name from there - if (ack != null) { - if (ack.getOutputData().getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE) != null) { - cordova.getContext().deleteFile(ack.getOutputData().getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE)); + if (uploadEventAck != null) { + if (uploadEventAck.getOutputData().getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE) != null) { + cordova.getContext().deleteFile(uploadEventAck.getOutputData().getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE)); } // Also delete it from database - AckDatabase.getInstance(cordova.getContext()).uploadEventDao().delete(ack); + AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().delete(pendingUploadAck); + AckDatabase.getInstance(cordova.getContext()).uploadEventDao().delete(uploadEventAck); } else { // Otherwise get the data from the task itself final WorkInfo task; From 0bc70901e107105d1cd950db309b12bfc97162ad Mon Sep 17 00:00:00 2001 From: zfir Date: Wed, 3 May 2023 10:38:56 +0400 Subject: [PATCH 14/22] OutOfQuota --- src/android/FileTransferBackground.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index a2502a28..4a6e23d0 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -375,6 +375,10 @@ private void startWorkers() { .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) .addTag(FileTransferBackground.WORK_TAG_UPLOAD); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); + } + OneTimeWorkRequest workRequest = workRequestBuilder.build(); WorkManager.getInstance(cordova.getContext()) From a659b53226ebb7123cfe52040c389e3861f29d08 Mon Sep 17 00:00:00 2001 From: zfir Date: Wed, 3 May 2023 11:05:19 +0400 Subject: [PATCH 15/22] if pendingUploadAck --- src/android/FileTransferBackground.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 4a6e23d0..852f028a 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -463,7 +463,6 @@ private void handleAck(final Data ackData) { * Cleanup response file and ACK entry. */ private void cleanupUpload(final String uploadId) { - final PendingUpload pendingUploadAck = AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().getById(uploadId); final UploadEvent uploadEventAck = AckDatabase.getInstance(cordova.getContext()).uploadEventDao().getById(uploadId); // If the upload is done there is an ACK of it, so get file name from there @@ -473,7 +472,10 @@ private void cleanupUpload(final String uploadId) { } // Also delete it from database - AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().delete(pendingUploadAck); + final PendingUpload pendingUploadAck = AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().getById(uploadId); + if (pendingUploadAck != null) { + AckDatabase.getInstance(cordova.getContext()).pendingUploadDao().delete(pendingUploadAck); + } AckDatabase.getInstance(cordova.getContext()).uploadEventDao().delete(uploadEventAck); } else { // Otherwise get the data from the task itself From ca059795827423b3751ba2de4be0b552899d3ae0 Mon Sep 17 00:00:00 2001 From: zfir Date: Wed, 3 May 2023 15:16:43 +0400 Subject: [PATCH 16/22] Remove MAX_TRIES --- src/android/UploadTask.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index fa7f1ae1..8680400a 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -145,17 +145,6 @@ public Result doWork() { return Result.failure(); } - // Check retry count - if (getRunAttemptCount() > MAX_TRIES) { - return Result.success(new Data.Builder() - .putString(KEY_OUTPUT_ID, id) - .putBoolean(KEY_OUTPUT_IS_ERROR, true) - .putString(KEY_OUTPUT_FAILURE_REASON, "Too many retries") - .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) - .build() - ); - } - Request request = null; try { request = createRequest(); From b9bcd9c2cd443755b57b5cf1695c51275c59a448 Mon Sep 17 00:00:00 2001 From: zfir Date: Wed, 3 May 2023 17:24:16 +0400 Subject: [PATCH 17/22] Fix Notification --- src/android/UploadForegroundNotification.java | 8 +++----- src/android/UploadNotification.java | 5 ++--- src/android/UploadTask.java | 10 +++++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/android/UploadForegroundNotification.java b/src/android/UploadForegroundNotification.java index 386e29c8..35f93fda 100644 --- a/src/android/UploadForegroundNotification.java +++ b/src/android/UploadForegroundNotification.java @@ -44,7 +44,7 @@ public static void done(final UUID uuid) { collectiveProgress.remove(uuid); } - static ForegroundInfo getForegroundInfo(final Context context) { + static ForegroundInfo getForegroundInfo(final Context context, float progress) { final long now = System.currentTimeMillis(); // Set to now to ensure other worker will be throttled final long lastUpdate = lastNotificationUpdateMs.getAndSet(now); @@ -56,9 +56,7 @@ static ForegroundInfo getForegroundInfo(final Context context) { return cachedInfo; } - float totalProgressStore = (float) (AckDatabase.getInstance(context).pendingUploadDao().getCompletedUploadsCount() / (double) AckDatabase.getInstance(context).pendingUploadDao().getAllCount()); - - FileTransferBackground.logMessage("eventLabel='getForegroundInfo: general (" + totalProgressStore + ") all (" + collectiveProgress + ")'"); + FileTransferBackground.logMessage("eventLabel='getForegroundInfo: general (" + (progress * 100) + ") all (" + collectiveProgress + ")'"); Class mainActivityClass = null; try { @@ -82,7 +80,7 @@ static ForegroundInfo getForegroundInfo(final Context context) { .setSmallIcon(notificationIconRes) .setColor(Color.rgb(57, 100, 150)) .setOngoing(true) - .setProgress(100, (int) (totalProgressStore * 100f), false) + .setProgress(100, (int) (progress * 100), false) .setContentIntent(pendingIntent) .addAction(notificationIconRes, "Open", pendingIntent) .build(); diff --git a/src/android/UploadNotification.java b/src/android/UploadNotification.java index 2d2fe2d1..f128d501 100644 --- a/src/android/UploadNotification.java +++ b/src/android/UploadNotification.java @@ -41,9 +41,8 @@ public class UploadNotification { )); } - public void updateProgress() { - float totalProgressStore = (float) (AckDatabase.getInstance(context).pendingUploadDao().getCompletedUploadsCount() / (double) AckDatabase.getInstance(context).pendingUploadDao().getAllCount()); - notificationBuilder.setProgress(100, (int) (totalProgressStore * 100f), false); + public void updateProgress(float progress) { + notificationBuilder.setProgress(100, (int) (progress * 100), false); notificationManager.notify(UploadNotification.notificationId, notificationBuilder.build()); } diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index 8680400a..bc6ce4e3 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -163,7 +163,7 @@ public Result doWork() { // Register me uploadForegroundNotification.progress(getId(), 0f); - handleNotification(); + handleNotification(0f); // Start call currentCall = httpClient.newCall(request); @@ -279,7 +279,7 @@ private void handleProgress(long bytesWritten, long totalBytes) { .build(); FileTransferBackground.logMessage("handleProgress: Progress data: " + data); setProgressAsync(data); - handleNotification(); + handleNotification(percent); } /** @@ -355,12 +355,12 @@ private Request createRequest() throws FileNotFoundException { return requestBuilder.build(); } - private void handleNotification() { + private void handleNotification(float progress) { FileTransferBackground.logMessage("Upload Notification"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { - setForegroundAsync(uploadForegroundNotification.getForegroundInfo(getApplicationContext())); + setForegroundAsync(uploadForegroundNotification.getForegroundInfo(getApplicationContext(), progress)); } else { - uploadNotification.updateProgress(); + uploadNotification.updateProgress(progress); } FileTransferBackground.logMessage("Upload Notification Exit"); } From 94e0f9a6e63bce5f10984e684a7d8f08a24e83f9 Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 4 May 2023 10:18:55 +0400 Subject: [PATCH 18/22] Remove Import --- src/android/UploadTask.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index bc6ce4e3..d6e303b1 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -3,7 +3,6 @@ import android.content.Context; import android.net.ConnectivityManager; import android.os.Build; -import android.util.Log; import android.webkit.MimeTypeMap; import androidx.annotation.NonNull; From b38c2778f5e89f737bf65b1731b3a1dde14be618 Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 4 May 2023 10:56:19 +0400 Subject: [PATCH 19/22] Update Node for Engine --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ace65222..afc165b5 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,8 @@ ], "license": "Apache-2.0", "engines": { - "node": "14.x", - "npm": "6.x", + "node": ">=14.x", + "npm": ">=6.x", "cordova": ">=8.0.0" }, "standard": { From 11512edd5006c6a105191a6fd761f9ed07cda66f Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 4 May 2023 14:55:18 +0400 Subject: [PATCH 20/22] runInTransaction --- src/android/FileTransferBackground.java | 66 ++++++++++++++++--------- src/android/PendingUploadDao.java | 8 +++ src/android/UploadTask.java | 62 ++++++++++++++++++----- 3 files changed, 102 insertions(+), 34 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index 852f028a..f98f521c 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -182,6 +182,13 @@ private void initManager(String options, final CallbackContext callbackContext) WorkManager.getInstance(cordova.getContext()).cancelAllWork(); WorkManager.getInstance(cordova.getContext()).pruneWork(); + ackDatabase.runInTransaction(new Runnable() { + @Override + public void run() { + ackDatabase.pendingUploadDao().resetUploadingAsPending(); + } + }); + // Start workers if there is pending uploads and no worker is already running try { List workInfoStates = new ArrayList<>(); @@ -191,26 +198,36 @@ private void initManager(String options, final CallbackContext callbackContext) workInfoStates.add(WorkInfo.State.RUNNING); List workers = WorkManager.getInstance(cordova.getContext()).getWorkInfos(WorkQuery.Builder.fromStates(workInfoStates).build()).get(); - if (ackDatabase.pendingUploadDao().getPendingUploadsCount() > 0 && workers.size() == 0) { - startWorkers(); - } + ackDatabase.runInTransaction(new Runnable() { + @Override + public void run() { + if (ackDatabase.pendingUploadDao().getPendingUploadsCount() > 0 && workers.size() == 0) { + startWorkers(); + } + } + }); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); logMessage("eventLabel='Uploader could not start worker:'" + e.getMessage() + "'"); } // Resend pending ACK at startup (and warmup database) - final List uploadEvents = ackDatabase - .uploadEventDao() - .getAll(); - - int ackDelay = 0; - for (UploadEvent ack : uploadEvents) { - executorService.schedule(() -> { - handleAck(ack.getOutputData()); - }, ackDelay, TimeUnit.MILLISECONDS); - ackDelay += 200; - } + + ackDatabase.runInTransaction(new Runnable() { + @Override + public void run() { + List uploadEvents = ackDatabase + .uploadEventDao() + .getAll(); + int ackDelay = 0; + for (UploadEvent ack : uploadEvents) { + executorService.schedule(() -> { + handleAck(ack.getOutputData()); + }, ackDelay, TimeUnit.MILLISECONDS); + ackDelay += 200; + } + } + }); // Can't use observeForever anywhere else than the main thread cordova.getActivity().runOnUiThread(() -> { @@ -222,12 +239,17 @@ private void initManager(String options, final CallbackContext callbackContext) for (WorkInfo info : tasks) { // No db in main thread executorService.schedule(() -> { - final List uploadEventsList = ackDatabase - .uploadEventDao() - .getAll(); - for (UploadEvent ack : uploadEventsList) { - handleAck(ack.getOutputData()); - } + ackDatabase.runInTransaction(new Runnable() { + @Override + public void run() { + List uploadEventsList = ackDatabase + .uploadEventDao() + .getAll(); + for (UploadEvent ack : uploadEventsList) { + handleAck(ack.getOutputData()); + } + } + }); }, 0, TimeUnit.MILLISECONDS); switch (info.getState()) { // If the upload in not finished, publish its progress @@ -372,8 +394,8 @@ private void startWorkers() { .build() ) .keepResultsForAtLeast(0, TimeUnit.MILLISECONDS) - .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) - .addTag(FileTransferBackground.WORK_TAG_UPLOAD); + .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) + .addTag(FileTransferBackground.WORK_TAG_UPLOAD); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST); diff --git a/src/android/PendingUploadDao.java b/src/android/PendingUploadDao.java index 8a3d0e2e..e3eb12a0 100644 --- a/src/android/PendingUploadDao.java +++ b/src/android/PendingUploadDao.java @@ -35,11 +35,19 @@ public interface PendingUploadDao { @Query("SELECT COUNT(*) FROM pending_upload WHERE state = 'UPLOADED'") int getCompletedUploadsCount(); + @Query("UPDATE pending_upload SET state = 'PENDING' WHERE state = 'UPLOADING'") + void resetUploadingAsPending(); + @Update(onConflict = OnConflictStrategy.REPLACE) default void markAsPending(final String id) { setState(id, "PENDING"); } + @Update(onConflict = OnConflictStrategy.REPLACE) + default void markAsUploading(final String id) { + setState(id, "UPLOADING"); + } + @Update(onConflict = OnConflictStrategy.REPLACE) default void markAsUploaded(final String id) { setState(id, "UPLOADED"); diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index d6e303b1..c170a69c 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -93,7 +93,13 @@ public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerPara super(context, workerParams); - nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); + } + }); if (httpClient == null) { httpClient = new OkHttpClient.Builder() @@ -133,9 +139,23 @@ public Result doWork() { return Result.retry(); } + final int[] pendingUploadCount = new int[1]; + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + pendingUploadCount[0] = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getPendingUploadsCount(); + } + }); + if (nextPendingUpload == null) { + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); + } + }); + } do { - nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); - final String id = nextPendingUpload.getInputData().getString(KEY_INPUT_ID); if (id == null) { @@ -201,8 +221,13 @@ public Result doWork() { .putString(KEY_OUTPUT_FAILURE_REASON, "User cancelled") .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, true) .build(); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); - AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); + AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); + } + }); return Result.success(data); } else { // But if it was not it must be a connectivity problem or @@ -246,15 +271,28 @@ public Result doWork() { } final Data data = outputData.build(); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); - AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); - } while(AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getPendingUploadsCount() > 0); + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); + AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); + pendingUploadCount[0] = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getPendingUploadsCount(); + nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); + } + }); + } while(pendingUploadCount[0] > 0); - final List pendingUploads = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getCompletedUploads(); + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + final List pendingUploads = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getCompletedUploads(); - for (PendingUpload pendingUpload: pendingUploads) { - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().delete(pendingUpload); - } + for (PendingUpload pendingUpload:pendingUploads) { + AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().delete(pendingUpload); + } + } + }); return Result.success(); } From 858f3d1247cab623737264081e8de713d049a3e7 Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 4 May 2023 16:31:37 +0400 Subject: [PATCH 21/22] Changes --- src/android/FileTransferBackground.java | 4 +++ src/android/UploadTask.java | 43 ++++++------------------- 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/src/android/FileTransferBackground.java b/src/android/FileTransferBackground.java index f98f521c..830e63be 100644 --- a/src/android/FileTransferBackground.java +++ b/src/android/FileTransferBackground.java @@ -300,6 +300,10 @@ private void addUpload(JSONObject jsonPayload) { final String uploadId = String.valueOf(payload.get("id")); + if (uploadId == null) { + return; + } + // Create headers final Map headers; try { diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index c170a69c..2aee3677 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -93,14 +93,6 @@ public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerPara super(context, workerParams); - AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { - @Override - public void run() { - nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); - } - }); - if (httpClient == null) { httpClient = new OkHttpClient.Builder() .followRedirects(true) @@ -113,8 +105,6 @@ public void run() { .build(); } - httpClient.dispatcher().setMaxRequests(nextPendingUpload.getInputData().getInt(KEY_INPUT_CONFIG_CONCURRENT_DOWNLOADS, 2)); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { UploadForegroundNotification.configure( nextPendingUpload.getInputData().getString(UploadTask.KEY_INPUT_NOTIFICATION_TITLE), @@ -139,14 +129,7 @@ public Result doWork() { return Result.retry(); } - final int[] pendingUploadCount = new int[1]; - AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { - @Override - public void run() { - pendingUploadCount[0] = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getPendingUploadsCount(); - } - }); - if (nextPendingUpload == null) { + while (true) { AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { @Override public void run() { @@ -154,14 +137,9 @@ public void run() { AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); } }); - } - do { - final String id = nextPendingUpload.getInputData().getString(KEY_INPUT_ID); - if (id == null) { - FileTransferBackground.logMessageError("doWork: ID is invalid !", null); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsPending(nextPendingUpload.getId()); - return Result.failure(); + if (nextPendingUpload == null) { + break; } Request request = null; @@ -170,7 +148,7 @@ public void run() { } catch (FileNotFoundException e) { FileTransferBackground.logMessageError("doWork: File not found !", e); return Result.success(new Data.Builder() - .putString(KEY_OUTPUT_ID, id) + .putString(KEY_OUTPUT_ID, nextPendingUpload.getId()) .putBoolean(KEY_OUTPUT_IS_ERROR, true) .putString(KEY_OUTPUT_FAILURE_REASON, "File not found !") .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, false) @@ -216,7 +194,7 @@ public void run() { // See #handleProgress for cancel code if (isStopped()) { final Data data = new Data.Builder() - .putString(KEY_OUTPUT_ID, id) + .putString(KEY_OUTPUT_ID, nextPendingUpload.getId()) .putBoolean(KEY_OUTPUT_IS_ERROR, true) .putString(KEY_OUTPUT_FAILURE_REASON, "User cancelled") .putBoolean(KEY_OUTPUT_FAILURE_CANCELED, true) @@ -225,7 +203,7 @@ public void run() { @Override public void run() { AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); - AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); + AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(nextPendingUpload.getId(), data)); } }); return Result.success(data); @@ -242,7 +220,7 @@ public void run() { // Start building the output data final Data.Builder outputData = new Data.Builder() - .putString(KEY_OUTPUT_ID, id) + .putString(KEY_OUTPUT_ID, nextPendingUpload.getId()) .putBoolean(KEY_OUTPUT_IS_ERROR, false) .putInt(KEY_OUTPUT_STATUS_CODE, (!DEBUG_SKIP_UPLOAD) ? response.code() : 200); @@ -275,13 +253,10 @@ public void run() { @Override public void run() { AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploaded(nextPendingUpload.getId()); - AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data)); - pendingUploadCount[0] = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getPendingUploadsCount(); - nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); - AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().markAsUploading(nextPendingUpload.getId()); + AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(nextPendingUpload.getId(), data)); } }); - } while(pendingUploadCount[0] > 0); + } AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { @Override From ec5f3e283aee27eb37d57e0666b80f0042f2712a Mon Sep 17 00:00:00 2001 From: zfir Date: Thu, 4 May 2023 16:43:30 +0400 Subject: [PATCH 22/22] Fixes --- src/android/UploadTask.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java index 2aee3677..606d2fe2 100644 --- a/src/android/UploadTask.java +++ b/src/android/UploadTask.java @@ -93,6 +93,13 @@ public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerPara super(context, workerParams); + AckDatabase.getInstance(getApplicationContext()).runInTransaction(new Runnable() { + @Override + public void run() { + nextPendingUpload = AckDatabase.getInstance(getApplicationContext()).pendingUploadDao().getFirstPendingEntry(); + } + }); + if (httpClient == null) { httpClient = new OkHttpClient.Builder() .followRedirects(true)