From 2637788429dbc984c176c50ac368a967e6f84607 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 16 Oct 2019 15:31:07 +0200 Subject: [PATCH] Fix dialog update --- .../database/action/ProgressDialogThread.kt | 99 +++++++++++++++---- .../DatabaseTaskNotificationService.kt | 77 ++++++++++----- .../tasks/ProgressTaskDialogFragment.kt | 38 +++++-- .../keepass/utils/BroadcastAction.kt | 2 - 4 files changed, 162 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index e3ade1b6b..0aeea41c3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -1,12 +1,10 @@ package com.kunzisoft.keepass.database.action -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter +import android.content.* +import android.content.Context.BIND_ABOVE_CLIENT +import android.content.Context.BIND_NOT_FOREGROUND import android.net.Uri -import android.os.Build -import android.os.Bundle +import android.os.* import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.* @@ -23,38 +21,102 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_TASK_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CHECK_ACTION import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_SUBTITLE_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.START_ACTION +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.STOP_ACTION +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.UPDATE_ACTION_ELEMENTS import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment +import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.UNDEFINED import com.kunzisoft.keepass.timeout.TimeoutHelper -import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION import java.io.File import java.util.* import kotlin.collections.ArrayList + class ProgressDialogThread(private val activity: FragmentActivity, var onActionFinish: (actionTask: String, - result: ActionRunnable.Result) -> Unit) { + result: ActionRunnable.Result) -> Unit) { private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null - private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null - private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java) - private fun startDialog(intent: Intent) { + private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null + + private var actionMessenger: Messenger? = null + private var serviceConnection = object: ServiceConnection { + override fun onServiceDisconnected(name: ComponentName?) { + actionMessenger = null + } + + override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { + actionMessenger = Messenger(serviceBinder) + try { + val message = Message.obtain(null, CHECK_ACTION) + message.replyTo = Messenger(ResponseHandler(activity, onActionFinish)) + actionMessenger?.send(message) + } catch (e: RemoteException) { + e.printStackTrace() + } + } + } + + private class ResponseHandler(private val activity: FragmentActivity, + var onActionFinish: (actionTask: String, + result: ActionRunnable.Result) -> Unit) : Handler() { + override fun handleMessage(message: Message) { + when (message.what) { + START_ACTION -> { + TimeoutHelper.temporarilyDisableTimeout() + ProgressTaskDialogFragment.start(activity, + ProgressTaskDialogFragment.build()) + } + STOP_ACTION -> { + ProgressTaskDialogFragment.stop(activity) + TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) + val dataBundle = message.data + if (dataBundle != null + && dataBundle.containsKey(ACTION_TASK_KEY) + && dataBundle.containsKey(RESULT_KEY)) + onActionFinish.invoke( + dataBundle.getString(ACTION_TASK_KEY)!!, + ActionRunnable.Result.fromBundle(dataBundle.getBundle(RESULT_KEY)!!)) + } + UPDATE_ACTION_ELEMENTS -> { + // TODO better implementation + val dataBundle = message.data + if (dataBundle != null) { + if (dataBundle.containsKey(DATABASE_TASK_TITLE_KEY)) + ProgressTaskDialogFragment.updateTitle(activity, + message.data.getInt(DATABASE_TASK_TITLE_KEY)) + if (dataBundle.containsKey(DATABASE_TASK_MESSAGE_KEY)) + ProgressTaskDialogFragment.updateMessage(activity, + message.data.getInt(DATABASE_TASK_MESSAGE_KEY)) + if (dataBundle.containsKey(DATABASE_TASK_WARNING_KEY)) + ProgressTaskDialogFragment.updateWarning(activity, + message.data.getInt(DATABASE_TASK_WARNING_KEY)) + } + } + } + } + } + + private fun startDialog(intent: Intent? = null) { TimeoutHelper.temporarilyDisableTimeout() + // Show the dialog - progressTaskDialogFragment = ProgressTaskDialogFragment.build( - intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database), - intent.getIntExtra(DATABASE_TASK_SUBTITLE_KEY, ProgressTaskDialogFragment.UNDEFINED), - intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, ProgressTaskDialogFragment.UNDEFINED)) + val title = intent?.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database) ?: UNDEFINED + val subTitle = intent?.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) ?: UNDEFINED + val message = intent?.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) ?: UNDEFINED + progressTaskDialogFragment = ProgressTaskDialogFragment.build(title, subTitle, message) ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment!!) } @@ -62,7 +124,6 @@ class ProgressDialogThread(private val activity: FragmentActivity, // Remove the progress task ProgressTaskDialogFragment.stop(activity) TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - activity.stopService(intentDatabaseTask) if (intent != null && intent.hasExtra(ACTION_TASK_KEY) && intent.hasExtra(RESULT_KEY)) @@ -97,10 +158,12 @@ class ProgressDialogThread(private val activity: FragmentActivity, ) // Check if a service is currently running - activity.sendBroadcast(Intent(DATABASE_CHECK_TASK_ACTION)) + activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) } fun unregisterProgressTask() { + activity.unbindService(serviceConnection) + activity.unregisterReceiver(databaseTaskBroadcastReceiver) } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 18a9f8935..77ccc2696 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -1,12 +1,8 @@ package com.kunzisoft.keepass.notifications -import android.content.BroadcastReceiver -import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.net.Uri -import android.os.AsyncTask -import android.os.Bundle +import android.os.* import android.util.Log import com.kunzisoft.keepass.R import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction @@ -18,12 +14,12 @@ import com.kunzisoft.keepass.database.action.node.* import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskUpdater -import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION import java.io.File import java.util.* import kotlin.collections.ArrayList +import android.os.Bundle class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater { @@ -31,27 +27,44 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null - private var checkBroadcastReceiver: BroadcastReceiver? = null + private var actionStatusHandler = ActionStatusHandler() + private var actionMessenger = Messenger(actionStatusHandler) - override fun onCreate() { - super.onCreate() + private class ActionStatusHandler: Handler() { + var titleId: Int? = null + var messageId: Int? = null + var warningId: Int? = null - checkBroadcastReceiver = object: BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - sendBroadcast(Intent(DATABASE_START_TASK_ACTION)) + override fun handleMessage(message: Message?) { + when (message?.what) { + CHECK_ACTION -> { + try { + // Incoming data + val response = Message.obtain(null, UPDATE_ACTION_ELEMENTS) + response.data = Bundle().apply { + titleId?.let { + putInt(DATABASE_TASK_TITLE_KEY, it) + } + messageId?.let { + putInt(DATABASE_TASK_MESSAGE_KEY, it) + } + warningId?.let { + putInt(DATABASE_TASK_WARNING_KEY, it) + } + } + message.replyTo?.send(response) + } catch (e: RemoteException) { + e.printStackTrace() + } + + } + else -> super.handleMessage(message) } } - - registerReceiver(checkBroadcastReceiver, IntentFilter().apply { - addAction(DATABASE_CHECK_TASK_ACTION) - } - ) } - override fun onDestroy() { - unregisterReceiver(checkBroadcastReceiver) - - super.onDestroy() + override fun onBind(intent: Intent): IBinder? { + return actionMessenger.binder } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -72,13 +85,15 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_LOAD_TASK -> R.string.loading_database else -> R.string.loading_database } - val subtitleId: Int? = when (intent.action) { - else -> null - } val messageId: Int? = when (intent.action) { ACTION_DATABASE_LOAD_TASK -> null - else -> R.string.do_not_kill_app + else -> null } + val warningId: Int? = + if (intent.action == ACTION_DATABASE_LOAD_TASK) + null + else + R.string.do_not_kill_app val actionRunnable: ActionRunnable? = when (intent.action) { ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent) @@ -107,13 +122,16 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_COPY_NODES_TASK, ACTION_DATABASE_MOVE_NODES_TASK, ACTION_DATABASE_DELETE_NODES_TASK -> { + actionStatusHandler.titleId = titleId + actionStatusHandler.messageId = messageId + actionStatusHandler.warningId = warningId newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) actionRunnableAsyncTask = ActionRunnableAsyncTask(this, { sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { putExtra(DATABASE_TASK_TITLE_KEY, titleId) - putExtra(DATABASE_TASK_SUBTITLE_KEY, subtitleId) putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) + putExtra(DATABASE_TASK_WARNING_KEY, warningId) }) }, { result -> @@ -121,6 +139,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat putExtra(ACTION_TASK_KEY, intent.action) putExtra(RESULT_KEY, result.toBundle()) }) + stopSelf() } ) actionRunnable?.let { actionRunnableNotNull -> @@ -412,9 +431,13 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private val TAG = DatabaseTaskNotificationService::class.java.name + const val START_ACTION = 42 + const val STOP_ACTION = 43 + const val CHECK_ACTION = 44 + const val UPDATE_ACTION_ELEMENTS = 45 const val DATABASE_TASK_TITLE_KEY = "DATABASE_TASK_TITLE_KEY" - const val DATABASE_TASK_SUBTITLE_KEY = "DATABASE_TASK_SUBTITLE_KEY" const val DATABASE_TASK_MESSAGE_KEY = "DATABASE_TASK_MESSAGE_KEY" + const val DATABASE_TASK_WARNING_KEY = "DATABASE_TASK_WARNING_KEY" const val ACTION_DATABASE_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK" const val ACTION_DATABASE_SAVE_TASK = "ACTION_DATABASE_SAVE_TASK" diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt index 60235a18d..deb41e426 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt @@ -110,12 +110,14 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { const val UNDEFINED = -1 - fun build(@StringRes titleId: Int, + fun build(@StringRes titleId: Int? = null, @StringRes messageId: Int? = null, @StringRes warningId: Int? = null): ProgressTaskDialogFragment { // Create an instance of the dialog fragment and show it val dialog = ProgressTaskDialogFragment() - dialog.updateTitle(titleId) + titleId?.let { + dialog.updateTitle(it) + } messageId?.let { dialog.updateMessage(it) } @@ -130,12 +132,34 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { dialog.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG) } - fun stop(activity: FragmentActivity) { - val fragmentTask = activity.supportFragmentManager.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) - if (fragmentTask != null) { - val loadingDatabaseDialog = fragmentTask as ProgressTaskDialogFragment - loadingDatabaseDialog.dismissAllowingStateLoss() + private fun retrieveProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment? { + return activity.supportFragmentManager + .findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment? + } + + private fun retrieveAndShowProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment { + var dialog = retrieveProgressDialog(activity) + if (dialog == null) { + dialog = build() + start(activity, build()) } + return dialog + } + + fun stop(activity: FragmentActivity) { + retrieveProgressDialog(activity)?.dismissAllowingStateLoss() + } + + fun updateTitle(activity: FragmentActivity, titleId: Int) { + retrieveAndShowProgressDialog(activity).updateTitle(titleId) + } + + fun updateMessage(activity: FragmentActivity, messageId: Int) { + retrieveAndShowProgressDialog(activity).updateMessage(messageId) + } + + fun updateWarning(activity: FragmentActivity, warningId: Int) { + retrieveAndShowProgressDialog(activity).updateWarning(warningId) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt index 8d6f8e793..8b8f9d8b2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt @@ -3,8 +3,6 @@ package com.kunzisoft.keepass.utils const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION" const val DATABASE_STOP_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_STOP_TASK_ACTION" -const val DATABASE_CHECK_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_CHECK_TASK_ACTION" - const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK" const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD"