mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Attachment download as coroutine
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
package com.kunzisoft.keepass.notifications
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.ContentResolver
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
@@ -29,7 +30,8 @@ import androidx.documentfile.provider.DocumentFile
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachment
|
||||
import com.kunzisoft.keepass.tasks.AttachmentFileAsyncTask
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
@@ -41,6 +43,8 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
private var mActionTaskBinder = ActionTaskBinder()
|
||||
private var mActionTaskListeners = LinkedList<ActionTaskListener>()
|
||||
|
||||
private val mainScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
inner class ActionTaskBinder: Binder() {
|
||||
|
||||
fun getService(): AttachmentFileNotificationService = this@AttachmentFileNotificationService
|
||||
@@ -99,16 +103,19 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
intent.getParcelableExtra<EntryAttachment>(ATTACHMENT_KEY)?.let { entryAttachment ->
|
||||
val attachmentNotification = AttachmentNotification(nextNotificationId, entryAttachment)
|
||||
downloadFileUris[downloadFileUri] = attachmentNotification
|
||||
AttachmentFileAsyncTask(downloadFileUri,
|
||||
attachmentNotification,
|
||||
contentResolver).apply {
|
||||
onUpdate = { uri, attachment, notificationIdAttach ->
|
||||
newNotification(uri, attachment, notificationIdAttach)
|
||||
mActionTaskListeners.forEach { actionListener ->
|
||||
actionListener.onAttachmentProgress(downloadFileUri, attachment)
|
||||
|
||||
mainScope.launch {
|
||||
AttachmentFileActionClass(downloadFileUri,
|
||||
attachmentNotification,
|
||||
contentResolver).apply {
|
||||
onUpdate = { uri, attachment, notificationIdAttach ->
|
||||
newNotification(uri, attachment, notificationIdAttach)
|
||||
mActionTaskListeners.forEach { actionListener ->
|
||||
actionListener.onAttachmentProgress(downloadFileUri, attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute()
|
||||
}.executeAction()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to download $downloadFileUri", e)
|
||||
@@ -202,9 +209,9 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
data class AttachmentNotification(var notificationId: Int,
|
||||
private data class AttachmentNotification(var notificationId: Int,
|
||||
var entryAttachment: EntryAttachment,
|
||||
var attachmentTask: AttachmentFileAsyncTask? = null) {
|
||||
var attachmentTask: AttachmentFileActionClass? = null) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
@@ -221,6 +228,78 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
}
|
||||
}
|
||||
|
||||
private class AttachmentFileActionClass(
|
||||
private val fileUri: Uri,
|
||||
private val attachmentNotification: AttachmentNotification,
|
||||
private val contentResolver: ContentResolver) {
|
||||
|
||||
private val updateMinFrequency = 1000
|
||||
private var previousSaveTime = System.currentTimeMillis()
|
||||
var onUpdate: ((Uri, EntryAttachment, Int)->Unit)? = null
|
||||
|
||||
suspend fun executeAction() {
|
||||
TimeoutHelper.temporarilyDisableTimeout()
|
||||
|
||||
// on pre execute
|
||||
attachmentNotification.attachmentTask = this
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.START
|
||||
downloadProgression = 0
|
||||
}
|
||||
onUpdate?.invoke(fileUri,
|
||||
attachmentNotification.entryAttachment,
|
||||
attachmentNotification.notificationId)
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
// on Progress with thread
|
||||
val asyncResult: Deferred<Boolean> = async {
|
||||
var progressResult = true
|
||||
try {
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.IN_PROGRESS
|
||||
binaryAttachment.download(fileUri, contentResolver, 1024) { percent ->
|
||||
// Publish progress
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (previousSaveTime + updateMinFrequency < currentTime) {
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.IN_PROGRESS
|
||||
downloadProgression = percent
|
||||
}
|
||||
onUpdate?.invoke(fileUri,
|
||||
attachmentNotification.entryAttachment,
|
||||
attachmentNotification.notificationId)
|
||||
Log.d(TAG, "Download file $fileUri : $percent%")
|
||||
previousSaveTime = currentTime
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
progressResult = false
|
||||
}
|
||||
progressResult
|
||||
}
|
||||
|
||||
// on post execute
|
||||
withContext(Dispatchers.Main) {
|
||||
val result = asyncResult.await()
|
||||
attachmentNotification.attachmentTask = null
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = if (result) AttachmentState.COMPLETE else AttachmentState.ERROR
|
||||
downloadProgression = 100
|
||||
}
|
||||
onUpdate?.invoke(fileUri,
|
||||
attachmentNotification.entryAttachment,
|
||||
attachmentNotification.notificationId)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = AttachmentFileActionClass::class.java.name
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = AttachmentFileNotificationService::javaClass.name
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.tasks
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachment
|
||||
import com.kunzisoft.keepass.notifications.AttachmentFileNotificationService
|
||||
|
||||
class AttachmentFileAsyncTask(
|
||||
private val fileUri: Uri,
|
||||
private val attachmentNotification: AttachmentFileNotificationService.AttachmentNotification,
|
||||
private val contentResolver: ContentResolver)
|
||||
: AsyncTask<Void, Int, Boolean>() {
|
||||
|
||||
private val updateMinFrequency = 1000
|
||||
private var previousSaveTime = System.currentTimeMillis()
|
||||
var onUpdate: ((Uri, EntryAttachment, Int)->Unit)? = null
|
||||
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
attachmentNotification.attachmentTask = this
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.START
|
||||
downloadProgression = 0
|
||||
}
|
||||
onUpdate?.invoke(fileUri, attachmentNotification.entryAttachment, attachmentNotification.notificationId)
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Void?): Boolean {
|
||||
try {
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.IN_PROGRESS
|
||||
binaryAttachment.download(fileUri, contentResolver, 1024) { percent ->
|
||||
publishProgress(percent)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onProgressUpdate(vararg values: Int?) {
|
||||
super.onProgressUpdate(*values)
|
||||
val percent = values[0] ?: 0
|
||||
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (previousSaveTime + updateMinFrequency < currentTime) {
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = AttachmentState.IN_PROGRESS
|
||||
downloadProgression = percent
|
||||
}
|
||||
onUpdate?.invoke(fileUri, attachmentNotification.entryAttachment, attachmentNotification.notificationId)
|
||||
Log.d(TAG, "Download file $fileUri : $percent%")
|
||||
previousSaveTime = currentTime
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: Boolean) {
|
||||
super.onPostExecute(result)
|
||||
attachmentNotification.attachmentTask = null
|
||||
attachmentNotification.entryAttachment.apply {
|
||||
downloadState = if (result) AttachmentState.COMPLETE else AttachmentState.ERROR
|
||||
downloadProgression = 100
|
||||
}
|
||||
onUpdate?.invoke(fileUri, attachmentNotification.entryAttachment, attachmentNotification.notificationId)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = AttachmentFileAsyncTask::class.java.name
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user