Change file creation methods

This commit is contained in:
J-Jamet
2021-04-03 19:40:55 +02:00
parent 7b5e9d2344
commit d5fbc8393f
8 changed files with 123 additions and 141 deletions

View File

@@ -39,6 +39,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
@@ -93,6 +94,8 @@ class EntryActivity : LockingActivity() {
private var clipboardHelper: ClipboardHelper? = null
private var mFirstLaunchOfActivity: Boolean = false
private var mExternalFileHelper: ExternalFileHelper? = null
private var iconColor: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
@@ -140,6 +143,9 @@ class EntryActivity : LockingActivity() {
clipboardHelper = ClipboardHelper(this)
mFirstLaunchOfActivity = savedInstanceState?.getBoolean(KEY_FIRST_LAUNCH_ACTIVITY) ?: true
// Init SAF manager
mExternalFileHelper = ExternalFileHelper(this)
// Init attachment service binder manager
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
@@ -344,7 +350,7 @@ class EntryActivity : LockingActivity() {
// Manage attachments
entryContentsView?.assignAttachments(entryInfo.attachments.toSet(), StreamDirection.DOWNLOAD) { attachmentItem ->
createDocument(this, attachmentItem.name)?.let { requestCode ->
mExternalFileHelper?.createDocument(attachmentItem.name)?.let { requestCode ->
mAttachmentsToDownload[requestCode] = attachmentItem
}
}
@@ -380,7 +386,7 @@ class EntryActivity : LockingActivity() {
}
}
onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
if (createdFileUri != null) {
mAttachmentsToDownload[requestCode]?.let { attachmentToDownload ->
mAttachmentFileBinderManager

View File

@@ -45,7 +45,7 @@ import com.kunzisoft.keepass.activities.dialogs.*
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE
import com.kunzisoft.keepass.activities.fragments.EntryEditFragment
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
import com.kunzisoft.keepass.autofill.AutofillComponent
@@ -103,7 +103,7 @@ class EntryEditActivity : LockingActivity(),
private var lockView: View? = null
// To manage attachments
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mAttachmentFileBinderManager: AttachmentFileBinderManager? = null
private var mAllowMultipleAttachments: Boolean = false
private var mTempAttachments = ArrayList<EntryAttachmentState>()
@@ -241,7 +241,7 @@ class EntryEditActivity : LockingActivity(),
}
// To retrieve attachment
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
// Save button
@@ -459,7 +459,7 @@ class EntryEditActivity : LockingActivity(),
* Add a new attachment
*/
private fun addNewAttachment(item: MenuItem) {
mSelectFileHelper?.selectFileOnClickViewListener?.onMenuItemClick(item)
mExternalFileHelper?.selectFileOnClickViewListener?.onMenuItemClick(item)
}
override fun onValidateUploadFileTooBig(attachmentToUploadUri: Uri?, fileName: String?) {
@@ -505,7 +505,7 @@ class EntryEditActivity : LockingActivity(),
entryEditFragment?.icon = icon
}
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
uri?.let { attachmentToUploadUri ->
UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile ->
documentFile.name?.let { fileName ->
@@ -655,7 +655,7 @@ class EntryEditActivity : LockingActivity(),
&& entryEditActivityEducation.checkAndPerformedAttachmentEducation(
attachmentView,
{
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(attachmentView)
mExternalFileHelper?.selectFileOnClickViewListener?.onClick(attachmentView)
},
{
performedNextEducation(entryEditActivityEducation)

View File

@@ -42,7 +42,7 @@ import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
@@ -82,7 +82,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
private var mDatabaseFileUri: Uri? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
@@ -103,10 +103,10 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
createDatabaseButtonView?.setOnClickListener { createNewFile() }
// Open database button
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
openDatabaseButtonView = findViewById(R.id.open_keyfile_button)
openDatabaseButtonView?.apply {
mSelectFileHelper?.selectFileOnClickViewListener?.let {
mExternalFileHelper?.selectFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
@@ -234,7 +234,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
* Create a new file by calling the content provider
*/
private fun createNewFile() {
createDocument(this, getString(R.string.database_file_name_default) +
mExternalFileHelper?.createDocument( getString(R.string.database_file_name_default) +
getString(R.string.database_file_extension_default), "application/x-keepass")
}
@@ -286,7 +286,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
// Show open and create button or special mode
when (mSpecialMode) {
SpecialMode.DEFAULT -> {
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
if (ExternalFileHelper.allowCreateDocumentByStorageAccessFramework(packageManager)) {
// There is an activity which can handle this intent.
createDatabaseButtonView?.visibility = View.VISIBLE
} else{
@@ -359,14 +359,14 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
}
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
if (uri != null) {
launchPasswordActivityWithPath(uri)
}
}
// Retrieve the created URI from the file manager
onCreateDocumentResult(requestCode, resultCode, data) { databaseFileCreatedUri ->
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { databaseFileCreatedUri ->
mDatabaseFileUri = databaseFileCreatedUri
if (mDatabaseFileUri != null) {
AssignMasterKeyDialogFragment.getInstance(true)
@@ -414,7 +414,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
openDatabaseButtonView!!,
{tapTargetView ->
tapTargetView?.let {
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(it)
mExternalFileHelper?.selectFileOnClickViewListener?.onClick(it)
}
},
{}

View File

@@ -34,7 +34,7 @@ import androidx.fragment.app.commit
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.fragments.IconPickerFragment
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
import com.kunzisoft.keepass.database.element.Database
@@ -66,7 +66,7 @@ class IconPickerActivity : LockingActivity() {
private var mDatabase: Database? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -87,10 +87,10 @@ class IconPickerActivity : LockingActivity() {
uploadButton = findViewById(R.id.icon_picker_upload)
if (mDatabase?.allowCustomIcons == true) {
uploadButton.setOnClickListener {
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(it)
mExternalFileHelper?.selectFileOnClickViewListener?.onClick(it)
}
uploadButton.setOnLongClickListener {
mSelectFileHelper?.selectFileOnClickViewListener?.onLongClick(it)
mExternalFileHelper?.selectFileOnClickViewListener?.onLongClick(it)
true
}
} else {
@@ -124,7 +124,7 @@ class IconPickerActivity : LockingActivity() {
// Focus view to reinitialize timeout
findViewById<ViewGroup>(R.id.icon_picker_container)?.resetAppTimeoutWhenViewFocusedOrChanged(this)
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
iconPickerViewModel.standardIconPicked.observe(this) { iconStandard ->
mIconImage.standard = iconStandard
@@ -281,7 +281,7 @@ class IconPickerActivity : LockingActivity() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
addCustomIcon(uri)
}
}

View File

@@ -44,7 +44,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
@@ -95,7 +95,7 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
private var mDatabaseKeyFileUri: Uri? = null
private var mRememberKeyFile: Boolean = false
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mPermissionAsked = false
private var readOnly: Boolean = false
@@ -138,9 +138,9 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
readOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrPreference(this, savedInstanceState)
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
mSelectFileHelper = SelectFileHelper(this@PasswordActivity)
mExternalFileHelper = ExternalFileHelper(this@PasswordActivity)
keyFileSelectionView?.apply {
mSelectFileHelper?.selectFileOnClickViewListener?.let {
mExternalFileHelper?.selectFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
@@ -702,7 +702,7 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
}
var keyFileResult = false
mSelectFileHelper?.let {
mExternalFileHelper?.let {
keyFileResult = it.onActivityResultCallback(requestCode, resultCode, data
) { uri ->
if (uri != null) {

View File

@@ -30,13 +30,12 @@ import android.text.SpannableStringBuilder
import android.text.TextWatcher
import android.view.View
import android.widget.CompoundButton
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.model.MainCredential
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.KeyFileSelectionView
@@ -60,7 +59,7 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
private var mListener: AssignPasswordDialogListener? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mEmptyPasswordConfirmationDialog: AlertDialog? = null
private var mNoKeyConfirmationDialog: AlertDialog? = null
@@ -133,10 +132,10 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
keyFileCheckBox = rootView?.findViewById(R.id.keyfile_checkox)
keyFileSelectionView = rootView?.findViewById(R.id.keyfile_selection)
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
keyFileSelectionView?.apply {
setOnClickListener(mSelectFileHelper?.selectFileOnClickViewListener)
setOnLongClickListener(mSelectFileHelper?.selectFileOnClickViewListener)
setOnClickListener(mExternalFileHelper?.selectFileOnClickViewListener)
setOnLongClickListener(mExternalFileHelper?.selectFileOnClickViewListener)
}
val dialog = builder.create()
@@ -289,7 +288,7 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
uri?.let { pathUri ->
UriUtil.getFileData(requireContext(), uri)?.length()?.let { lengthFile ->
keyFileSelectionView?.error = null

View File

@@ -20,7 +20,6 @@
package com.kunzisoft.keepass.activities.helpers
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
@@ -35,15 +34,15 @@ import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
import com.kunzisoft.keepass.utils.UriUtil
class SelectFileHelper {
class ExternalFileHelper {
private var activity: Activity? = null
private var activity: FragmentActivity? = null
private var fragment: Fragment? = null
val selectFileOnClickViewListener: SelectFileOnClickViewListener
get() = SelectFileOnClickViewListener()
constructor(context: Activity) {
constructor(context: FragmentActivity) {
this.activity = context
this.fragment = null
}
@@ -60,18 +59,10 @@ class SelectFileHelper {
private fun onAbstractClick(longClick: Boolean = false) {
try {
if (longClick) {
try {
openActivityWithActionGetContent()
} catch (e: Exception) {
openActivityWithActionOpenDocument()
}
} else {
try {
openActivityWithActionOpenDocument()
} catch (e: Exception) {
openActivityWithActionGetContent()
}
try {
openDocument(longClick)
} catch (e: Exception) {
openDocument(!longClick)
}
} catch (e: Exception) {
Log.e(TAG, "Enable to start the file picker activity", e)
@@ -96,6 +87,14 @@ class SelectFileHelper {
}
}
fun openDocument(getContent: Boolean) {
if (getContent) {
openActivityWithActionGetContent()
} else {
openActivityWithActionOpenDocument()
}
}
@SuppressLint("InlinedApi")
private fun openActivityWithActionOpenDocument() {
val intentOpenDocument = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
@@ -187,10 +186,7 @@ class SelectFileHelper {
* @param keyFileCallback Callback retrieve from data
* @return true if requestCode was captured, false elsechere
*/
fun onActivityResultCallback(
requestCode: Int,
resultCode: Int,
data: Intent?,
fun onActivityResultCallback(requestCode: Int, resultCode: Int, data: Intent?,
keyFileCallback: ((uri: Uri?) -> Unit)?): Boolean {
when (requestCode) {
@@ -231,6 +227,50 @@ class SelectFileHelper {
return false
}
private fun showFileManagerDialogFragment() {
if (fragment != null) {
fragment?.parentFragmentManager
} else {
activity?.supportFragmentManager
}?.let { fragmentManager ->
FileManagerDialogFragment().show(fragmentManager, "browserDialog")
}
}
fun createDocument(titleString: String,
typeString: String = "application/octet-stream"): Int? {
val idCode = getUnusedCreateFileRequestCode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
putExtra(Intent.EXTRA_TITLE, titleString)
}
if (fragment != null)
fragment?.startActivityForResult(intent, idCode)
else
activity?.startActivityForResult(intent, idCode)
return idCode
} catch (e: Exception) {
showFileManagerDialogFragment()
}
} else {
showFileManagerDialogFragment()
}
return null
}
fun onCreateDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
action: (fileCreated: Uri?)->Unit) {
// Retrieve the created URI from the file manager
if (fileRequestCodes.contains(requestCode) && resultCode == RESULT_OK) {
action.invoke(data?.data)
fileRequestCodes.remove(requestCode)
}
}
companion object {
private const val TAG = "OpenFileHelper"
@@ -240,5 +280,28 @@ class SelectFileHelper {
private const val GET_CONTENT = 25745
private const val OPEN_DOC = 25845
private const val FILE_BROWSE = 25645
private var CREATE_FILE_REQUEST_CODE_DEFAULT = 3853
private var fileRequestCodes = ArrayList<Int>()
private fun getUnusedCreateFileRequestCode(): Int {
val newCreateFileRequestCode = CREATE_FILE_REQUEST_CODE_DEFAULT++
fileRequestCodes.add(newCreateFileRequestCode)
return newCreateFileRequestCode
}
@SuppressLint("InlinedApi")
fun allowCreateDocumentByStorageAccessFramework(packageManager: PackageManager): Boolean {
return when {
// To check if a custom file manager can manage the ACTION_CREATE_DOCUMENT
Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT -> {
packageManager.queryIntentActivities(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/x-keepass"
}, PackageManager.MATCH_DEFAULT_ONLY).isNotEmpty()
}
else -> true
}
}
}
}

View File

@@ -1,86 +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.utils
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
private var CREATE_FILE_REQUEST_CODE_DEFAULT = 3853
private var fileRequestCodes = ArrayList<Int>()
fun getUnusedCreateFileRequestCode(): Int {
val newCreateFileRequestCode = CREATE_FILE_REQUEST_CODE_DEFAULT++
fileRequestCodes.add(newCreateFileRequestCode)
return newCreateFileRequestCode
}
@SuppressLint("InlinedApi")
fun allowCreateDocumentByStorageAccessFramework(packageManager: PackageManager): Boolean {
return when {
// To check if a custom file manager can manage the ACTION_CREATE_DOCUMENT
Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT -> {
packageManager.queryIntentActivities(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/x-keepass"
}, PackageManager.MATCH_DEFAULT_ONLY).isNotEmpty()
}
else -> true
}
}
fun createDocument(activity: FragmentActivity,
titleString: String,
typeString: String = "application/octet-stream"): Int? {
val idCode = getUnusedCreateFileRequestCode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
activity.startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
putExtra(Intent.EXTRA_TITLE, titleString)
}, idCode)
return idCode
} catch (e: Exception) {
FileManagerDialogFragment().show(activity.supportFragmentManager, "browserDialog")
}
} else {
FileManagerDialogFragment().show(activity.supportFragmentManager, "browserDialog")
}
return null
}
fun onCreateDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
action: (fileCreated: Uri?)->Unit) {
// Retrieve the created URI from the file manager
if (fileRequestCodes.contains(requestCode) && resultCode == Activity.RESULT_OK) {
action.invoke(data?.data)
fileRequestCodes.remove(requestCode)
}
}