|
@@ -26,23 +26,23 @@ import android.accounts.AccountManager
|
|
|
import android.accounts.OnAccountsUpdateListener
|
|
|
import android.app.PendingIntent
|
|
|
import android.content.Context
|
|
|
-import androidx.core.util.component1
|
|
|
-import androidx.core.util.component2
|
|
|
+import android.os.Binder
|
|
|
+import android.os.IBinder
|
|
|
+import android.util.Pair
|
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|
|
import androidx.work.Worker
|
|
|
import androidx.work.WorkerParameters
|
|
|
+import com.google.gson.Gson
|
|
|
import com.nextcloud.client.account.User
|
|
|
import com.nextcloud.client.account.UserAccountManager
|
|
|
+import com.nextcloud.client.notifications.download.DownloadNotificationManager
|
|
|
import com.nextcloud.java.util.Optional
|
|
|
-import com.nextcloud.model.WorkerState
|
|
|
-import com.nextcloud.model.WorkerStateLiveData
|
|
|
-import com.nextcloud.utils.ForegroundServiceHelper
|
|
|
-import com.owncloud.android.R
|
|
|
import com.owncloud.android.datamodel.FileDataStorageManager
|
|
|
-import com.owncloud.android.datamodel.ForegroundServiceType
|
|
|
import com.owncloud.android.datamodel.OCFile
|
|
|
+import com.owncloud.android.datamodel.UploadsStorageManager
|
|
|
import com.owncloud.android.files.services.IndexedForest
|
|
|
import com.owncloud.android.lib.common.OwnCloudAccount
|
|
|
+import com.owncloud.android.lib.common.OwnCloudClient
|
|
|
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
|
|
|
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
|
|
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
|
@@ -51,14 +51,14 @@ import com.owncloud.android.lib.common.utils.Log_OC
|
|
|
import com.owncloud.android.operations.DownloadFileOperation
|
|
|
import com.owncloud.android.operations.DownloadType
|
|
|
import com.owncloud.android.utils.theme.ViewThemeUtils
|
|
|
-import java.security.SecureRandom
|
|
|
import java.util.AbstractList
|
|
|
import java.util.Vector
|
|
|
|
|
|
-@Suppress("LongParameterList", "TooManyFunctions")
|
|
|
+@Suppress("LongParameterList")
|
|
|
class FileDownloadWorker(
|
|
|
private val viewThemeUtils: ViewThemeUtils,
|
|
|
private val accountManager: UserAccountManager,
|
|
|
+ private val uploadsStorageManager: UploadsStorageManager,
|
|
|
private var localBroadcastManager: LocalBroadcastManager,
|
|
|
private val context: Context,
|
|
|
params: WorkerParameters
|
|
@@ -67,30 +67,19 @@ class FileDownloadWorker(
|
|
|
companion object {
|
|
|
private val TAG = FileDownloadWorker::class.java.simpleName
|
|
|
|
|
|
- private val pendingDownloads = IndexedForest<DownloadFileOperation>()
|
|
|
-
|
|
|
- fun cancelOperation(accountName: String, fileId: Long) {
|
|
|
- pendingDownloads.all.forEach {
|
|
|
- it.value.payload?.cancelMatchingOperation(accountName, fileId)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const val WORKER_ID = "WORKER_ID"
|
|
|
- const val FILES_SEPARATOR = ","
|
|
|
- const val FOLDER_REMOTE_PATH = "FOLDER_REMOTE_PATH"
|
|
|
- const val FILE_REMOTE_PATH = "FILE_REMOTE_PATH"
|
|
|
- const val FILES_REMOTE_PATH = "FILES_REMOTE_PATH"
|
|
|
- const val ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
+ const val USER_NAME = "USER"
|
|
|
+ const val FILE = "FILE"
|
|
|
const val BEHAVIOUR = "BEHAVIOUR"
|
|
|
const val DOWNLOAD_TYPE = "DOWNLOAD_TYPE"
|
|
|
const val ACTIVITY_NAME = "ACTIVITY_NAME"
|
|
|
const val PACKAGE_NAME = "PACKAGE_NAME"
|
|
|
const val CONFLICT_UPLOAD_ID = "CONFLICT_UPLOAD_ID"
|
|
|
-
|
|
|
- const val EXTRA_DOWNLOAD_RESULT = "EXTRA_DOWNLOAD_RESULT"
|
|
|
- const val EXTRA_REMOTE_PATH = "EXTRA_REMOTE_PATH"
|
|
|
- const val EXTRA_LINKED_TO_PATH = "EXTRA_LINKED_TO_PATH"
|
|
|
- const val EXTRA_ACCOUNT_NAME = "EXTRA_ACCOUNT_NAME"
|
|
|
+ const val EXTRA_USER = "USER"
|
|
|
+ const val EXTRA_FILE = "FILE"
|
|
|
+ const val EXTRA_DOWNLOAD_RESULT = "RESULT"
|
|
|
+ const val EXTRA_REMOTE_PATH = "REMOTE_PATH"
|
|
|
+ const val EXTRA_LINKED_TO_PATH = "LINKED_TO"
|
|
|
+ const val ACCOUNT_NAME = "ACCOUNT_NAME"
|
|
|
|
|
|
fun getDownloadAddedMessage(): String {
|
|
|
return FileDownloadWorker::class.java.name + "DOWNLOAD_ADDED"
|
|
@@ -102,223 +91,116 @@ class FileDownloadWorker(
|
|
|
}
|
|
|
|
|
|
private var currentDownload: DownloadFileOperation? = null
|
|
|
-
|
|
|
private var conflictUploadId: Long? = null
|
|
|
private var lastPercent = 0
|
|
|
-
|
|
|
private val intents = FileDownloadIntents(context)
|
|
|
- private lateinit var notificationManager: DownloadNotificationManager
|
|
|
- private var downloadProgressListener = FileDownloadProgressListener()
|
|
|
-
|
|
|
- private var user: User? = null
|
|
|
+ private val notificationManager = DownloadNotificationManager(context, viewThemeUtils)
|
|
|
+ private val pendingDownloads = IndexedForest<DownloadFileOperation>()
|
|
|
+ private var downloadBinder: IBinder = FileDownloaderBinder()
|
|
|
private var currentUser = Optional.empty<User>()
|
|
|
-
|
|
|
- private var currentUserFileStorageManager: FileDataStorageManager? = null
|
|
|
- private var fileDataStorageManager: FileDataStorageManager? = null
|
|
|
-
|
|
|
- private var workerId: Int? = null
|
|
|
- private var folder: OCFile? = null
|
|
|
- private var isAnyOperationFailed = false
|
|
|
+ private val helper = FileDownloadHelper()
|
|
|
+ private var startedDownload = false
|
|
|
+ private var storageManager: FileDataStorageManager? = null
|
|
|
+ private var downloadClient: OwnCloudClient? = null
|
|
|
+ private val gson = Gson()
|
|
|
|
|
|
@Suppress("TooGenericExceptionCaught")
|
|
|
override fun doWork(): Result {
|
|
|
return try {
|
|
|
val requestDownloads = getRequestDownloads()
|
|
|
- notificationManager =
|
|
|
- DownloadNotificationManager(workerId ?: SecureRandom().nextInt(), context, viewThemeUtils)
|
|
|
|
|
|
+ notificationManager.init()
|
|
|
addAccountUpdateListener()
|
|
|
-
|
|
|
- val foregroundInfo = ForegroundServiceHelper.createWorkerForegroundInfo(
|
|
|
- notificationManager.getId(),
|
|
|
- notificationManager.getNotification(),
|
|
|
- ForegroundServiceType.DataSync
|
|
|
- )
|
|
|
- setForegroundAsync(foregroundInfo)
|
|
|
-
|
|
|
- requestDownloads.forEach {
|
|
|
- downloadFile(it)
|
|
|
- }
|
|
|
-
|
|
|
- showSuccessNotification()
|
|
|
- setIdleWorkerState()
|
|
|
+ startDownloadForEachRequest(requestDownloads)
|
|
|
|
|
|
Log_OC.e(TAG, "FilesDownloadWorker successfully completed")
|
|
|
Result.success()
|
|
|
} catch (t: Throwable) {
|
|
|
- notificationManager.showCompleteNotification(context.getString(R.string.downloader_unexpected_error))
|
|
|
Log_OC.e(TAG, "Error caught at FilesDownloadWorker(): " + t.localizedMessage)
|
|
|
- setIdleWorkerState()
|
|
|
Result.failure()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- override fun onStopped() {
|
|
|
- Log_OC.e(TAG, "FilesDownloadWorker stopped")
|
|
|
-
|
|
|
- notificationManager.dismissNotification()
|
|
|
- cancelAllDownloads()
|
|
|
- removePendingDownload(currentDownload?.user?.accountName)
|
|
|
- setIdleWorkerState()
|
|
|
-
|
|
|
- super.onStopped()
|
|
|
- }
|
|
|
-
|
|
|
- private fun setWorkerState(user: User?) {
|
|
|
- WorkerStateLiveData.instance().setWorkState(WorkerState.Download(user, currentDownload))
|
|
|
- }
|
|
|
-
|
|
|
- private fun setIdleWorkerState() {
|
|
|
- currentDownload = null
|
|
|
- WorkerStateLiveData.instance().setWorkState(WorkerState.Idle)
|
|
|
- }
|
|
|
-
|
|
|
- private fun cancelAllDownloads() {
|
|
|
- pendingDownloads.all.forEach {
|
|
|
- it.value.payload?.cancel()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private fun removePendingDownload(accountName: String?) {
|
|
|
- pendingDownloads.remove(accountName)
|
|
|
- }
|
|
|
-
|
|
|
- @Suppress("MagicNumber")
|
|
|
- private fun showSuccessNotification() {
|
|
|
- if (isAnyOperationFailed) {
|
|
|
- notificationManager.dismissNotification()
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- val successText = if (folder != null) {
|
|
|
- context.getString(R.string.downloader_folder_downloaded, folder?.fileName)
|
|
|
- } else if (currentDownload?.file != null) {
|
|
|
- context.getString(R.string.downloader_file_downloaded, currentDownload?.file?.fileName)
|
|
|
- } else {
|
|
|
- context.getString(R.string.downloader_download_completed)
|
|
|
- }
|
|
|
-
|
|
|
- notificationManager.showCompleteNotification(successText)
|
|
|
- }
|
|
|
-
|
|
|
private fun getRequestDownloads(): AbstractList<String> {
|
|
|
- workerId = inputData.keyValueMap[WORKER_ID] as Int
|
|
|
-
|
|
|
- isAnyOperationFailed = false
|
|
|
- setUser()
|
|
|
- setFolder()
|
|
|
- val files = getFiles()
|
|
|
- val downloadType = getDownloadType()
|
|
|
-
|
|
|
conflictUploadId = inputData.keyValueMap[CONFLICT_UPLOAD_ID] as Long?
|
|
|
- val behaviour = inputData.keyValueMap[BEHAVIOUR] as String? ?: ""
|
|
|
- val activityName = inputData.keyValueMap[ACTIVITY_NAME] as String? ?: ""
|
|
|
- val packageName = inputData.keyValueMap[PACKAGE_NAME] as String? ?: ""
|
|
|
+ val file = gson.fromJson(inputData.keyValueMap[FILE] as String, OCFile::class.java)
|
|
|
+ val accountName = inputData.keyValueMap[USER_NAME] as String
|
|
|
+ val user = accountManager.getUser(accountName).get()
|
|
|
+ val downloadTypeAsString = inputData.keyValueMap[DOWNLOAD_TYPE] as String?
|
|
|
+ val downloadType = if (downloadTypeAsString != null) {
|
|
|
+ if (downloadTypeAsString == DownloadType.DOWNLOAD.toString()) {
|
|
|
+ DownloadType.DOWNLOAD
|
|
|
+ } else {
|
|
|
+ DownloadType.EXPORT
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ null
|
|
|
+ }
|
|
|
+ val behaviour = inputData.keyValueMap[BEHAVIOUR] as String
|
|
|
+ val activityName = inputData.keyValueMap[ACTIVITY_NAME] as String
|
|
|
+ val packageName = inputData.keyValueMap[PACKAGE_NAME] as String
|
|
|
|
|
|
val requestedDownloads: AbstractList<String> = Vector()
|
|
|
|
|
|
- return try {
|
|
|
- files.forEach { file ->
|
|
|
- val operation = DownloadFileOperation(
|
|
|
- user,
|
|
|
- file,
|
|
|
- behaviour,
|
|
|
- activityName,
|
|
|
- packageName,
|
|
|
- context,
|
|
|
- downloadType
|
|
|
- )
|
|
|
-
|
|
|
- operation.addDownloadDataTransferProgressListener(this)
|
|
|
- operation.addDownloadDataTransferProgressListener(downloadProgressListener)
|
|
|
- val (downloadKey, linkedToRemotePath) = pendingDownloads.putIfAbsent(
|
|
|
- user?.accountName,
|
|
|
- file.remotePath,
|
|
|
- operation
|
|
|
- )
|
|
|
-
|
|
|
- if (downloadKey != null) {
|
|
|
- requestedDownloads.add(downloadKey)
|
|
|
- localBroadcastManager.sendBroadcast(intents.newDownloadIntent(operation, linkedToRemotePath))
|
|
|
- }
|
|
|
- }
|
|
|
+ try {
|
|
|
+ val operation = DownloadFileOperation(
|
|
|
+ user,
|
|
|
+ file,
|
|
|
+ behaviour,
|
|
|
+ activityName,
|
|
|
+ packageName,
|
|
|
+ context,
|
|
|
+ downloadType
|
|
|
+ )
|
|
|
+ operation.addDatatransferProgressListener(this)
|
|
|
+ operation.addDatatransferProgressListener(downloadBinder as FileDownloaderBinder)
|
|
|
+ val putResult = pendingDownloads.putIfAbsent(
|
|
|
+ user?.accountName,
|
|
|
+ file.remotePath,
|
|
|
+ operation
|
|
|
+ )
|
|
|
|
|
|
- requestedDownloads
|
|
|
+ if (putResult != null) {
|
|
|
+ val downloadKey = putResult.first
|
|
|
+ requestedDownloads.add(downloadKey)
|
|
|
+ localBroadcastManager.sendBroadcast(intents.newDownloadIntent(operation, putResult.second))
|
|
|
+ }
|
|
|
} catch (e: IllegalArgumentException) {
|
|
|
Log_OC.e(TAG, "Not enough information provided in intent: " + e.message)
|
|
|
- requestedDownloads
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- private fun setUser() {
|
|
|
- val accountName = inputData.keyValueMap[ACCOUNT_NAME] as String
|
|
|
- user = accountManager.getUser(accountName).get()
|
|
|
- fileDataStorageManager = FileDataStorageManager(user, context.contentResolver)
|
|
|
+ return requestedDownloads
|
|
|
}
|
|
|
|
|
|
- private fun setFolder() {
|
|
|
- val folderPath = inputData.keyValueMap[FOLDER_REMOTE_PATH] as? String?
|
|
|
- if (folderPath != null) {
|
|
|
- folder = fileDataStorageManager?.getFileByEncryptedRemotePath(folderPath)
|
|
|
- }
|
|
|
+ private fun addAccountUpdateListener() {
|
|
|
+ val am = AccountManager.get(context)
|
|
|
+ am.addOnAccountsUpdatedListener(this, null, false)
|
|
|
}
|
|
|
|
|
|
- private fun getFiles(): List<OCFile> {
|
|
|
- val result = arrayListOf<OCFile>()
|
|
|
-
|
|
|
- val filesPath = inputData.keyValueMap[FILES_REMOTE_PATH] as String?
|
|
|
- val filesPathList = filesPath?.split(FILES_SEPARATOR)
|
|
|
+ private fun startDownloadForEachRequest(requestDownloads: AbstractList<String>) {
|
|
|
+ val it: Iterator<String> = requestDownloads.iterator()
|
|
|
|
|
|
- if (filesPathList != null) {
|
|
|
- filesPathList.forEach {
|
|
|
- fileDataStorageManager?.getFileByEncryptedRemotePath(it)?.let { file ->
|
|
|
- result.add(file)
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- val remotePath = inputData.keyValueMap[FILE_REMOTE_PATH] as String
|
|
|
- fileDataStorageManager?.getFileByEncryptedRemotePath(remotePath)?.let { file ->
|
|
|
- result.add(file)
|
|
|
- }
|
|
|
+ while (it.hasNext()) {
|
|
|
+ val next = it.next()
|
|
|
+ Log_OC.e(TAG, "Download Key: $next")
|
|
|
+ downloadFile(next)
|
|
|
}
|
|
|
|
|
|
- return result
|
|
|
- }
|
|
|
-
|
|
|
- private fun getDownloadType(): DownloadType? {
|
|
|
- val typeAsString = inputData.keyValueMap[DOWNLOAD_TYPE] as String?
|
|
|
- return if (typeAsString != null) {
|
|
|
- if (typeAsString == DownloadType.DOWNLOAD.toString()) {
|
|
|
- DownloadType.DOWNLOAD
|
|
|
- } else {
|
|
|
- DownloadType.EXPORT
|
|
|
- }
|
|
|
- } else {
|
|
|
- null
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private fun addAccountUpdateListener() {
|
|
|
- val am = AccountManager.get(context)
|
|
|
- am.addOnAccountsUpdatedListener(this, null, false)
|
|
|
+ startedDownload = false
|
|
|
}
|
|
|
|
|
|
@Suppress("TooGenericExceptionCaught")
|
|
|
private fun downloadFile(downloadKey: String) {
|
|
|
+ startedDownload = true
|
|
|
currentDownload = pendingDownloads.get(downloadKey)
|
|
|
|
|
|
if (currentDownload == null) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- val fileName = currentDownload?.file?.fileName
|
|
|
-
|
|
|
- setWorkerState(user)
|
|
|
- Log_OC.e(TAG, "FilesDownloadWorker downloading: $downloadKey")
|
|
|
-
|
|
|
val isAccountExist = accountManager.exists(currentDownload?.user?.toPlatformAccount())
|
|
|
if (!isAccountExist) {
|
|
|
- removePendingDownload(currentDownload?.user?.accountName)
|
|
|
+ cancelPendingDownloads(currentDownload?.user?.accountName)
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -326,30 +208,33 @@ class FileDownloadWorker(
|
|
|
var downloadResult: RemoteOperationResult<*>? = null
|
|
|
try {
|
|
|
val ocAccount = getOCAccountForDownload()
|
|
|
- val downloadClient =
|
|
|
+ downloadClient =
|
|
|
OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context)
|
|
|
|
|
|
downloadResult = currentDownload?.execute(downloadClient)
|
|
|
if (downloadResult?.isSuccess == true && currentDownload?.downloadType === DownloadType.DOWNLOAD) {
|
|
|
getCurrentFile()?.let {
|
|
|
- FileDownloadHelper.instance().saveFile(it, currentDownload, currentUserFileStorageManager)
|
|
|
+ helper.saveFile(it, currentDownload, storageManager)
|
|
|
}
|
|
|
}
|
|
|
} catch (e: Exception) {
|
|
|
Log_OC.e(TAG, "Error downloading", e)
|
|
|
downloadResult = RemoteOperationResult<Any?>(e)
|
|
|
} finally {
|
|
|
- cleanupDownloadProcess(downloadResult, fileName)
|
|
|
+ cleanupDownloadProcess(downloadResult)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private fun cancelPendingDownloads(accountName: String?) {
|
|
|
+ pendingDownloads.remove(accountName)
|
|
|
+ }
|
|
|
+
|
|
|
private fun notifyDownloadStart(download: DownloadFileOperation) {
|
|
|
lastPercent = 0
|
|
|
|
|
|
- notificationManager.run {
|
|
|
- prepareForStart(download)
|
|
|
- setContentIntent(intents.detailsIntent(download), PendingIntent.FLAG_IMMUTABLE)
|
|
|
- }
|
|
|
+ notificationManager.notifyForStart(download)
|
|
|
+ notificationManager.setContentIntent(intents.detailsIntent(download), PendingIntent.FLAG_IMMUTABLE)
|
|
|
+ notificationManager.showDownloadInProgressNotification()
|
|
|
}
|
|
|
|
|
|
private fun getOCAccountForDownload(): OwnCloudAccount {
|
|
@@ -357,16 +242,16 @@ class FileDownloadWorker(
|
|
|
val currentDownloadUser = accountManager.getUser(currentDownloadAccount?.name)
|
|
|
if (currentUser != currentDownloadUser) {
|
|
|
currentUser = currentDownloadUser
|
|
|
- currentUserFileStorageManager = FileDataStorageManager(currentUser.get(), context.contentResolver)
|
|
|
+ storageManager = FileDataStorageManager(currentUser.get(), context.contentResolver)
|
|
|
}
|
|
|
return currentDownloadUser.get().toOwnCloudAccount()
|
|
|
}
|
|
|
|
|
|
private fun getCurrentFile(): OCFile? {
|
|
|
- var file: OCFile? = currentDownload?.file?.fileId?.let { currentUserFileStorageManager?.getFileById(it) }
|
|
|
+ var file: OCFile? = currentDownload?.file?.fileId?.let { storageManager?.getFileById(it) }
|
|
|
|
|
|
if (file == null) {
|
|
|
- file = currentUserFileStorageManager?.getFileByDecryptedRemotePath(currentDownload?.file?.remotePath)
|
|
|
+ file = storageManager?.getFileByDecryptedRemotePath(currentDownload?.file?.remotePath)
|
|
|
}
|
|
|
|
|
|
if (file == null) {
|
|
@@ -377,11 +262,7 @@ class FileDownloadWorker(
|
|
|
return file
|
|
|
}
|
|
|
|
|
|
- private fun cleanupDownloadProcess(result: RemoteOperationResult<*>?, fileName: String?) {
|
|
|
- result?.let {
|
|
|
- showFailedDownloadNotifications(it, fileName)
|
|
|
- }
|
|
|
-
|
|
|
+ private fun cleanupDownloadProcess(result: RemoteOperationResult<*>?) {
|
|
|
val removeResult = pendingDownloads.removePayload(
|
|
|
currentDownload?.user?.accountName,
|
|
|
currentDownload?.remotePath
|
|
@@ -391,39 +272,15 @@ class FileDownloadWorker(
|
|
|
|
|
|
currentDownload?.run {
|
|
|
notifyDownloadResult(this, downloadResult)
|
|
|
-
|
|
|
val downloadFinishedIntent = intents.downloadFinishedIntent(
|
|
|
this,
|
|
|
downloadResult,
|
|
|
removeResult.second
|
|
|
)
|
|
|
-
|
|
|
localBroadcastManager.sendBroadcast(downloadFinishedIntent)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private fun showFailedDownloadNotifications(result: RemoteOperationResult<*>, fileName: String?) {
|
|
|
- if (result.isSuccess) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- isAnyOperationFailed = true
|
|
|
-
|
|
|
- val failMessage = if (result.isCancelled) {
|
|
|
- context.getString(
|
|
|
- R.string.downloader_file_download_cancelled,
|
|
|
- fileName
|
|
|
- )
|
|
|
- } else {
|
|
|
- context.getString(
|
|
|
- R.string.downloader_file_download_failed,
|
|
|
- fileName
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- notificationManager.showNewNotification(failMessage)
|
|
|
- }
|
|
|
-
|
|
|
private fun notifyDownloadResult(
|
|
|
download: DownloadFileOperation,
|
|
|
downloadResult: RemoteOperationResult<*>
|
|
@@ -432,20 +289,31 @@ class FileDownloadWorker(
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ if (downloadResult.isSuccess) {
|
|
|
+ dismissDownloadInProgressNotification()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
val needsToUpdateCredentials = (ResultCode.UNAUTHORIZED == downloadResult.code)
|
|
|
- notificationManager.run {
|
|
|
- prepareForResult()
|
|
|
-
|
|
|
- if (needsToUpdateCredentials) {
|
|
|
- showNewNotification(context.getString(R.string.downloader_download_failed_credentials_error))
|
|
|
- setContentIntent(
|
|
|
- intents.credentialContentIntent(download.user),
|
|
|
- PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
|
|
|
- )
|
|
|
- } else {
|
|
|
- setContentIntent(intents.detailsIntent(null), PendingIntent.FLAG_IMMUTABLE)
|
|
|
+ notificationManager.prepareForResult(downloadResult, needsToUpdateCredentials)
|
|
|
+
|
|
|
+ if (needsToUpdateCredentials) {
|
|
|
+ notificationManager.setCredentialContentIntent(download.user)
|
|
|
+ } else {
|
|
|
+ notificationManager.setContentIntent(intents.detailsIntent(null), PendingIntent.FLAG_IMMUTABLE)
|
|
|
+ }
|
|
|
+
|
|
|
+ notificationManager.notifyForResult(downloadResult, download)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun dismissDownloadInProgressNotification() {
|
|
|
+ conflictUploadId?.let {
|
|
|
+ if (it > 0) {
|
|
|
+ uploadsStorageManager.removeUpload(it)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ notificationManager.dismissDownloadInProgressNotification()
|
|
|
}
|
|
|
|
|
|
override fun onAccountsUpdated(accounts: Array<out Account>?) {
|
|
@@ -464,19 +332,43 @@ class FileDownloadWorker(
|
|
|
val percent: Int = (100.0 * totalTransferredSoFar.toDouble() / totalToTransfer.toDouble()).toInt()
|
|
|
|
|
|
if (percent != lastPercent) {
|
|
|
- notificationManager.run {
|
|
|
- updateDownloadProgress(filePath, percent, totalToTransfer)
|
|
|
- }
|
|
|
+ notificationManager.updateDownloadProgressNotification(filePath, percent, totalToTransfer)
|
|
|
+ notificationManager.showDownloadInProgressNotification()
|
|
|
}
|
|
|
|
|
|
lastPercent = percent
|
|
|
}
|
|
|
|
|
|
- inner class FileDownloadProgressListener : OnDatatransferProgressListener {
|
|
|
+ inner class FileDownloaderBinder : Binder(), OnDatatransferProgressListener {
|
|
|
private val boundListeners: MutableMap<Long, OnDatatransferProgressListener> = HashMap()
|
|
|
|
|
|
+ fun cancelPendingOrCurrentDownloads(account: Account, file: OCFile) {
|
|
|
+ val removeResult: Pair<DownloadFileOperation, String> =
|
|
|
+ pendingDownloads.remove(account.name, file.remotePath)
|
|
|
+ val download = removeResult.first
|
|
|
+
|
|
|
+ if (download != null) {
|
|
|
+ download.cancel()
|
|
|
+ } else {
|
|
|
+ if (currentUser?.isPresent == true &&
|
|
|
+ currentDownload?.remotePath?.startsWith(file.remotePath) == true &&
|
|
|
+ account.name == currentUser.get()?.accountName
|
|
|
+ ) {
|
|
|
+ currentDownload?.cancel()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun cancelAllDownloadsForAccount(accountName: String?) {
|
|
|
+ if (currentDownload?.user?.nameEquals(accountName) == true) {
|
|
|
+ currentDownload?.cancel()
|
|
|
+ }
|
|
|
+
|
|
|
+ cancelPendingDownloads(accountName)
|
|
|
+ }
|
|
|
+
|
|
|
fun isDownloading(user: User?, file: OCFile?): Boolean {
|
|
|
- return FileDownloadHelper.instance().isDownloading(user, file)
|
|
|
+ return user != null && file != null && pendingDownloads.contains(user.accountName, file.remotePath)
|
|
|
}
|
|
|
|
|
|
fun addDataTransferProgressListener(listener: OnDatatransferProgressListener?, file: OCFile?) {
|