Empty Magikeyboard memory when the main service is killed #1261

This commit is contained in:
J-Jamet
2022-04-08 16:53:03 +02:00
parent 2042c85b22
commit 3e56521ea8
6 changed files with 145 additions and 133 deletions

View File

@@ -8,7 +8,7 @@ KeePassDX(3.4.0)
* Fix small bugs #1282
* Better search implementation #175 #1254
* Setting to change keyboard during a search #1267
* Manage package name from Magikeyboard #1010
* Manage package name from Magikeyboard #1010 #1261
* Ask confirmation to lock if changes without save #970
KeePassDX(3.3.3)

View File

@@ -24,6 +24,7 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
@@ -60,7 +61,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
keySelectionBundle.getParcelable<SearchInfo>(KEY_SEARCH_INFO)?.let { mSearchInfo ->
searchInfo = mSearchInfo
}
launch(database, searchInfo)
launch(database, searchInfo, true)
} else {
// To manage share
var sharedWebDomain: String? = null
@@ -102,9 +103,9 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
}
private fun launch(database: Database?,
searchInfo: SearchInfo) {
searchInfo: SearchInfo,
forceSelection: Boolean = false) {
if (!searchInfo.containsOnlyNullValues()) {
// Setting to integrate Magikeyboard
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
@@ -129,13 +130,14 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
.show()
}
} else if (searchShareForMagikeyboard) {
if (items.size == 1) {
if (items.size == 1 && !forceSelection) {
// Automatically populate keyboard
val entryPopulate = items[0]
populateKeyboardAndMoveAppToBackground(
this,
entryPopulate,
intent)
Log.e("TEST", "One item activity")
} else {
// Select the one we want
GroupActivity.launchForKeyboardSelectionResult(this,
@@ -190,24 +192,6 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
}
}
)
} else {
SearchHelper.checkAutoSearchInfo(this,
database,
null,
{ _, _ ->
// Not called
// if items found directly returns before calling this activity
},
{ openedDatabase ->
// Select if not found
GroupActivity.launchForKeyboardSelectionResult(this, openedDatabase)
},
{
// Pass extra to get entry
FileDatabaseSelectActivity.launchForKeyboardSelectionResult(this)
}
)
}
finish()
}
@@ -225,7 +209,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
}
// New task needed because don't launch from an Activity context
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Intent.FLAG_ACTIVITY_CLEAR_TASK
context.startActivity(intent)
}
}

View File

