|
@@ -21,6 +21,7 @@
|
|
|
|
|
|
package com.nextcloud.client.jobs.upload
|
|
package com.nextcloud.client.jobs.upload
|
|
|
|
|
|
|
|
+import android.app.PendingIntent
|
|
import android.content.BroadcastReceiver
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.Intent
|
|
@@ -66,6 +67,109 @@ class FileUploadWorker(
|
|
params: WorkerParameters
|
|
params: WorkerParameters
|
|
) : Worker(context, params), OnDatatransferProgressListener {
|
|
) : Worker(context, params), OnDatatransferProgressListener {
|
|
|
|
|
|
|
|
+ companion object {
|
|
|
|
+ val TAG: String = FileUploadWorker::class.java.simpleName
|
|
|
|
+
|
|
|
|
+ const val NOTIFICATION_ERROR_ID: Int = 413
|
|
|
|
+ private const val MAX_PROGRESS: Int = 100
|
|
|
|
+ const val ACCOUNT = "data_account"
|
|
|
|
+ var currentUploadFileOperation: UploadFileOperation? = null
|
|
|
|
+
|
|
|
|
+ private const val UPLOADS_ADDED_MESSAGE = "UPLOADS_ADDED"
|
|
|
|
+ private const val UPLOAD_START_MESSAGE = "UPLOAD_START"
|
|
|
|
+ private const val UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH"
|
|
|
|
+
|
|
|
|
+ const val EXTRA_UPLOAD_RESULT = "RESULT"
|
|
|
|
+ const val EXTRA_REMOTE_PATH = "REMOTE_PATH"
|
|
|
|
+ const val EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH"
|
|
|
|
+ const val EXTRA_OLD_FILE_PATH = "OLD_FILE_PATH"
|
|
|
|
+ const val EXTRA_LINKED_TO_PATH = "LINKED_TO"
|
|
|
|
+ const val ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
|
+ const val EXTRA_ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
|
+ const val ACTION_CANCEL_BROADCAST = "CANCEL"
|
|
|
|
+ const val LOCAL_BEHAVIOUR_COPY = 0
|
|
|
|
+ const val LOCAL_BEHAVIOUR_MOVE = 1
|
|
|
|
+ const val LOCAL_BEHAVIOUR_FORGET = 2
|
|
|
|
+ const val LOCAL_BEHAVIOUR_DELETE = 3
|
|
|
|
+
|
|
|
|
+ @Suppress("ComplexCondition")
|
|
|
|
+ fun retryFailedUploads(
|
|
|
|
+ uploadsStorageManager: UploadsStorageManager,
|
|
|
|
+ connectivityService: ConnectivityService,
|
|
|
|
+ accountManager: UserAccountManager,
|
|
|
|
+ powerManagementService: PowerManagementService
|
|
|
|
+ ) {
|
|
|
|
+ val failedUploads = uploadsStorageManager.failedUploads
|
|
|
|
+ if (failedUploads == null || failedUploads.isEmpty()) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val (gotNetwork, _, gotWifi) = connectivityService.connectivity
|
|
|
|
+ val batteryStatus = powerManagementService.battery
|
|
|
|
+ val charging = batteryStatus.isCharging || batteryStatus.isFull
|
|
|
|
+ val isPowerSaving = powerManagementService.isPowerSavingEnabled
|
|
|
|
+ var uploadUser = Optional.empty<User>()
|
|
|
|
+ for (failedUpload in failedUploads) {
|
|
|
|
+ // 1. extract failed upload owner account and cache it between loops (expensive query)
|
|
|
|
+ if (!uploadUser.isPresent || !uploadUser.get().nameEquals(failedUpload.accountName)) {
|
|
|
|
+ uploadUser = accountManager.getUser(failedUpload.accountName)
|
|
|
|
+ }
|
|
|
|
+ val isDeleted = !File(failedUpload.localPath).exists()
|
|
|
|
+ if (isDeleted) {
|
|
|
|
+ // 2A. for deleted files, mark as permanently failed
|
|
|
|
+ if (failedUpload.lastResult != UploadResult.FILE_NOT_FOUND) {
|
|
|
|
+ failedUpload.lastResult = UploadResult.FILE_NOT_FOUND
|
|
|
|
+ uploadsStorageManager.updateUpload(failedUpload)
|
|
|
|
+ }
|
|
|
|
+ } else if (!isPowerSaving && gotNetwork &&
|
|
|
|
+ canUploadBeRetried(failedUpload, gotWifi, charging) && !connectivityService.isInternetWalled
|
|
|
|
+ ) {
|
|
|
|
+ // 2B. for existing local files, try restarting it if possible
|
|
|
|
+ FileUploadHelper.instance().retryUpload(failedUpload, uploadUser.get())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun canUploadBeRetried(upload: OCUpload, gotWifi: Boolean, isCharging: Boolean): Boolean {
|
|
|
|
+ val file = File(upload.localPath)
|
|
|
|
+ val needsWifi = upload.isUseWifiOnly
|
|
|
|
+ val needsCharging = upload.isWhileChargingOnly
|
|
|
|
+ return file.exists() && (!needsWifi || gotWifi) && (!needsCharging || isCharging)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fun getUploadsAddedMessage(): String {
|
|
|
|
+ return FileUploadWorker::class.java.name + UPLOADS_ADDED_MESSAGE
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fun getUploadStartMessage(): String {
|
|
|
|
+ return FileUploadWorker::class.java.name + UPLOAD_START_MESSAGE
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fun getUploadFinishMessage(): String {
|
|
|
|
+ return FileUploadWorker::class.java.name + UPLOAD_FINISH_MESSAGE
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ class UploadNotificationActionReceiver : BroadcastReceiver() {
|
|
|
|
+ override fun onReceive(context: Context, intent: Intent) {
|
|
|
|
+ val accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME)
|
|
|
|
+ val remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH)
|
|
|
|
+ val action = intent.action
|
|
|
|
+
|
|
|
|
+ if (ACTION_CANCEL_BROADCAST == action) {
|
|
|
|
+ Log_OC.d(
|
|
|
|
+ TAG,
|
|
|
|
+ "Cancel broadcast received for file " + remotePath + " at " + System.currentTimeMillis()
|
|
|
|
+ )
|
|
|
|
+ if (accountName == null || remotePath == null) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ FileUploadHelper.instance().cancelFileUpload(remotePath, accountName)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private var lastPercent = 0
|
|
private var lastPercent = 0
|
|
private val notificationManager = UploadNotificationManager(context, viewThemeUtils)
|
|
private val notificationManager = UploadNotificationManager(context, viewThemeUtils)
|
|
private val intents = FileUploaderIntents(context)
|
|
private val intents = FileUploaderIntents(context)
|
|
@@ -75,21 +179,7 @@ class FileUploadWorker(
|
|
override fun doWork(): Result {
|
|
override fun doWork(): Result {
|
|
return try {
|
|
return try {
|
|
backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class))
|
|
backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class))
|
|
-
|
|
|
|
- val accountName = inputData.getString(ACCOUNT)
|
|
|
|
- if (accountName.isNullOrEmpty()) {
|
|
|
|
- Log_OC.w(TAG, "User was null for file upload worker")
|
|
|
|
-
|
|
|
|
- val result = Result.failure()
|
|
|
|
- backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
|
|
|
|
- return result
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- retrievePagesBySortingUploadsByID(accountName)
|
|
|
|
-
|
|
|
|
- Log_OC.e(TAG, "FileUploadWorker successfully completed")
|
|
|
|
-
|
|
|
|
- val result = Result.success()
|
|
|
|
|
|
+ val result = retrievePagesBySortingUploadsByID()
|
|
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
|
|
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
|
|
result
|
|
result
|
|
} catch (t: Throwable) {
|
|
} catch (t: Throwable) {
|
|
@@ -116,20 +206,23 @@ class FileUploadWorker(
|
|
WorkerStateLiveData.instance().setWorkState(WorkerState.Idle)
|
|
WorkerStateLiveData.instance().setWorkState(WorkerState.Idle)
|
|
}
|
|
}
|
|
|
|
|
|
- private fun retrievePagesBySortingUploadsByID(accountName: String) {
|
|
|
|
|
|
+ private fun retrievePagesBySortingUploadsByID(): Result {
|
|
|
|
+ val accountName = inputData.getString(ACCOUNT) ?: return Result.failure()
|
|
var currentPage = uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(-1, accountName)
|
|
var currentPage = uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(-1, accountName)
|
|
|
|
+
|
|
while (currentPage.isNotEmpty() && !isStopped) {
|
|
while (currentPage.isNotEmpty() && !isStopped) {
|
|
Log_OC.d(TAG, "Handling ${currentPage.size} uploads for account $accountName")
|
|
Log_OC.d(TAG, "Handling ${currentPage.size} uploads for account $accountName")
|
|
val lastId = currentPage.last().uploadId
|
|
val lastId = currentPage.last().uploadId
|
|
- handlePendingUploads(currentPage, accountName)
|
|
|
|
|
|
+ uploadFiles(currentPage, accountName)
|
|
currentPage =
|
|
currentPage =
|
|
uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(lastId, accountName)
|
|
uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(lastId, accountName)
|
|
}
|
|
}
|
|
|
|
|
|
Log_OC.d(TAG, "No more pending uploads for account $accountName, stopping work")
|
|
Log_OC.d(TAG, "No more pending uploads for account $accountName, stopping work")
|
|
|
|
+ return Result.success()
|
|
}
|
|
}
|
|
|
|
|
|
- private fun handlePendingUploads(uploads: List<OCUpload>, accountName: String) {
|
|
|
|
|
|
+ private fun uploadFiles(uploads: List<OCUpload>, accountName: String) {
|
|
val user = userAccountManager.getUser(accountName)
|
|
val user = userAccountManager.getUser(accountName)
|
|
setWorkerState(user.get(), uploads)
|
|
setWorkerState(user.get(), uploads)
|
|
|
|
|
|
@@ -139,16 +232,16 @@ class FileUploadWorker(
|
|
}
|
|
}
|
|
|
|
|
|
if (user.isPresent) {
|
|
if (user.isPresent) {
|
|
- val uploadFileOperation = createUploadFileOperation(upload, user.get())
|
|
|
|
|
|
+ val operation = createUploadFileOperation(upload, user.get())
|
|
|
|
|
|
- currentUploadFileOperation = uploadFileOperation
|
|
|
|
- val result = upload(uploadFileOperation, user.get())
|
|
|
|
|
|
+ currentUploadFileOperation = operation
|
|
|
|
+ val result = upload(operation, user.get())
|
|
currentUploadFileOperation = null
|
|
currentUploadFileOperation = null
|
|
|
|
|
|
fileUploaderDelegate.sendBroadcastUploadFinished(
|
|
fileUploaderDelegate.sendBroadcastUploadFinished(
|
|
- uploadFileOperation,
|
|
|
|
|
|
+ operation,
|
|
result,
|
|
result,
|
|
- uploadFileOperation.oldFile?.storagePath,
|
|
|
|
|
|
+ operation.oldFile?.storagePath,
|
|
context,
|
|
context,
|
|
localBroadcastManager
|
|
localBroadcastManager
|
|
)
|
|
)
|
|
@@ -178,41 +271,42 @@ class FileUploadWorker(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- @Suppress("TooGenericExceptionCaught")
|
|
|
|
- private fun upload(uploadFileOperation: UploadFileOperation, user: User): RemoteOperationResult<Any?> {
|
|
|
|
- lateinit var uploadResult: RemoteOperationResult<Any?>
|
|
|
|
|
|
+ @Suppress("TooGenericExceptionCaught", "DEPRECATION")
|
|
|
|
+ private fun upload(operation: UploadFileOperation, user: User): RemoteOperationResult<Any?> {
|
|
|
|
+ lateinit var result: RemoteOperationResult<Any?>
|
|
|
|
|
|
- notificationManager.notifyForStart(
|
|
|
|
- uploadFileOperation,
|
|
|
|
- intents.startIntent(uploadFileOperation),
|
|
|
|
- intents.notificationStartIntent(uploadFileOperation)
|
|
|
|
|
|
+ notificationManager.prepareForStart(
|
|
|
|
+ operation,
|
|
|
|
+ intents.startIntent(operation),
|
|
|
|
+ intents.notificationStartIntent(operation)
|
|
)
|
|
)
|
|
|
|
|
|
try {
|
|
try {
|
|
- val storageManager = uploadFileOperation.storageManager
|
|
|
|
-
|
|
|
|
- // always get client from client manager, to get fresh credentials in case of update
|
|
|
|
|
|
+ val storageManager = operation.storageManager
|
|
val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context)
|
|
val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context)
|
|
val uploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context)
|
|
val uploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context)
|
|
- uploadResult = uploadFileOperation.execute(uploadClient)
|
|
|
|
|
|
+ result = operation.execute(uploadClient)
|
|
|
|
|
|
- // generate new Thumbnail
|
|
|
|
val task = ThumbnailsCacheManager.ThumbnailGenerationTask(storageManager, user)
|
|
val task = ThumbnailsCacheManager.ThumbnailGenerationTask(storageManager, user)
|
|
- val file = File(uploadFileOperation.originalStoragePath)
|
|
|
|
- val remoteId: String? = uploadFileOperation.file.remoteId
|
|
|
|
|
|
+ val file = File(operation.originalStoragePath)
|
|
|
|
+ val remoteId: String? = operation.file.remoteId
|
|
task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId))
|
|
task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId))
|
|
} catch (e: Exception) {
|
|
} catch (e: Exception) {
|
|
Log_OC.e(TAG, "Error uploading", e)
|
|
Log_OC.e(TAG, "Error uploading", e)
|
|
- uploadResult = RemoteOperationResult<Any?>(e)
|
|
|
|
|
|
+ result = RemoteOperationResult<Any?>(e)
|
|
} finally {
|
|
} finally {
|
|
- if (!(isStopped && uploadResult.isCancelled)) {
|
|
|
|
- uploadsStorageManager.updateDatabaseUploadResult(uploadResult, uploadFileOperation)
|
|
|
|
- notifyUploadResult(uploadFileOperation, uploadResult)
|
|
|
|
- notificationManager.dismissWorkerNotifications()
|
|
|
|
- }
|
|
|
|
|
|
+ cleanupUploadProcess(result, operation)
|
|
}
|
|
}
|
|
|
|
|
|
- return uploadResult
|
|
|
|
|
|
+ return result
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun cleanupUploadProcess(result: RemoteOperationResult<Any?>, operation: UploadFileOperation) {
|
|
|
|
+ if (!(isStopped && result.isCancelled)) {
|
|
|
|
+ uploadsStorageManager.updateDatabaseUploadResult(result, operation)
|
|
|
|
+ notifyUploadResult(operation, result)
|
|
|
|
+ notificationManager.dismissWorkerNotifications()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Suppress("ReturnCount")
|
|
@Suppress("ReturnCount")
|
|
@@ -248,8 +342,20 @@ class FileUploadWorker(
|
|
|
|
|
|
val needsToUpdateCredentials = (uploadResult.code == ResultCode.UNAUTHORIZED)
|
|
val needsToUpdateCredentials = (uploadResult.code == ResultCode.UNAUTHORIZED)
|
|
notificationManager.run {
|
|
notificationManager.run {
|
|
- notifyForResult(uploadResult.code)
|
|
|
|
- setContentIntent(intents.resultIntent(ResultCode.OK, uploadFileOperation))
|
|
|
|
|
|
+ val resultIntent = intents.resultIntent(ResultCode.OK, uploadFileOperation)
|
|
|
|
+ val credentialIntent: PendingIntent? = if (needsToUpdateCredentials) {
|
|
|
|
+ intents.credentialIntent(uploadFileOperation)
|
|
|
|
+ } else {
|
|
|
|
+ null
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val errorMessage = if (!uploadResult.isSuccess) {
|
|
|
|
+ ErrorMessageAdapter.getErrorCauseMessage(uploadResult, uploadFileOperation, context.resources)
|
|
|
|
+ } else {
|
|
|
|
+ null
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ notifyForResult(uploadResult.code, resultIntent, credentialIntent, errorMessage)
|
|
|
|
|
|
if (uploadResult.code == ResultCode.SYNC_CONFLICT) {
|
|
if (uploadResult.code == ResultCode.SYNC_CONFLICT) {
|
|
addAction(
|
|
addAction(
|
|
@@ -259,18 +365,9 @@ class FileUploadWorker(
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
- if (needsToUpdateCredentials) {
|
|
|
|
- setContentIntent(intents.credentialIntent(uploadFileOperation))
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- val content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, uploadFileOperation, context.resources)
|
|
|
|
- setContentText(content)
|
|
|
|
-
|
|
|
|
if (!uploadResult.isSuccess) {
|
|
if (!uploadResult.isSuccess) {
|
|
- showRandomNotification()
|
|
|
|
|
|
+ showNewNotification(uploadFileOperation)
|
|
}
|
|
}
|
|
-
|
|
|
|
- showNotificationTag(uploadFileOperation)
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -281,130 +378,31 @@ class FileUploadWorker(
|
|
fileAbsoluteName: String
|
|
fileAbsoluteName: String
|
|
) {
|
|
) {
|
|
val percent = (MAX_PROGRESS * totalTransferredSoFar.toDouble() / totalToTransfer.toDouble()).toInt()
|
|
val percent = (MAX_PROGRESS * totalTransferredSoFar.toDouble() / totalToTransfer.toDouble()).toInt()
|
|
- if (percent != lastPercent) {
|
|
|
|
- notificationManager.updateUploadProgressNotification(fileAbsoluteName, percent, currentUploadFileOperation)
|
|
|
|
-
|
|
|
|
- val accountName = currentUploadFileOperation?.user?.accountName
|
|
|
|
- val remotePath = currentUploadFileOperation?.remotePath
|
|
|
|
-
|
|
|
|
- if (accountName != null && remotePath != null) {
|
|
|
|
- val key: String =
|
|
|
|
- FileUploadHelper.buildRemoteName(accountName, remotePath)
|
|
|
|
- val boundListener = FileUploadHelper.mBoundListeners[key]
|
|
|
|
-
|
|
|
|
- boundListener?.onTransferProgress(
|
|
|
|
- progressRate,
|
|
|
|
- totalTransferredSoFar,
|
|
|
|
- totalToTransfer,
|
|
|
|
- fileAbsoluteName
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- notificationManager.dismissOldErrorNotification(currentUploadFileOperation)
|
|
|
|
- }
|
|
|
|
- lastPercent = percent
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- companion object {
|
|
|
|
- val TAG: String = FileUploadWorker::class.java.simpleName
|
|
|
|
-
|
|
|
|
- const val NOTIFICATION_ERROR_ID: Int = 413
|
|
|
|
- private const val MAX_PROGRESS: Int = 100
|
|
|
|
- const val ACCOUNT = "data_account"
|
|
|
|
- var currentUploadFileOperation: UploadFileOperation? = null
|
|
|
|
-
|
|
|
|
- private const val UPLOADS_ADDED_MESSAGE = "UPLOADS_ADDED"
|
|
|
|
- private const val UPLOAD_START_MESSAGE = "UPLOAD_START"
|
|
|
|
- private const val UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH"
|
|
|
|
-
|
|
|
|
- const val EXTRA_UPLOAD_RESULT = "RESULT"
|
|
|
|
- const val EXTRA_REMOTE_PATH = "REMOTE_PATH"
|
|
|
|
- const val EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH"
|
|
|
|
- const val EXTRA_OLD_FILE_PATH = "OLD_FILE_PATH"
|
|
|
|
- const val EXTRA_LINKED_TO_PATH = "LINKED_TO"
|
|
|
|
- const val ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
|
- const val EXTRA_ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
|
- const val ACTION_CANCEL_BROADCAST = "CANCEL"
|
|
|
|
- const val LOCAL_BEHAVIOUR_COPY = 0
|
|
|
|
- const val LOCAL_BEHAVIOUR_MOVE = 1
|
|
|
|
- const val LOCAL_BEHAVIOUR_FORGET = 2
|
|
|
|
- const val LOCAL_BEHAVIOUR_DELETE = 3
|
|
|
|
-
|
|
|
|
- @Suppress("ComplexCondition")
|
|
|
|
- fun retryFailedUploads(
|
|
|
|
- uploadsStorageManager: UploadsStorageManager,
|
|
|
|
- connectivityService: ConnectivityService,
|
|
|
|
- accountManager: UserAccountManager,
|
|
|
|
- powerManagementService: PowerManagementService
|
|
|
|
- ) {
|
|
|
|
- val failedUploads = uploadsStorageManager.failedUploads
|
|
|
|
- if (failedUploads == null || failedUploads.isEmpty()) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- val (gotNetwork, _, gotWifi) = connectivityService.connectivity
|
|
|
|
- val batteryStatus = powerManagementService.battery
|
|
|
|
- val charging = batteryStatus.isCharging || batteryStatus.isFull
|
|
|
|
- val isPowerSaving = powerManagementService.isPowerSavingEnabled
|
|
|
|
- var uploadUser = Optional.empty<User>()
|
|
|
|
- for (failedUpload in failedUploads) {
|
|
|
|
- // 1. extract failed upload owner account and cache it between loops (expensive query)
|
|
|
|
- if (!uploadUser.isPresent || !uploadUser.get().nameEquals(failedUpload.accountName)) {
|
|
|
|
- uploadUser = accountManager.getUser(failedUpload.accountName)
|
|
|
|
- }
|
|
|
|
- val isDeleted = !File(failedUpload.localPath).exists()
|
|
|
|
- if (isDeleted) {
|
|
|
|
- // 2A. for deleted files, mark as permanently failed
|
|
|
|
- if (failedUpload.lastResult != UploadResult.FILE_NOT_FOUND) {
|
|
|
|
- failedUpload.lastResult = UploadResult.FILE_NOT_FOUND
|
|
|
|
- uploadsStorageManager.updateUpload(failedUpload)
|
|
|
|
- }
|
|
|
|
- } else if (!isPowerSaving && gotNetwork &&
|
|
|
|
- canUploadBeRetried(failedUpload, gotWifi, charging) && !connectivityService.isInternetWalled
|
|
|
|
- ) {
|
|
|
|
- // 2B. for existing local files, try restarting it if possible
|
|
|
|
- FileUploadHelper.instance().retryUpload(failedUpload, uploadUser.get())
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
|
|
- private fun canUploadBeRetried(upload: OCUpload, gotWifi: Boolean, isCharging: Boolean): Boolean {
|
|
|
|
- val file = File(upload.localPath)
|
|
|
|
- val needsWifi = upload.isUseWifiOnly
|
|
|
|
- val needsCharging = upload.isWhileChargingOnly
|
|
|
|
- return file.exists() && (!needsWifi || gotWifi) && (!needsCharging || isCharging)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fun getUploadsAddedMessage(): String {
|
|
|
|
- return FileUploadWorker::class.java.name + UPLOADS_ADDED_MESSAGE
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fun getUploadStartMessage(): String {
|
|
|
|
- return FileUploadWorker::class.java.name + UPLOAD_START_MESSAGE
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fun getUploadFinishMessage(): String {
|
|
|
|
- return FileUploadWorker::class.java.name + UPLOAD_FINISH_MESSAGE
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- class UploadNotificationActionReceiver : BroadcastReceiver() {
|
|
|
|
- override fun onReceive(context: Context, intent: Intent) {
|
|
|
|
- val accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME)
|
|
|
|
- val remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH)
|
|
|
|
- val action = intent.action
|
|
|
|
-
|
|
|
|
- if (ACTION_CANCEL_BROADCAST == action) {
|
|
|
|
- Log_OC.d(
|
|
|
|
- TAG,
|
|
|
|
- "Cancel broadcast received for file " + remotePath + " at " + System.currentTimeMillis()
|
|
|
|
|
|
+ if (percent != lastPercent) {
|
|
|
|
+ notificationManager.run {
|
|
|
|
+ updateUploadProgress(fileAbsoluteName, percent, currentUploadFileOperation)
|
|
|
|
+
|
|
|
|
+ val accountName = currentUploadFileOperation?.user?.accountName
|
|
|
|
+ val remotePath = currentUploadFileOperation?.remotePath
|
|
|
|
+
|
|
|
|
+ if (accountName != null && remotePath != null) {
|
|
|
|
+ val key: String =
|
|
|
|
+ FileUploadHelper.buildRemoteName(accountName, remotePath)
|
|
|
|
+ val boundListener = FileUploadHelper.mBoundListeners[key]
|
|
|
|
+
|
|
|
|
+ boundListener?.onTransferProgress(
|
|
|
|
+ progressRate,
|
|
|
|
+ totalTransferredSoFar,
|
|
|
|
+ totalToTransfer,
|
|
|
|
+ fileAbsoluteName
|
|
)
|
|
)
|
|
- if (accountName == null || remotePath == null) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- FileUploadHelper.instance().cancelFileUpload(remotePath, accountName)
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ dismissOldErrorNotification(currentUploadFileOperation)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ lastPercent = percent
|
|
}
|
|
}
|
|
}
|
|
}
|