diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d9f486a01..b887db2a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -126,10 +126,10 @@ android:configChanges="orientation|keyboardHidden" android:windowSoftInputMode="stateHidden" /> - - activity.startActivityForResult(intent, 0)); } @@ -179,16 +179,15 @@ public class GroupActivity extends LockingActivity * ------------------------- */ - public static void launchForKeyboardResult(Activity activity, boolean readOnly) { - TimeoutHelper.INSTANCE.recordTime(activity); - launchForKeyboardResult(activity, null, readOnly); + public static void launchForKeyboardSelection(Activity activity, boolean readOnly) { + launchForKeyboardSelection(activity, null, readOnly); } - public static void launchForKeyboardResult(Activity activity, PwGroup group, boolean readOnly) { + public static void launchForKeyboardSelection(Activity activity, PwGroup group, boolean readOnly) { // TODO implement pre search to directly open the direct group + TimeoutHelper.INSTANCE.recordTime(activity); buildAndLaunchIntent(activity, group, readOnly, (intent) -> { - EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent); - activity.startActivityForResult(intent, EntrySelectionHelper.ENTRY_SELECTION_RESPONSE_REQUEST_CODE); + KeyboardHelper.INSTANCE.startActivityForKeyboardSelection(activity, intent); }); } @@ -199,26 +198,17 @@ public class GroupActivity extends LockingActivity */ @RequiresApi(api = Build.VERSION_CODES.O) - public static void launchForAutofillResult(Activity activity, AssistStructure assistStructure, boolean readOnly) { - if ( assistStructure != null ) { - TimeoutHelper.INSTANCE.recordTime(activity); - launchForAutofillResult(activity, null, assistStructure, readOnly); - } else { - launch(activity, readOnly); - } + public static void launchForAutofillResult(Activity activity, @NonNull AssistStructure assistStructure, boolean readOnly) { + launchForAutofillResult(activity, null, assistStructure, readOnly); } @RequiresApi(api = Build.VERSION_CODES.O) - public static void launchForAutofillResult(Activity activity, PwGroup group, AssistStructure assistStructure, boolean readOnly) { + public static void launchForAutofillResult(Activity activity, PwGroup group, @NonNull AssistStructure assistStructure, boolean readOnly) { // TODO implement pre search to directly open the direct group - if ( assistStructure != null ) { - buildAndLaunchIntent(activity, group, readOnly, (intent) -> { - AutofillHelper.addAssistStructureExtraInIntent(intent, assistStructure); - activity.startActivityForResult(intent, AutofillHelper.AUTOFILL_RESPONSE_REQUEST_CODE); - }); - } else { - launch(activity, group, readOnly); - } + TimeoutHelper.INSTANCE.recordTime(activity); + buildAndLaunchIntent(activity, group, readOnly, (intent) -> { + AutofillHelper.INSTANCE.startActivityForAutofillResult(activity, intent, assistStructure); + }); } @Override @@ -316,13 +306,6 @@ public class GroupActivity extends LockingActivity addNodeButtonView.setAddEntryClickListener(v -> EntryEditActivity.launch(GroupActivity.this, mCurrentGroup)); - // To init autofill - entrySelectionMode = EntrySelectionHelper.isIntentInEntrySelectionMode(getIntent()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - autofillHelper = new AutofillHelper(); - autofillHelper.retrieveAssistStructure(getIntent()); - } - // Search suggestion searchSuggestionAdapter = new SearchEntryCursorAdapter(this, database); @@ -507,45 +490,44 @@ public class GroupActivity extends LockingActivity @Override public void onNodeClick(PwNode node) { - - // Add event when we have Autofill - AssistStructure assistStructure = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - assistStructure = autofillHelper.getAssistStructure(); - if (assistStructure != null) { - switch (node.getType()) { - case GROUP: - openChildGroup((PwGroup) node); - break; - case ENTRY: - // Build response with the entry selected - autofillHelper.buildResponseWhenEntrySelected(this, (PwEntry) node); - finish(); - break; + switch (node.getType()) { + case GROUP: + try { + openChildGroup((PwGroup) node); + } catch (ClassCastException e) { + Log.e(TAG, "Node can't be cast in Group"); } - } - } - if ( assistStructure == null ){ - if (entrySelectionMode) { - switch (node.getType()) { - case GROUP: - openChildGroup((PwGroup) node); - break; - case ENTRY: - EntrySelectionHelper.buildResponseWhenEntrySelected(this, (PwEntry) node); - finish(); - break; + break; + case ENTRY: + try { + PwEntry entry = ((PwEntry) node); + EntrySelectionHelper.INSTANCE.doEntrySelectionAction(getIntent(), + () -> { + EntryActivity.launch(GroupActivity.this, entry, getReadOnly()); + return null; + }, + () -> { + MagikIME.setEntryKey(entry.getEntry()); + // Show the notification if allowed in Preferences + if (PreferencesUtil.enableKeyboardNotificationEntry(GroupActivity.this)) { + Intent notificationIntent = new Intent(GroupActivity.this, KeyboardEntryNotificationService.class); + startService(notificationIntent); + } + moveTaskToBack(true); + return null; + }, + assistStructure -> { + // Build response with the entry selected + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AutofillHelper.INSTANCE.buildResponseWhenEntrySelected(GroupActivity.this, entry); + } + finish(); + return null; + }); + } catch (ClassCastException e) { + Log.e(TAG, "Node can't be cast in Entry"); } - } else { - switch (node.getType()) { - case GROUP: - openChildGroup((PwGroup) node); - break; - case ENTRY: - EntryActivity.launch(this, (PwEntry) node, getReadOnly()); - break; - } - } + break; } } @@ -920,7 +902,6 @@ public class GroupActivity extends LockingActivity @Override public void startActivity(Intent intent) { - boolean customSearchQueryExecuted = false; // Get the intent, verify the action and get the query if (Intent.ACTION_SEARCH.equals(intent.getAction())) { @@ -931,22 +912,26 @@ public class GroupActivity extends LockingActivity searchIntent.setAction(Intent.ACTION_SEARCH); searchIntent.putExtra(SearchManager.QUERY, query); - if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && autofillHelper.getAssistStructure() != null ) { - AutofillHelper.addAssistStructureExtraInIntent(searchIntent, autofillHelper.getAssistStructure()); - startActivityForResult(searchIntent, AutofillHelper.AUTOFILL_RESPONSE_REQUEST_CODE); - customSearchQueryExecuted = true; - } - // To get the keyboard response, verify if the current intent contains the EntrySelection key - else if (EntrySelectionHelper.isIntentInEntrySelectionMode(getIntent())){ - EntrySelectionHelper.addEntrySelectionModeExtraInIntent(searchIntent); - startActivityForResult(searchIntent, EntrySelectionHelper.ENTRY_SELECTION_RESPONSE_REQUEST_CODE); - customSearchQueryExecuted = true; - } - } - - if (!customSearchQueryExecuted) { - super.startActivity(intent); + EntrySelectionHelper.INSTANCE.doEntrySelectionAction(intent, + () -> { + GroupActivity.super.startActivity(intent); + return null; + }, + () -> { + KeyboardHelper.INSTANCE.startActivityForKeyboardSelection( + GroupActivity.this, + searchIntent); + return null; + }, + assistStructure -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AutofillHelper.INSTANCE.startActivityForAutofillResult( + GroupActivity.this, + searchIntent, + assistStructure); + } + return null; + }); } } @@ -1179,9 +1164,8 @@ public class GroupActivity extends LockingActivity protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - EntrySelectionHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); + AutofillHelper.INSTANCE.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt index 2a6d9fe90..5601d9433 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt @@ -103,7 +103,7 @@ abstract class LockingActivity : StylishActivity() { // After the first creation // or If simply swipe with another application // If the time is out -> close the Activity - TimeoutHelper.checkTime(this) + TimeoutHelper.checkTimeAndLockIfTimeout(this) // If onCreate already record time if (!exitLock) TimeoutHelper.recordTime(this) @@ -121,7 +121,7 @@ abstract class LockingActivity : StylishActivity() { if (timeoutEnable) { // If the time is out during our navigation in activity -> close the Activity - TimeoutHelper.checkTime(this) + TimeoutHelper.checkTimeAndLockIfTimeout(this) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillAuthActivity.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillLauncherActivity.kt similarity index 87% rename from app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillAuthActivity.kt rename to app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillLauncherActivity.kt index aa92f16e4..d04a28fd6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillAuthActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/AutoFillLauncherActivity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017 Jeremy Jamet / Kunzisoft. + * Copyright 2019 Jeremy Jamet / Kunzisoft. * * This file is part of KeePass DX. * @@ -34,12 +34,12 @@ import com.kunzisoft.keepass.fileselect.FileSelectActivity import com.kunzisoft.keepass.timeout.TimeoutHelper @RequiresApi(api = Build.VERSION_CODES.O) -class AutoFillAuthActivity : AppCompatActivity() { +class AutoFillLauncherActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { - TimeoutHelper.checkTime(this) {} // Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE) - val assistStructure = AutofillHelper().retrieveAssistStructure(intent) + TimeoutHelper.checkTime(this) + val assistStructure = AutofillHelper.retrieveAssistStructure(intent) if (assistStructure != null) { if (App.getDB().loaded) GroupActivity.launchForAutofillResult(this, assistStructure, true) @@ -54,14 +54,14 @@ class AutoFillAuthActivity : AppCompatActivity() { super.onCreate(savedInstanceState) } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data) } companion object { fun getAuthIntentSenderForResponse(context: Context): IntentSender { - val intent = Intent(context, AutoFillAuthActivity::class.java) + val intent = Intent(context, AutoFillLauncherActivity::class.java) return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT).intentSender } diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.java b/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.java deleted file mode 100644 index fa2798ce4..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX 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. - * - * KeePass DX 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 KeePass DX. If not, see . - * - */ -package com.kunzisoft.keepass.autofill; - -import android.app.Activity; -import android.app.assist.AssistStructure; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.service.autofill.Dataset; -import android.service.autofill.FillResponse; -import android.support.annotation.Nullable; -import android.support.annotation.RequiresApi; -import android.util.Log; -import android.view.autofill.AutofillId; -import android.view.autofill.AutofillManager; -import android.view.autofill.AutofillValue; -import android.widget.RemoteViews; - -import com.kunzisoft.keepass.R; -import com.kunzisoft.keepass.database.PwEntry; -import com.kunzisoft.keepass.selection.EntrySelectionHelper; - -import java.util.ArrayList; -import java.util.List; - - -@RequiresApi(api = Build.VERSION_CODES.O) -public class AutofillHelper { - - public static final int AUTOFILL_RESPONSE_REQUEST_CODE = 8165; - - private AssistStructure assistStructure = null; - - public AssistStructure retrieveAssistStructure(Intent intent) { - if (intent != null && intent.getExtras() != null) { - assistStructure = intent.getParcelableExtra(android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE); - } - return assistStructure; - } - - /** - * Call retrieveAssistStructure before - */ - public AssistStructure getAssistStructure() { - return assistStructure; - } - - public static void addAssistStructureExtraInIntent(Intent intent, AssistStructure assistStructure) { - if (assistStructure != null) { - EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent); - intent.putExtra(android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE, assistStructure); - } - } - - /** - * Define if android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE is an extra bundle key present in the Intent - */ - public static boolean isIntentContainsExtraAssistStructureKey(Intent intent) { - return (intent != null - && intent.getExtras() != null - && intent.getExtras().containsKey(android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE)); - } - - private @Nullable Dataset buildDataset(Context context, PwEntry entry, - StructureParser.Result struct) { - String title = makeEntryTitle(entry); - RemoteViews views = newRemoteViews(context.getPackageName(), title); - Dataset.Builder builder = new Dataset.Builder(views); - builder.setId(entry.getUUID().toString()); - - if (entry.getPassword() != null) { - AutofillValue value = AutofillValue.forText(entry.getPassword()); - struct.password.forEach(id -> builder.setValue(id, value)); - } - if (entry.getUsername() != null) { - AutofillValue value = AutofillValue.forText(entry.getUsername()); - List ids = new ArrayList<>(struct.username); - if (entry.getUsername().contains("@") || struct.username.isEmpty()) - ids.addAll(struct.email); - ids.forEach(id -> builder.setValue(id, value)); - } - try { - return builder.build(); - } catch (IllegalArgumentException e) { - // if not value be set - return null; - } - } - - static private String makeEntryTitle(PwEntry entry) { - if (!entry.getTitle().isEmpty() && !entry.getUsername().isEmpty()) - return String.format("%s (%s)", entry.getTitle(), entry.getUsername()); - if (!entry.getTitle().isEmpty()) - return entry.getTitle(); - if (!entry.getUsername().isEmpty()) - return entry.getUsername(); - if (!entry.getNotes().isEmpty()) - return entry.getNotes().trim(); - return ""; // TODO No title - } - - /** - * Method to hit when right key is selected - */ - public void buildResponseWhenEntrySelected(Activity activity, PwEntry entry) { - Intent mReplyIntent; - Intent intent = activity.getIntent(); - if (isIntentContainsExtraAssistStructureKey(intent)) { - AssistStructure structure = intent.getParcelableExtra(android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE); - StructureParser.Result result = new StructureParser(structure).parse(); - - // New Response - FillResponse.Builder responseBuilder = new FillResponse.Builder(); - Dataset dataset = buildDataset(activity, entry, result); - responseBuilder.addDataset(dataset); - mReplyIntent = new Intent(); - Log.d(activity.getClass().getName(), "Successed Autofill auth."); - mReplyIntent.putExtra( - AutofillManager.EXTRA_AUTHENTICATION_RESULT, - responseBuilder.build()); - activity.setResult(Activity.RESULT_OK, mReplyIntent); - } else { - Log.w(activity.getClass().getName(), "Failed Autofill auth."); - activity.setResult(Activity.RESULT_CANCELED); - } - } - - /** - * Utility method to loop and close each activity with return data - */ - public static void onActivityResultSetResultAndFinish(Activity activity, int requestCode, int resultCode, Intent data) { - if (requestCode == AUTOFILL_RESPONSE_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - activity.setResult(resultCode, data); - } - if (resultCode == Activity.RESULT_CANCELED) { - activity.setResult(Activity.RESULT_CANCELED); - } - activity.finish(); - } - } - - private static RemoteViews newRemoteViews(String packageName, String remoteViewsText) { - RemoteViews presentation = - new RemoteViews(packageName, R.layout.autofill_service_list_item); - presentation.setTextViewText(R.id.text, remoteViewsText); - return presentation; - } -} diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt new file mode 100644 index 000000000..9048a4558 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2019 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePass DX. + * + * KeePass DX 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. + * + * KeePass DX 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 KeePass DX. If not, see . + * + */ +package com.kunzisoft.keepass.autofill + +import android.app.Activity +import android.app.assist.AssistStructure +import android.content.Context +import android.content.Intent +import android.os.Build +import android.service.autofill.Dataset +import android.service.autofill.FillResponse +import android.support.annotation.RequiresApi +import android.util.Log +import android.view.autofill.AutofillManager +import android.view.autofill.AutofillValue +import android.widget.RemoteViews +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.PwEntry +import com.kunzisoft.keepass.selection.EntrySelectionHelper +import java.util.* + + +@RequiresApi(api = Build.VERSION_CODES.O) +object AutofillHelper { + + private const val AUTOFILL_RESPONSE_REQUEST_CODE = 8165 + + private const val ASSIST_STRUCTURE = android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE + + fun retrieveAssistStructure(intent: Intent?): AssistStructure? { + intent?.let { + return it.getParcelableExtra(ASSIST_STRUCTURE) + } + return null + } + + private fun makeEntryTitle(entry: PwEntry<*>): String { + if (!entry.title.isEmpty() && !entry.username.isEmpty()) + return String.format("%s (%s)", entry.title, entry.username) + if (!entry.title.isEmpty()) + return entry.title + if (!entry.username.isEmpty()) + return entry.username + return if (!entry.notes.isEmpty()) entry.notes.trim { it <= ' ' } else "" + // TODO No title + } + + private fun buildDataset(context: Context, entry: PwEntry<*>, + struct: StructureParser.Result): Dataset? { + val title = makeEntryTitle(entry) + val views = newRemoteViews(context.packageName, title) + val builder = Dataset.Builder(views) + builder.setId(entry.uuid.toString()) + + if (entry.password != null) { + val value = AutofillValue.forText(entry.password) + struct.password.forEach { id -> builder.setValue(id, value) } + } + if (entry.username != null) { + val value = AutofillValue.forText(entry.username) + val ids = ArrayList(struct.username) + if (entry.username.contains("@") || struct.username.isEmpty()) + ids.addAll(struct.email) + ids.forEach { id -> builder.setValue(id, value) } + } + return try { + builder.build() + } catch (e: IllegalArgumentException) { + // if not value be set + null + } + } + + /** + * Method to hit when right key is selected + */ + fun buildResponseWhenEntrySelected(activity: Activity, entry: PwEntry<*>) { + val mReplyIntent: Intent + activity.intent?.let { intent -> + if (intent.extras.containsKey(ASSIST_STRUCTURE)) { + val structure = intent.getParcelableExtra(ASSIST_STRUCTURE) + val result = StructureParser(structure).parse() + + // New Response + val responseBuilder = FillResponse.Builder() + val dataset = buildDataset(activity, entry, result) + responseBuilder.addDataset(dataset) + mReplyIntent = Intent() + Log.d(activity.javaClass.name, "Successed Autofill auth.") + mReplyIntent.putExtra( + AutofillManager.EXTRA_AUTHENTICATION_RESULT, + responseBuilder.build()) + activity.setResult(Activity.RESULT_OK, mReplyIntent) + } else { + Log.w(activity.javaClass.name, "Failed Autofill auth.") + activity.setResult(Activity.RESULT_CANCELED) + } + } + } + + /** + * Utility method to start an activity with an Autofill for result + */ + fun startActivityForAutofillResult(activity: Activity, intent: Intent, assistStructure: AssistStructure) { + EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent) + intent.putExtra(ASSIST_STRUCTURE, assistStructure) + activity.startActivityForResult(intent, AutofillHelper.AUTOFILL_RESPONSE_REQUEST_CODE) + } + + /** + * Utility method to loop and close each activity with return data + */ + fun onActivityResultSetResultAndFinish(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == AUTOFILL_RESPONSE_REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + activity.setResult(resultCode, data) + } + if (resultCode == Activity.RESULT_CANCELED) { + activity.setResult(Activity.RESULT_CANCELED) + } + activity.finish() + } + } + + private fun newRemoteViews(packageName: String, remoteViewsText: String): RemoteViews { + val presentation = RemoteViews(packageName, R.layout.autofill_service_list_item) + presentation.setTextViewText(R.id.text, remoteViewsText) + return presentation + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.java b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.java index 932509972..eb62f6a48 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.java +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.java @@ -62,7 +62,7 @@ public class KeeAutofillService extends AutofillService { if (!Arrays.asList(autofillIds).isEmpty()) { // If the entire Autofill Response is authenticated, AuthActivity is used // to generate Response. - IntentSender sender = AutoFillAuthActivity.Companion.getAuthIntentSenderForResponse(this); + IntentSender sender = AutoFillLauncherActivity.Companion.getAuthIntentSenderForResponse(this); RemoteViews presentation = new RemoteViews(getPackageName(), R.layout.autofill_service_unlock); responseBuilder.setAuthentication(autofillIds, sender, presentation); callback.onSuccess(responseBuilder.build()); diff --git a/app/src/main/java/com/kunzisoft/keepass/database/PwEntry.java b/app/src/main/java/com/kunzisoft/keepass/database/PwEntry.java index fb1434aa0..8f72c888c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/PwEntry.java +++ b/app/src/main/java/com/kunzisoft/keepass/database/PwEntry.java @@ -23,6 +23,8 @@ import android.os.Parcel; import com.kunzisoft.keepass.database.iterator.EntrySearchStringIterator; import com.kunzisoft.keepass.database.security.ProtectedString; +import com.kunzisoft.keepass.model.Entry; +import com.kunzisoft.keepass.model.Field; import java.util.UUID; @@ -199,6 +201,21 @@ public abstract class PwEntry extends PwNode { return false; } + public Entry getEntry() { + Entry entryModel = new Entry(); + entryModel.setTitle(getTitle()); + entryModel.setUsername(getUsername()); + entryModel.setPassword(getPassword()); + entryModel.setUrl(getUrl()); + if (containsCustomFields()) { + getFields() + .doActionToAllCustomProtectedField( + (key, value) -> entryModel.addCustomField( + new Field(key, value.toString()))); + } + return entryModel; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/app/src/main/java/com/kunzisoft/keepass/fileselect/FileSelectActivity.java b/app/src/main/java/com/kunzisoft/keepass/fileselect/FileSelectActivity.java index 966ea388b..d1b9115e0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/fileselect/FileSelectActivity.java +++ b/app/src/main/java/com/kunzisoft/keepass/fileselect/FileSelectActivity.java @@ -53,9 +53,9 @@ import com.kunzisoft.keepass.app.App; import com.kunzisoft.keepass.autofill.AutofillHelper; import com.kunzisoft.keepass.database.action.CreateDatabaseRunnable; import com.kunzisoft.keepass.database.action.FileOnFinishRunnable; -import com.kunzisoft.keepass.database.exception.ContentFileNotFoundException; import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment; import com.kunzisoft.keepass.dialogs.CreateFileDialogFragment; +import com.kunzisoft.keepass.magikeyboard.KeyboardHelper; import com.kunzisoft.keepass.password.AssignPasswordHelper; import com.kunzisoft.keepass.password.PasswordActivity; import com.kunzisoft.keepass.selection.EntrySelectionHelper; @@ -104,9 +104,6 @@ public class FileSelectActivity extends StylishActivity implements // TODO Consultation Mode private boolean consultationMode = false; - private boolean entrySelectionMode; - private AutofillHelper autofillHelper; - private View fileSelectExpandableButton; private ExpandableLayout fileSelectExpandable; private EditText openFileNameView; @@ -118,27 +115,33 @@ public class FileSelectActivity extends StylishActivity implements private String defaultPath; - public static void launch(Activity activity) { - Intent intent = new Intent(activity, FileSelectActivity.class); - // only to avoid visible flickering when redirecting - activity.startActivityForResult(intent, RESULT_CANCELED); - } + /* + * ------------------------- + * No Standard Launch, pass by PasswordActivity + * ------------------------- + */ - public static void launchForKeyboardResult(Activity activity) { - Intent intent = new Intent(activity, FileSelectActivity.class); - EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent); - activity.startActivityForResult(intent, EntrySelectionHelper.ENTRY_SELECTION_RESPONSE_REQUEST_CODE); + /* + * ------------------------- + * Keyboard Launch + * ------------------------- + */ + + public static void launchForKeyboardSelection(Activity activity) { + KeyboardHelper.INSTANCE.startActivityForKeyboardSelection(activity, new Intent(activity, FileSelectActivity.class)); } + /* + * ------------------------- + * Autofill Launch + * ------------------------- + */ + @RequiresApi(api = Build.VERSION_CODES.O) - public static void launchForAutofillResult(Activity activity, AssistStructure assistStructure) { - if ( assistStructure != null ) { - Intent intent = new Intent(activity, FileSelectActivity.class); - AutofillHelper.addAssistStructureExtraInIntent(intent, assistStructure); - activity.startActivityForResult(intent, AutofillHelper.AUTOFILL_RESPONSE_REQUEST_CODE); - } else { - launch(activity); - } + public static void launchForAutofillResult(Activity activity, @NonNull AssistStructure assistStructure) { + AutofillHelper.INSTANCE.startActivityForAutofillResult(activity, + new Intent(activity, FileSelectActivity.class), + assistStructure); } @Override @@ -177,13 +180,6 @@ public class FileSelectActivity extends StylishActivity implements RecyclerView mListFiles = findViewById(R.id.file_list); mListFiles.setLayoutManager(new LinearLayoutManager(this)); - entrySelectionMode = EntrySelectionHelper.isIntentInEntrySelectionMode(getIntent()); - // To retrieve info for AutoFill - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - autofillHelper = new AutofillHelper(); - autofillHelper.retrieveAssistStructure(getIntent()); - } - // Open button openButtonView = findViewById(R.id.open_database); openButtonView.setOnClickListener(v -> { @@ -243,40 +239,52 @@ public class FileSelectActivity extends StylishActivity implements checkAndPerformedEducation(); } + private void fileNoFoundAction(FileNotFoundException e) { + String error = getString(R.string.file_not_found_content); + Toast.makeText(FileSelectActivity.this, + error, Toast.LENGTH_LONG).show(); + Log.e(TAG, error, e); + } + + private void launchPasswordActivity(String fileName, String keyFile) { + EntrySelectionHelper.INSTANCE.doEntrySelectionAction(getIntent(), + () -> { + try { + PasswordActivity.launch(FileSelectActivity.this, + fileName, keyFile); + } catch (FileNotFoundException e) { + fileNoFoundAction(e); + } + return null; + }, + () -> { + try { + PasswordActivity.launchForKeyboardResult(FileSelectActivity.this, + fileName, keyFile); + } catch (FileNotFoundException e) { + fileNoFoundAction(e); + } + return null; + }, + assistStructure -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + PasswordActivity.launchForAutofillResult(FileSelectActivity.this, + fileName, keyFile, + assistStructure); + } catch (FileNotFoundException e) { + fileNoFoundAction(e); + } + } + return null; + }); + } + private void launchPasswordActivityWithPath(String path) { - try { - AssistStructure assistStructure = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - assistStructure = autofillHelper.getAssistStructure(); - if (assistStructure != null) { - PasswordActivity.launchForAutofillResult(FileSelectActivity.this, - path, - assistStructure); - } - } - if (assistStructure == null) { - if (entrySelectionMode) { - PasswordActivity.launchForKeyboardResult(FileSelectActivity.this, path); - } else { - PasswordActivity.launch(FileSelectActivity.this, path); - } - } - // Delete flickering for kitkat <= - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) - overridePendingTransition(0, 0); - } catch (ContentFileNotFoundException e) { - String error = getString(R.string.file_not_found_content); - Toast.makeText(FileSelectActivity.this, - error, Toast.LENGTH_LONG).show(); - Log.e(TAG, error, e); - } catch (FileNotFoundException e) { - String error = getString(R.string.file_not_found); - Toast.makeText(FileSelectActivity.this, - error, Toast.LENGTH_LONG).show(); - Log.e(TAG, error, e); - } catch (Exception e) { - Log.e(TAG, "Can't launch PasswordActivity", e); - } + launchPasswordActivity(path, ""); + // Delete flickering for kitkat <= + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + overridePendingTransition(0, 0); } private void updateExternalStorageWarning() { @@ -603,32 +611,7 @@ public class FileSelectActivity extends StylishActivity implements @Override public void onFileItemOpenListener(int itemPosition) { new OpenFileHistoryAsyncTask((fileName, keyFile) -> { - // TODO ENCAPSULATE - try { - AssistStructure assistStructure = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - assistStructure = autofillHelper.getAssistStructure(); - if (assistStructure != null) { - PasswordActivity.launchForAutofillResult(FileSelectActivity.this, - fileName, keyFile, assistStructure); - } - } - if (assistStructure == null) { - if (entrySelectionMode) { - PasswordActivity.launchForKeyboardResult(FileSelectActivity.this, fileName, keyFile); - } else { - PasswordActivity.launch(FileSelectActivity.this, fileName, keyFile); - } - } - } catch (ContentFileNotFoundException e) { - Toast.makeText(FileSelectActivity.this, - R.string.file_not_found_content, Toast.LENGTH_LONG) - .show(); - } catch (FileNotFoundException e) { - Toast.makeText(FileSelectActivity.this, - R.string.file_not_found, Toast.LENGTH_LONG) - .show(); - } + launchPasswordActivity(fileName, keyFile); updateFileListVisibility(); }, fileHistory).execute(itemPosition); } @@ -656,10 +639,8 @@ public class FileSelectActivity extends StylishActivity implements protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - // Get the entry result in entry selection mode - EntrySelectionHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); + AutofillHelper.INSTANCE.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); } keyFileHelper.onActivityResultCallback(requestCode, resultCode, data, diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardHelper.kt b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardHelper.kt new file mode 100644 index 000000000..b6b9b37bf --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardHelper.kt @@ -0,0 +1,14 @@ +package com.kunzisoft.keepass.magikeyboard + +import android.app.Activity +import android.content.Intent +import com.kunzisoft.keepass.selection.EntrySelectionHelper + +object KeyboardHelper { + + fun startActivityForKeyboardSelection(activity: Activity, intent: Intent) { + EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent) + // only to avoid visible flickering when redirecting + activity.startActivityForResult(intent, 0) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt new file mode 100644 index 000000000..0262d27cc --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt @@ -0,0 +1,27 @@ +package com.kunzisoft.keepass.magikeyboard + +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import com.kunzisoft.keepass.activities.GroupActivity +import com.kunzisoft.keepass.app.App +import com.kunzisoft.keepass.fileselect.FileSelectActivity +import com.kunzisoft.keepass.timeout.TimeoutHelper + +class KeyboardLauncherActivity : AppCompatActivity() { + + companion object { + val TAG = KeyboardLauncherActivity::class.java.name!! + } + + override fun onCreate(savedInstanceState: Bundle?) { + TimeoutHelper.checkTime(this) + if (App.getDB().loaded) + GroupActivity.launchForKeyboardSelection(this, true) + else { + // Pass extra to get entry + FileSelectActivity.launchForKeyboardSelection(this) + } + finish() + super.onCreate(savedInstanceState) + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index 5d7272189..5b8bb8dba 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -48,7 +48,6 @@ import com.kunzisoft.keepass.magikeyboard.adapter.FieldsAdapter; import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; import com.kunzisoft.keepass.magikeyboard.view.MagikeyboardView; import com.kunzisoft.keepass.model.Entry; -import com.kunzisoft.keepass.selection.KeyboardEntryRetrieverActivity; import static com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; @@ -206,8 +205,7 @@ public class MagikIME extends InputMethodService break; case KEY_ENTRY: deleteEntryKey(this); - Intent intent = new Intent(this, KeyboardEntryRetrieverActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Intent intent = new Intent(this, KeyboardLauncherActivity.class); startActivity(intent); break; case KEY_LOCK: diff --git a/app/src/main/java/com/kunzisoft/keepass/password/PasswordActivity.java b/app/src/main/java/com/kunzisoft/keepass/password/PasswordActivity.java index 64fcfea40..b0b1bebbf 100644 --- a/app/src/main/java/com/kunzisoft/keepass/password/PasswordActivity.java +++ b/app/src/main/java/com/kunzisoft/keepass/password/PasswordActivity.java @@ -70,6 +70,7 @@ import com.kunzisoft.keepass.fileselect.KeyFileHelper; import com.kunzisoft.keepass.fingerprint.FingerPrintAnimatedVector; import com.kunzisoft.keepass.fingerprint.FingerPrintExplanationDialog; import com.kunzisoft.keepass.fingerprint.FingerPrintHelper; +import com.kunzisoft.keepass.magikeyboard.KeyboardHelper; import com.kunzisoft.keepass.selection.EntrySelectionHelper; import com.kunzisoft.keepass.settings.PreferencesUtil; import com.kunzisoft.keepass.stylish.StylishActivity; @@ -133,9 +134,6 @@ public class PasswordActivity extends StylishActivity private KeyFileHelper keyFileHelper; - protected boolean entrySelectionMode; - private AutofillHelper autofillHelper; - private static void buildAndLaunchIntent(Activity activity, String fileName, String keyFile, IntentBuildLauncher intentBuildLauncher) { Intent intent = new Intent(activity, PasswordActivity.class); @@ -167,12 +165,6 @@ public class PasswordActivity extends StylishActivity * ------------------------- */ - public static void launch( - Activity act, - String fileName) throws FileNotFoundException { - launch(act, fileName, ""); - } - public static void launch( Activity activity, String fileName, @@ -187,12 +179,6 @@ public class PasswordActivity extends StylishActivity * ------------------------- */ - public static void launchForKeyboardResult( - Activity act, - String fileName) throws FileNotFoundException { - launchForKeyboardResult(act, fileName, ""); - } - public static void launchForKeyboardResult( Activity activity, String fileName, @@ -200,9 +186,7 @@ public class PasswordActivity extends StylishActivity verifyFileNameUriFromLaunch(fileName); buildAndLaunchIntent(activity, fileName, keyFile, (intent) -> { - EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent); - // only to avoid visible flickering when redirecting - activity.startActivityForResult(intent, EntrySelectionHelper.ENTRY_SELECTION_RESPONSE_REQUEST_CODE); + KeyboardHelper.INSTANCE.startActivityForKeyboardSelection(activity, intent); }); } @@ -212,14 +196,6 @@ public class PasswordActivity extends StylishActivity * ------------------------- */ - @RequiresApi(api = Build.VERSION_CODES.O) - public static void launchForAutofillResult( - Activity act, - String fileName, - AssistStructure assistStructure) throws FileNotFoundException { - launchForAutofillResult(act, fileName, "", assistStructure); - } - @RequiresApi(api = Build.VERSION_CODES.O) public static void launchForAutofillResult( Activity activity, @@ -230,8 +206,10 @@ public class PasswordActivity extends StylishActivity if ( assistStructure != null ) { buildAndLaunchIntent(activity, fileName, keyFile, (intent) -> { - AutofillHelper.addAssistStructureExtraInIntent(intent, assistStructure); - activity.startActivityForResult(intent, AutofillHelper.AUTOFILL_RESPONSE_REQUEST_CODE); + AutofillHelper.INSTANCE.startActivityForAutofillResult( + activity, + intent, + assistStructure); }); } else { launch(activity, fileName, keyFile); @@ -310,13 +288,6 @@ public class PasswordActivity extends StylishActivity fingerPrintAnimatedVector = new FingerPrintAnimatedVector(this, fingerprintImageView); } - - entrySelectionMode = EntrySelectionHelper.isIntentInEntrySelectionMode(getIntent()); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - autofillHelper = new AutofillHelper(); - autofillHelper.retrieveAssistStructure(getIntent()); - } } @Override @@ -974,20 +945,21 @@ public class PasswordActivity extends StylishActivity } private void launchGroupActivity() { - AssistStructure assistStructure = null; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - assistStructure = autofillHelper.getAssistStructure(); - if (assistStructure != null) { - GroupActivity.launchForAutofillResult(PasswordActivity.this, assistStructure, readOnly); - } - } - if (assistStructure == null) { - if (entrySelectionMode) { - GroupActivity.launchForKeyboardResult(PasswordActivity.this, readOnly); - } else { - GroupActivity.launch(PasswordActivity.this, readOnly); - } - } + EntrySelectionHelper.INSTANCE.doEntrySelectionAction(getIntent(), + () -> { + GroupActivity.launch(PasswordActivity.this, readOnly); + return null; + }, + () -> { + GroupActivity.launchForKeyboardSelection(PasswordActivity.this, readOnly); + return null; + }, + assistStructure -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + GroupActivity.launchForAutofillResult(PasswordActivity.this, assistStructure, readOnly); + } + return null; + }); } @Override @@ -1060,9 +1032,8 @@ public class PasswordActivity extends StylishActivity super.onActivityResult(requestCode, resultCode, data); // To get entry in result - EntrySelectionHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); + AutofillHelper.INSTANCE.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data); } boolean keyFileResult = false; diff --git a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java deleted file mode 100644 index 71c9db809..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.kunzisoft.keepass.selection; - -import android.app.Activity; -import android.content.Intent; -import android.util.Log; - -import com.kunzisoft.keepass.database.PwEntry; -import com.kunzisoft.keepass.model.Entry; -import com.kunzisoft.keepass.model.Field; - -public class EntrySelectionHelper { - - public static final int ENTRY_SELECTION_RESPONSE_REQUEST_CODE = 5164; - - public static final String EXTRA_ENTRY_SELECTION_MODE = "com.kunzisoft.keepass.extra.ENTRY_SELECTION_MODE"; - - public static void addEntrySelectionModeExtraInIntent(Intent intent) { - intent.putExtra(EXTRA_ENTRY_SELECTION_MODE, true); - } - - public static boolean isIntentInEntrySelectionMode(Intent intent) { - return intent.getBooleanExtra(EXTRA_ENTRY_SELECTION_MODE, false); - } - - /** - * Method to hit when right key is selected - */ - public static void buildResponseWhenEntrySelected(Activity activity, PwEntry entry) { - Intent mReplyIntent; - Intent intent = activity.getIntent(); - boolean entrySelectionMode = isIntentInEntrySelectionMode(intent); - if (entrySelectionMode) { - mReplyIntent = new Intent(); - - Entry entryModel = new Entry(); - entryModel.setTitle(entry.getTitle()); - entryModel.setUsername(entry.getUsername()); - entryModel.setPassword(entry.getPassword()); - entryModel.setUrl(entry.getUrl()); - if (entry.containsCustomFields()) { - entry.getFields() - .doActionToAllCustomProtectedField( - (key, value) -> entryModel.addCustomField( - new Field(key, value.toString()))); - } - Log.d(activity.getClass().getName(), "Build entry selection for reply: " + entryModel.getTitle()); - - mReplyIntent.putExtra( - EXTRA_ENTRY_SELECTION_MODE, - entryModel); - activity.setResult(Activity.RESULT_OK, mReplyIntent); - } else { - activity.setResult(Activity.RESULT_CANCELED); - } - } - - /** - * Utility method to loop and close each activity with return data - */ - public static void onActivityResultSetResultAndFinish(Activity activity, int requestCode, int resultCode, Intent data) { - if (requestCode == ENTRY_SELECTION_RESPONSE_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - activity.setResult(resultCode, data); - } - if (resultCode == Activity.RESULT_CANCELED) { - activity.setResult(Activity.RESULT_CANCELED); - } - activity.finish(); - } - } -} diff --git a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.kt b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.kt new file mode 100644 index 000000000..3625fdd56 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.kt @@ -0,0 +1,36 @@ +package com.kunzisoft.keepass.selection + +import android.app.assist.AssistStructure +import android.content.Intent +import android.os.Build +import com.kunzisoft.keepass.autofill.AutofillHelper + +object EntrySelectionHelper { + + private const val EXTRA_ENTRY_SELECTION_MODE = "com.kunzisoft.keepass.extra.ENTRY_SELECTION_MODE" + + fun addEntrySelectionModeExtraInIntent(intent: Intent) { + intent.putExtra(EXTRA_ENTRY_SELECTION_MODE, true) + } + + fun doEntrySelectionAction(intent: Intent, + standardAction: () -> Unit, + keyboardAction: () -> Unit, + autofillAction: (assistStructure: AssistStructure) -> Unit) { + var assistStructure: AssistStructure? = null + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + assistStructure = AutofillHelper.retrieveAssistStructure(intent) + assistStructure?.let { + autofillAction.invoke(assistStructure) + } + } + if (assistStructure == null) { + if (intent.getBooleanExtra(EXTRA_ENTRY_SELECTION_MODE, false)) { + intent.putExtra(EXTRA_ENTRY_SELECTION_MODE, false) + keyboardAction.invoke() + } else { + standardAction.invoke() + } + } + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/selection/KeyboardEntryRetrieverActivity.kt b/app/src/main/java/com/kunzisoft/keepass/selection/KeyboardEntryRetrieverActivity.kt deleted file mode 100644 index 8d4c37490..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/selection/KeyboardEntryRetrieverActivity.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.kunzisoft.keepass.selection - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.preference.PreferenceManager -import android.support.v7.app.AppCompatActivity -import android.util.Log -import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.activities.GroupActivity -import com.kunzisoft.keepass.app.App -import com.kunzisoft.keepass.fileselect.FileSelectActivity -import com.kunzisoft.keepass.magikeyboard.KeyboardEntryNotificationService -import com.kunzisoft.keepass.magikeyboard.MagikIME -import com.kunzisoft.keepass.model.Entry -import com.kunzisoft.keepass.selection.EntrySelectionHelper.ENTRY_SELECTION_RESPONSE_REQUEST_CODE -import com.kunzisoft.keepass.selection.EntrySelectionHelper.EXTRA_ENTRY_SELECTION_MODE -import com.kunzisoft.keepass.timeout.TimeoutHelper - -class KeyboardEntryRetrieverActivity : AppCompatActivity() { - - companion object { - - val TAG = KeyboardEntryRetrieverActivity::class.java.name!! - } - - override fun onCreate(savedInstanceState: Bundle?) { - TimeoutHelper.checkTime(this) {} - if (App.getDB().loaded) - GroupActivity.launchForKeyboardResult(this, true) - else { - // Pass extra to get entry - FileSelectActivity.launchForKeyboardResult(this) - } - - super.onCreate(savedInstanceState) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - Log.d(TAG, "Retrieve the entry selected, requestCode: $requestCode, resultCode: $resultCode") - if (requestCode == ENTRY_SELECTION_RESPONSE_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - val entry = data?.getParcelableExtra(EXTRA_ENTRY_SELECTION_MODE) - Log.d(TAG, "Set the entry ${entry?.title} to keyboard") - MagikIME.setEntryKey(entry) - - // Show the notification if allowed in Preferences - val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) - if (sharedPreferences.getBoolean(getString(R.string.keyboard_notification_entry_key), - resources.getBoolean(R.bool.keyboard_notification_entry_default))) { - val notificationIntent = Intent(this, KeyboardEntryNotificationService::class.java) - startService(notificationIntent) - } - } - if (resultCode == Activity.RESULT_CANCELED) { - Log.w(TAG, "Entry not retrieved") - } - } - finish() - } -} diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.java b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.java index e40d75832..499a664e5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.java @@ -197,6 +197,12 @@ public class PreferencesUtil { context.getResources().getBoolean(R.bool.enable_read_only_default)); } + public static boolean enableKeyboardNotificationEntry(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getBoolean(context.getString(R.string.keyboard_notification_entry_key), + context.getResources().getBoolean(R.bool.keyboard_notification_entry_default)); + } + /** * All preference keys associated with education */ diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt index 5a27c5b31..9af21ceed 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt @@ -48,7 +48,7 @@ open class SettingsActivity : LockingActivity(), MainPreferenceFragment.Callback intent.putExtra(TIMEOUT_ENABLE_KEY, timeoutEnable) if (!timeoutEnable) { activity.startActivity(intent) - } else if (TimeoutHelper.checkTime(activity)) { + } else if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) { activity.startActivity(intent) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.kt b/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.kt index 575e2b7a8..903ce1a8c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.kt @@ -78,9 +78,10 @@ object TimeoutHelper { } /** - * Check the time previously record with recordTime and do the shutdown action if timeout + * Check the time previously record with recordTime and do the [timeoutAction] if timeout + * return 'false' if timeout, 'true' if in time */ - fun checkTime(context: Context, shutdown: (() -> Unit)): Boolean { + fun checkTime(context: Context, timeoutAction: (() -> Unit)? = null): Boolean { // Cancel the lock PendingIntent if (App.getDB().loaded) { val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager @@ -118,7 +119,7 @@ object TimeoutHelper { if (diff >= appTimeout) { // We have timed out App.getDB().loaded = false - shutdown.invoke() + timeoutAction?.invoke() return false } return true @@ -127,14 +128,14 @@ object TimeoutHelper { /** * Check the time previously record with recordTime and lock the activity if timeout */ - fun checkTime(activity: Activity): Boolean { + fun checkTimeAndLockIfTimeout(activity: Activity): Boolean { return checkTime(activity) { activity.lock() } } fun lockOrResetTimeout(activity: Activity, action: (() -> Unit)? = null) { - if (checkTime(activity)) { + if (checkTimeAndLockIfTimeout(activity)) { recordTime(activity) action?.invoke() }