mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Links to open external applications
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"/>
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
|
||||
@@ -22,8 +22,10 @@ package com.kunzisoft.keepass.utils
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.kunzisoft.keepass.R
|
||||
@@ -151,6 +153,24 @@ object UriUtil {
|
||||
gotoUrl(context, context.getString(resId))
|
||||
}
|
||||
|
||||
fun isExternalAppInstalled(context: Context, packageName: String): Boolean {
|
||||
try {
|
||||
context.applicationContext.packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e(javaClass.simpleName, "App not accessible", e)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun openExternalApp(context: Context, packageName: String) {
|
||||
try {
|
||||
context.startActivity(context.applicationContext.packageManager.getLaunchIntentForPackage(packageName))
|
||||
} catch (e: Exception) {
|
||||
Log.e(javaClass.simpleName, "App cannot be open", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun getBinaryDir(context: Context): File {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
context.applicationContext.noBackupFilesDir
|
||||
|
||||
@@ -30,7 +30,8 @@ import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.text.util.LinkifyCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import java.util.regex.Pattern
|
||||
import com.kunzisoft.keepass.model.EntryInfo.Companion.APPLICATION_ID_FIELD_NAME
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
|
||||
class EntryField @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@@ -101,9 +102,7 @@ class EntryField @JvmOverloads constructor(context: Context,
|
||||
setTextIsSelectable(true)
|
||||
}
|
||||
applyHiddenStyle(isProtected && !showButtonView.isSelected)
|
||||
if (valueView.autoLinkMask == LINKIFY_MASKS) {
|
||||
linkify()
|
||||
}
|
||||
if (!isProtected) linkify()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,13 +112,23 @@ class EntryField @JvmOverloads constructor(context: Context,
|
||||
}
|
||||
|
||||
private fun linkify() {
|
||||
valueView.autoLinkMask = LINKIFY_MASKS
|
||||
LinkifyCompat.addLinks(valueView, LINKIFY_MASKS)
|
||||
when {
|
||||
labelView.text.contains(APPLICATION_ID_FIELD_NAME) -> {
|
||||
val packageName = valueView.text.toString()
|
||||
if (UriUtil.isExternalAppInstalled(context, packageName)) {
|
||||
valueView.customLink {
|
||||
UriUtil.openExternalApp(context, packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
LinkifyCompat.addLinks(valueView, Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setLinkAll() {
|
||||
valueView.autoLinkMask = LINKIFY_ALL
|
||||
LinkifyCompat.addLinks(valueView, LINKIFY_ALL)
|
||||
LinkifyCompat.addLinks(valueView, Linkify.ALL)
|
||||
}
|
||||
|
||||
fun activateCopyButton(enable: Boolean) {
|
||||
@@ -131,8 +140,4 @@ class EntryField @JvmOverloads constructor(context: Context,
|
||||
copyButtonView.setOnClickListener(onClickActionListener)
|
||||
copyButtonView.visibility = if (onClickActionListener == null) GONE else VISIBLE
|
||||
}
|
||||
companion object {
|
||||
private const val LINKIFY_MASKS = Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES
|
||||
private const val LINKIFY_ALL = Linkify.ALL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,13 @@ import android.animation.ValueAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Typeface
|
||||
import android.text.Selection
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.method.PasswordTransformationMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.TextView
|
||||
@@ -68,6 +74,21 @@ fun TextView.strikeOut(strikeOut: Boolean) {
|
||||
paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||
}
|
||||
|
||||
fun TextView.customLink(listener: (View) -> Unit) {
|
||||
val spannableString = SpannableString(this.text)
|
||||
val clickableSpan = object : ClickableSpan() {
|
||||
override fun onClick(view: View) {
|
||||
Selection.setSelection((view as TextView).text as Spannable, 0)
|
||||
view.invalidate()
|
||||
listener.invoke(view)
|
||||
}
|
||||
}
|
||||
spannableString.setSpan(clickableSpan, 0, text.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
this.movementMethod = LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
|
||||
this.setText(spannableString, TextView.BufferType.SPANNABLE)
|
||||
}
|
||||
|
||||
fun Snackbar.asError(): Snackbar {
|
||||
this.view.apply {
|
||||
setBackgroundColor(Color.RED)
|
||||
|
||||
Reference in New Issue
Block a user