瀏覽代碼

Improve notifications

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 年之前
父節點
當前提交
c00a423a0e

+ 1 - 1
app/src/main/java/com/nextcloud/client/jobs/download/DownloadNotificationManager.kt

@@ -45,7 +45,6 @@ class DownloadNotificationManager(
     private val context: Context,
     private val viewThemeUtils: ViewThemeUtils
 ) {
-
     private var notification: Notification
     private var notificationBuilder: NotificationCompat.Builder
     private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@@ -53,6 +52,7 @@ class DownloadNotificationManager(
     init {
         notificationBuilder = NotificationUtils.newNotificationBuilder(context, viewThemeUtils).apply {
             setContentTitle(context.getString(R.string.downloader_download_in_progress_ticker))
+            setTicker(context.getString(R.string.downloader_download_in_progress_ticker))
             setSmallIcon(R.drawable.notification_icon)
             setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.notification_icon))
 

+ 5 - 3
app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt

@@ -108,7 +108,7 @@ class FileDownloadWorker(
     private var lastPercent = 0
 
     private val intents = FileDownloadIntents(context)
-    private lateinit var notificationManager: com.nextcloud.client.jobs.download.DownloadNotificationManager
+    private lateinit var notificationManager: DownloadNotificationManager
     private var downloadProgressListener = FileDownloadProgressListener()
 
     private var user: User? = null
@@ -126,7 +126,7 @@ class FileDownloadWorker(
             val requestDownloads = getRequestDownloads()
 
             notificationManager =
-                com.nextcloud.client.jobs.download.DownloadNotificationManager(
+                DownloadNotificationManager(
                     workerId ?: SecureRandom().nextInt(),
                     context,
                     viewThemeUtils
@@ -267,7 +267,7 @@ class FileDownloadWorker(
         am.addOnAccountsUpdatedListener(this, null, false)
     }
 
-    @Suppress("TooGenericExceptionCaught")
+    @Suppress("TooGenericExceptionCaught", "DEPRECATION")
     private fun downloadFile(downloadKey: String) {
         currentDownload = pendingDownloads.get(downloadKey)
 
@@ -314,6 +314,7 @@ class FileDownloadWorker(
         }
     }
 
+    @Suppress("DEPRECATION")
     private fun getOCAccountForDownload(): OwnCloudAccount {
         val currentDownloadAccount = currentDownload?.user?.toPlatformAccount()
         val currentDownloadUser = accountManager.getUser(currentDownloadAccount?.name)
@@ -413,6 +414,7 @@ class FileDownloadWorker(
         }
     }
 
+    @Suppress("DEPRECATION")
     override fun onAccountsUpdated(accounts: Array<out Account>?) {
         if (!accountManager.exists(currentDownload?.user?.toPlatformAccount())) {
             currentDownload?.cancel()

+ 174 - 176
app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt

@@ -21,6 +21,7 @@
 
 package com.nextcloud.client.jobs.upload
 
+import android.app.PendingIntent
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
@@ -66,6 +67,109 @@ class FileUploadWorker(
     params: WorkerParameters
 ) : 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 val notificationManager = UploadNotificationManager(context, viewThemeUtils)
     private val intents = FileUploaderIntents(context)
@@ -75,21 +179,7 @@ class FileUploadWorker(
     override fun doWork(): Result {
         return try {
             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)
             result
         } catch (t: Throwable) {
@@ -116,20 +206,23 @@ class FileUploadWorker(
         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)
+
         while (currentPage.isNotEmpty() && !isStopped) {
             Log_OC.d(TAG, "Handling ${currentPage.size} uploads for account $accountName")
             val lastId = currentPage.last().uploadId
-            handlePendingUploads(currentPage, accountName)
+            uploadFiles(currentPage, accountName)
             currentPage =
                 uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(lastId, accountName)
         }
 
         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)
         setWorkerState(user.get(), uploads)
 
@@ -139,16 +232,16 @@ class FileUploadWorker(
             }
 
             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
 
                 fileUploaderDelegate.sendBroadcastUploadFinished(
-                    uploadFileOperation,
+                    operation,
                     result,
-                    uploadFileOperation.oldFile?.storagePath,
+                    operation.oldFile?.storagePath,
                     context,
                     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 {
-            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 uploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context)
-            uploadResult = uploadFileOperation.execute(uploadClient)
+            result = operation.execute(uploadClient)
 
-            // generate new Thumbnail
             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))
         } catch (e: Exception) {
             Log_OC.e(TAG, "Error uploading", e)
-            uploadResult = RemoteOperationResult<Any?>(e)
+            result = RemoteOperationResult<Any?>(e)
         } 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")
@@ -248,8 +342,20 @@ class FileUploadWorker(
 
         val needsToUpdateCredentials = (uploadResult.code == ResultCode.UNAUTHORIZED)
         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) {
                 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) {
-                showRandomNotification()
+                showNewNotification(uploadFileOperation)
             }
-
-            showNotificationTag(uploadFileOperation)
         }
     }
 
@@ -281,130 +378,31 @@ class FileUploadWorker(
         fileAbsoluteName: String
     ) {
         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
     }
 }

+ 52 - 56
app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt

@@ -34,27 +34,18 @@ import com.owncloud.android.lib.resources.files.FileUtils
 import com.owncloud.android.operations.UploadFileOperation
 import com.owncloud.android.ui.notifications.NotificationUtils
 import com.owncloud.android.utils.theme.ViewThemeUtils
-import java.security.SecureRandom
 
 class UploadNotificationManager(private val context: Context, private val viewThemeUtils: ViewThemeUtils) {
 
-    companion object {
-        private const val WORKER_ID = 411
-    }
+    private val id = 411
 
     private var notification: Notification? = null
-    private val secureRandomGenerator = SecureRandom()
-    private lateinit var notificationBuilder: NotificationCompat.Builder
+    private var notificationBuilder: NotificationCompat.Builder
     private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
 
     init {
-        initNotificationBuilder()
-    }
-
-    private fun initNotificationBuilder() {
         notificationBuilder = NotificationUtils.newNotificationBuilder(context, viewThemeUtils).apply {
-            setContentTitle(context.getString(R.string.app_name))
-            setContentText(context.getString(R.string.worker_upload))
+            setContentTitle(context.getString(R.string.uploader_upload_in_progress_ticker))
             setSmallIcon(R.drawable.notification_icon)
             setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.notification_icon))
 
@@ -67,69 +58,77 @@ class UploadNotificationManager(private val context: Context, private val viewTh
     }
 
     @Suppress("MagicNumber")
-    fun notifyForStart(upload: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) {
+    fun prepareForStart(upload: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) {
         notificationBuilder = NotificationUtils.newNotificationBuilder(context, viewThemeUtils).apply {
-            setOngoing(true)
             setSmallIcon(R.drawable.notification_icon)
+            setOngoing(true)
             setTicker(context.getString(R.string.uploader_upload_in_progress_ticker))
             setContentTitle(context.getString(R.string.uploader_upload_in_progress_ticker))
             setProgress(100, 0, false)
             setContentText(
                 String.format(
-                    context.getString(R.string.uploader_upload_in_progress_content),
+                    context.getString(R.string.uploader_upload_in_progress),
                     0,
                     upload.fileName
                 )
             )
             clearActions()
+
             addAction(
                 R.drawable.ic_action_cancel_grey,
                 context.getString(R.string.common_cancel),
                 pendingIntent
             )
+
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD)
             }
+
             setContentIntent(startIntent)
         }
 
         if (!upload.isInstantPicture && !upload.isInstantVideo) {
-            showWorkerNotification()
+            showNotification()
         }
     }
 
-    fun notifyForResult(resultCode: RemoteOperationResult.ResultCode) {
+    fun notifyForResult(
+        resultCode: RemoteOperationResult.ResultCode,
+        resultIntent: PendingIntent,
+        credentialIntent: PendingIntent?,
+        errorMessage: String?
+    ) {
         val textId = resultText(resultCode)
 
-        notificationBuilder
-            .setTicker(context.getString(textId))
-            .setContentTitle(context.getString(textId))
-            .setAutoCancel(true)
-            .setOngoing(false)
-            .setProgress(0, 0, false)
-            .clearActions()
+        notificationBuilder.run {
+            setTicker(context.getString(textId))
+            setContentTitle(context.getString(textId))
+            setAutoCancel(true)
+            setOngoing(false)
+            setProgress(0, 0, false)
+            clearActions()
+            setContentIntent(resultIntent)
+
+            credentialIntent?.let {
+                setContentIntent(it)
+            }
+
+            errorMessage?.let {
+                setContentText(it)
+            }
+        }
     }
 
     private fun resultText(resultCode: RemoteOperationResult.ResultCode): Int {
-        var result = R.string.uploader_upload_failed_ticker
-
         val needsToUpdateCredentials = (resultCode == RemoteOperationResult.ResultCode.UNAUTHORIZED)
 
-        if (needsToUpdateCredentials) {
-            result = R.string.uploader_upload_failed_credentials_error
+        return if (needsToUpdateCredentials) {
+            R.string.uploader_upload_failed_credentials_error
         } else if (resultCode == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
-            result = R.string.uploader_upload_failed_sync_conflict_error
+            R.string.uploader_upload_failed_sync_conflict_error
+        } else {
+            R.string.uploader_upload_failed_ticker
         }
-
-        return result
-    }
-
-    fun setContentIntent(pendingIntent: PendingIntent) {
-        notificationBuilder.setContentIntent(pendingIntent)
-    }
-
-    fun setContentText(text: String) {
-        notificationBuilder.setContentText(text)
     }
 
     fun addAction(icon: Int, textId: Int, intent: PendingIntent) {
@@ -140,7 +139,7 @@ class UploadNotificationManager(private val context: Context, private val viewTh
         )
     }
 
-    fun showNotificationTag(operation: UploadFileOperation) {
+    fun showNewNotification(operation: UploadFileOperation) {
         notificationManager.notify(
             NotificationUtils.createUploadNotificationTag(operation.file),
             FileUploadWorker.NOTIFICATION_ERROR_ID,
@@ -148,24 +147,21 @@ class UploadNotificationManager(private val context: Context, private val viewTh
         )
     }
 
-    fun showRandomNotification() {
-        notificationManager.notify(secureRandomGenerator.nextInt(), notificationBuilder.build())
-    }
-
-    private fun showWorkerNotification() {
-        notificationManager.notify(WORKER_ID, notificationBuilder.build())
+    fun showNotification() {
+        notificationManager.notify(id, notificationBuilder.build())
     }
 
     @Suppress("MagicNumber")
-    fun updateUploadProgressNotification(filePath: String, percent: Int, currentOperation: UploadFileOperation?) {
-        notificationBuilder.setProgress(100, percent, false)
-
-        val fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1)
-        val text = String.format(context.getString(R.string.uploader_upload_in_progress_content), percent, fileName)
-
-        notificationBuilder.setContentText(text)
-        showWorkerNotification()
-        dismissOldErrorNotification(currentOperation)
+    fun updateUploadProgress(filePath: String, percent: Int, currentOperation: UploadFileOperation?) {
+        notificationBuilder.run {
+            setProgress(100, percent, false)
+            val fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1)
+            val text = String.format(context.getString(R.string.uploader_upload_in_progress), percent, fileName)
+            setContentText(text)
+
+            showNotification()
+            dismissOldErrorNotification(currentOperation)
+        }
     }
 
     fun dismissOldErrorNotification(operation: UploadFileOperation?) {
@@ -187,6 +183,6 @@ class UploadNotificationManager(private val context: Context, private val viewTh
     }
 
     fun dismissWorkerNotifications() {
-        notificationManager.cancel(WORKER_ID)
+        notificationManager.cancel(id)
     }
 }

+ 0 - 11
app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java

@@ -104,7 +104,6 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
     private final Handler handler = new Handler();
     private String accountName;
     private UserListAdapter userListAdapter;
-    private ServiceConnection uploadServiceConnection;
     private Set<String> originalUsers;
     private String originalCurrentUser;
 
@@ -351,16 +350,6 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         }
     }
 
-    @Override
-    protected void onDestroy() {
-        if (uploadServiceConnection != null) {
-            unbindService(uploadServiceConnection);
-            uploadServiceConnection = null;
-        }
-
-        super.onDestroy();
-    }
-
     public Handler getHandler() {
         return handler;
     }

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -141,6 +141,7 @@
     <string name="upload_chooser_title">Upload from…</string>
     <string name="uploader_info_dirname">Folder name</string>
     <string name="uploader_upload_in_progress_ticker">Uploading…</string>
+    <string name="uploader_upload_in_progress">%1$d%% %2$s</string>
     <string name="uploader_upload_in_progress_content">%1$d%% Uploading %2$s</string>
     <string name="uploader_upload_succeeded_content_single">%1$s uploaded</string>
     <string name="uploader_upload_failed_ticker">Upload failed</string>