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
|
package com.kunzisoft.keepass.notifications
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
@@ -29,7 +30,8 @@ import androidx.documentfile.provider.DocumentFile
|
|||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.model.AttachmentState
|
import com.kunzisoft.keepass.model.AttachmentState
|
||||||
import com.kunzisoft.keepass.model.EntryAttachment
|
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 java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
@@ -41,6 +43,8 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
|||||||
private var mActionTaskBinder = ActionTaskBinder()
|
private var mActionTaskBinder = ActionTaskBinder()
|
||||||
private var mActionTaskListeners = LinkedList<ActionTaskListener>()
|
private var mActionTaskListeners = LinkedList<ActionTaskListener>()
|
||||||
|
|
||||||
|
private val mainScope = CoroutineScope(Dispatchers.Main)
|
||||||
|
|
||||||
inner class ActionTaskBinder: Binder() {
|
inner class ActionTaskBinder: Binder() {
|
||||||
|
|
||||||
fun getService(): AttachmentFileNotificationService = this@AttachmentFileNotificationService
|
fun getService(): AttachmentFileNotificationService = this@AttachmentFileNotificationService
|
||||||
@@ -99,7 +103,9 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
|||||||
intent.getParcelableExtra<EntryAttachment>(ATTACHMENT_KEY)?.let { entryAttachment ->
|
intent.getParcelableExtra<EntryAttachment>(ATTACHMENT_KEY)?.let { entryAttachment ->
|
||||||
val attachmentNotification = AttachmentNotification(nextNotificationId, entryAttachment)
|
val attachmentNotification = AttachmentNotification(nextNotificationId, entryAttachment)
|
||||||
downloadFileUris[downloadFileUri] = attachmentNotification
|
downloadFileUris[downloadFileUri] = attachmentNotification
|
||||||
AttachmentFileAsyncTask(downloadFileUri,
|
|
||||||
|
mainScope.launch {
|
||||||
|
AttachmentFileActionClass(downloadFileUri,
|
||||||
attachmentNotification,
|
attachmentNotification,
|
||||||
contentResolver).apply {
|
contentResolver).apply {
|
||||||
onUpdate = { uri, attachment, notificationIdAttach ->
|
onUpdate = { uri, attachment, notificationIdAttach ->
|
||||||
@@ -108,7 +114,8 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
|||||||
actionListener.onAttachmentProgress(downloadFileUri, attachment)
|
actionListener.onAttachmentProgress(downloadFileUri, attachment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute()
|
}.executeAction()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Unable to download $downloadFileUri", e)
|
Log.e(TAG, "Unable to download $downloadFileUri", e)
|
||||||
@@ -202,9 +209,9 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AttachmentNotification(var notificationId: Int,
|
private data class AttachmentNotification(var notificationId: Int,
|
||||||
var entryAttachment: EntryAttachment,
|
var entryAttachment: EntryAttachment,
|
||||||
var attachmentTask: AttachmentFileAsyncTask? = null) {
|
var attachmentTask: AttachmentFileActionClass? = null) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
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 {
|
companion object {
|
||||||
private val TAG = AttachmentFileNotificationService::javaClass.name
|
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