@@ -96,15 +96,9 @@ abstract class DatabaseModeActivity : DatabaseActivity() {
private fun backToTheMainAppAndFinish() {
// To move the app in background and return to the main app
// Not visible as opened with FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
moveTaskToBack(true)
// To remove this instance in the OS app selector
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask()
} else {
Handler(Looper.getMainLooper()).postDelayed({
finish()
}, 500)
}
// Not finish() to prevent service kill
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@@ -39,12 +39,15 @@ import com.kunzisoft.keepass.adapters.FieldsAdapter
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.Field
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
import com.kunzisoft.keepass.services.KeyboardEntryNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.*
import java.util.*
class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionListener {
@@ -71,6 +74,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
mDatabaseTaskProvider?.registerProgressTask()
mDatabaseTaskProvider?.onDatabaseRetrieved = { database ->
this.mDatabase = database
assignKeyboardView()
}
// Remove the entry and lock the keyboard when the lock signal is receive
lockReceiver = LockReceiver {
@@ -110,7 +114,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
fieldsAdapter = FieldsAdapter(this)
fieldsAdapter?.onItemClickListener = object : FieldsAdapter.OnItemClickListener {
override fun onItemClick(item: Field) {
currentInputConnection.commitText(entryInfoKey?.getGeneratedFieldValue(item.name) , 1)
currentInputConnection.commitText(getEntryInfo()?.getGeneratedFieldValue(item.name) , 1)
actionTabAutomatically()
}
}
@@ -120,17 +124,6 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
val closeView = popupFieldsView.findViewById<View>(R.id.keyboard_popup_close)
closeView.setOnClickListener { popupCustomKeys?.dismiss() }
// Remove entry info if the database is not loaded
// or if entry info timestamp is before database loaded timestamp
val databaseTime = mDatabase?.loadTimestamp
val entryTime = entryInfoTimestamp
if (mDatabase == null
|| mDatabase?.loaded != true
|| databaseTime == null
|| entryTime == null
|| entryTime < databaseTime) {
removeEntryInfo()
}
assignKeyboardView()
keyboardView?.onKeyboardActionListener = this
@@ -140,12 +133,23 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
return super.onCreateInputView()
}
private fun getEntryInfo(): EntryInfo? {
var entryInfoRetrieved: EntryInfo? = null
entryUUID?.let { entryId ->
entryInfoRetrieved = mDatabase
?.getEntryById(NodeIdUUID(entryId))
?.getEntryInfo(mDatabase)
}
return entryInfoRetrieved
}
private fun assignKeyboardView() {
dismissCustomKeys()
if (keyboardView != null) {
if (entryInfoKey != null) {
val entryInfo = getEntryInfo()
if (entryInfo != null) {
if (keyboardEntry != null) {
populateEntryInfoInView()
populateEntryInfoInView(entryInfo)
keyboardView?.keyboard = keyboardEntry
}
} else {
@@ -161,10 +165,10 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
}
}
private fun populateEntryInfoInView() {
private fun populateEntryInfoInView(entryInfo: EntryInfo) {
entryText?.visibility = View.VISIBLE
if (entryInfoKey?.title?.isNotEmpty() == true) {
entryText?.text = entryInfoKey?.title
if (entryInfo.title.isNotEmpty()) {
entryText?.text = entryInfo.title
} else {
hideEntryInfo()
}
@@ -259,12 +263,13 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
dismissCustomKeys()
}
KEY_USERNAME -> {
entryInfoKey?.username?.let { username ->
getEntryInfo()?.username?.let { username ->
currentInputConnection.commitText(username, 1)
}
actionTabAutomatically()
}
KEY_PASSWORD -> {
val entryInfoKey = getEntryInfo()
entryInfoKey?.password?.let { password ->
currentInputConnection.commitText(password, 1)
}
@@ -272,14 +277,14 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
actionGoAutomatically(!otpFieldExists)
}
KEY_OTP -> {
entryInfoKey?.let { entryInfo ->
getEntryInfo()?.let { entryInfo ->
currentInputConnection.commitText(
entryInfo.getGeneratedFieldValue(OTP_TOKEN_FIELD), 1)
}
actionGoAutomatically()
}
KEY_OTP_ALT -> {
entryInfoKey?.let { entryInfo ->
getEntryInfo()?.let { entryInfo ->
val otpToken = entryInfo.getGeneratedFieldValue(OTP_TOKEN_FIELD)
if (otpToken.isNotEmpty()) {
// Cut to fill each digit separatelyKeyEvent.KEYCODE_TAB
@@ -296,13 +301,13 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
actionGoAutomatically()
}
KEY_URL -> {
entryInfoKey?.url?.let { url ->
getEntryInfo()?.url?.let { url ->
currentInputConnection.commitText(url, 1)
}
actionGoAutomatically()
}
KEY_FIELDS -> {
entryInfoKey?.customFields?.let { customFields ->
getEntryInfo()?.customFields?.let { customFields ->
fieldsAdapter?.apply {
setFields(customFields.filter { it.name != OTP_TOKEN_FIELD})
notifyDataSetChanged()
@@ -318,8 +323,41 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
}
private fun actionKeyEntry(searchInfo: SearchInfo? = null) {
// Stop current service and reinit entry
stopService(Intent(this, KeyboardEntryNotificationService::class.java))
SearchHelper.checkAutoSearchInfo(this,
mDatabase,
searchInfo,
{ _, items ->
if (items.size == 1) {
if (entryUUID == null) {
// Automatically populate keyboard
removeEntryInfo()
addEntryAndLaunchNotificationIfAllowed(
this,
items[0],
true
)
assignKeyboardView()
} else {
// Choose another one
launchEntrySelection(null)
}
} else {
// Select if multiple
launchEntrySelection(searchInfo)
}
},
{ _ ->
// Select if not found
launchEntrySelection(searchInfo)
},
{
// Select if database not opened
launchEntrySelection(searchInfo)
}
)
}
private fun launchEntrySelection(searchInfo: SearchInfo?) {
removeEntryInfo()
EntrySelectionLauncherActivity.launch(this, searchInfo)
}
@@ -390,13 +428,10 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
const val KEY_URL = 520
const val KEY_FIELDS = 530
// TODO Retrieve entry info from id and service when database is open
private var entryInfoKey: EntryInfo? = null
private var entryInfoTimestamp: Long? = null
private var entryUUID: UUID? = null
private fun removeEntryInfo() {
entryInfoKey = null
entryInfoTimestamp = null
entryUUID = null
}
fun removeEntry(context: Context) {
@@ -405,8 +440,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
fun addEntryAndLaunchNotificationIfAllowed(context: Context, entry: EntryInfo, toast: Boolean = false) {
// Add a new entry
entryInfoKey = entry
entryInfoTimestamp = System.currentTimeMillis()
entryUUID = entry.id
// Launch notification if allowed
KeyboardEntryNotificationService.launchNotificationIfAllowed(context, entry, toast)
}

View File

@@ -7,5 +7,5 @@
* Fix small bugs #1282
* Better search implementation #175 #1254
* Setting to change keyboard during a search #1267
* Manage package name from Magikeyboard #1010
* Manage package name from Magikeyboard #1010 #1261
* Ask confirmation to lock if changes without save #970

View File

@@ -7,5 +7,5 @@
* Correction de petits bugs #1282
* Meilleure implémentation de la recherche #175 #1254
* Paramètre pour changer de clavier lors d'une recherche #1267
* Gestion du nom de package du Magiclavier #1010
* Gestion du nom de package du Magiclavier #1010 #1261
* Demande de confirmation de verouiller si chanegement sans sauvegarde #970