Compile against SDK 33 (#2023)
* Compile against SDK 33 * autofill-parser: fix warnings for SDK 33 upgrade * app: fix warnings for SDK 33 upgrade * Mark all clipboard content as sensitive from crypto activities * Skip Snackbar on Android 13 and above * detekt: raise `TooManyFunctions` limit to 15
This commit is contained in:
parent
9cd2f5f446
commit
ade73fd5bc
29 changed files with 210 additions and 71 deletions
|
@ -22,6 +22,9 @@ import app.passwordstore.databinding.ActivityOreoAutofillPublisherChangedBinding
|
||||||
import app.passwordstore.util.autofill.AutofillMatcher
|
import app.passwordstore.util.autofill.AutofillMatcher
|
||||||
import app.passwordstore.util.autofill.AutofillPublisherChangedException
|
import app.passwordstore.util.autofill.AutofillPublisherChangedException
|
||||||
import app.passwordstore.util.extensions.asLog
|
import app.passwordstore.util.extensions.asLog
|
||||||
|
import app.passwordstore.util.extensions.getApplicationInfoCompat
|
||||||
|
import app.passwordstore.util.extensions.getPackageInfoCompat
|
||||||
|
import app.passwordstore.util.extensions.getParcelableExtraCompat
|
||||||
import app.passwordstore.util.extensions.viewBinding
|
import app.passwordstore.util.extensions.viewBinding
|
||||||
import com.github.androidpasswordstore.autofillparser.FormOrigin
|
import com.github.androidpasswordstore.autofillparser.FormOrigin
|
||||||
import com.github.androidpasswordstore.autofillparser.computeCertificatesHash
|
import com.github.androidpasswordstore.autofillparser.computeCertificatesHash
|
||||||
|
@ -93,7 +96,8 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
|
||||||
this@AutofillPublisherChangedActivity,
|
this@AutofillPublisherChangedActivity,
|
||||||
FormOrigin.App(appPackage)
|
FormOrigin.App(appPackage)
|
||||||
)
|
)
|
||||||
val fillResponse = intent.getParcelableExtra<FillResponse>(EXTRA_FILL_RESPONSE_AFTER_RESET)
|
val fillResponse =
|
||||||
|
intent.getParcelableExtraCompat<FillResponse>(EXTRA_FILL_RESPONSE_AFTER_RESET)
|
||||||
setResult(
|
setResult(
|
||||||
RESULT_OK,
|
RESULT_OK,
|
||||||
Intent().apply { putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillResponse) }
|
Intent().apply { putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillResponse) }
|
||||||
|
@ -106,11 +110,13 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
|
||||||
private fun showPackageInfo() {
|
private fun showPackageInfo() {
|
||||||
runCatching {
|
runCatching {
|
||||||
with(binding) {
|
with(binding) {
|
||||||
val packageInfo = packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA)
|
val packageInfo =
|
||||||
|
packageManager.getPackageInfoCompat(appPackage, PackageManager.GET_META_DATA)
|
||||||
val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime)
|
val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime)
|
||||||
warningAppInstallDate.text =
|
warningAppInstallDate.text =
|
||||||
getString(R.string.oreo_autofill_warning_publisher_install_time, installTime)
|
getString(R.string.oreo_autofill_warning_publisher_install_time, installTime)
|
||||||
val appInfo = packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA)
|
val appInfo =
|
||||||
|
packageManager.getApplicationInfoCompat(appPackage, PackageManager.GET_META_DATA)
|
||||||
warningAppName.text =
|
warningAppName.text =
|
||||||
getString(
|
getString(
|
||||||
R.string.oreo_autofill_warning_publisher_app_name,
|
R.string.oreo_autofill_warning_publisher_app_name,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.PersistableBundle
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
@ -68,8 +69,12 @@ open class BasePgpActivity : AppCompatActivity() {
|
||||||
) {
|
) {
|
||||||
val clipboard = clipboard ?: return
|
val clipboard = clipboard ?: return
|
||||||
val clip = ClipData.newPlainText("pgp_handler_result_pm", text)
|
val clip = ClipData.newPlainText("pgp_handler_result_pm", text)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
clip.description.extras =
|
||||||
|
PersistableBundle().apply { putBoolean("android.content.extra.IS_SENSITIVE", true) }
|
||||||
|
}
|
||||||
clipboard.setPrimaryClip(clip)
|
clipboard.setPrimaryClip(clip)
|
||||||
if (showSnackbar) {
|
if (showSnackbar && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
snackbar(message = resources.getString(snackbarTextRes))
|
snackbar(message = resources.getString(snackbarTextRes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +85,7 @@ open class BasePgpActivity : AppCompatActivity() {
|
||||||
* clearing the clipboard.
|
* clearing the clipboard.
|
||||||
*/
|
*/
|
||||||
fun copyPasswordToClipboard(password: String?) {
|
fun copyPasswordToClipboard(password: String?) {
|
||||||
copyTextToClipboard(password, showSnackbar = false)
|
copyTextToClipboard(password)
|
||||||
|
|
||||||
val clearAfter = settings.getString(PreferenceKeys.GENERAL_SHOW_TIME)?.toIntOrNull() ?: 45
|
val clearAfter = settings.getString(PreferenceKeys.GENERAL_SHOW_TIME)?.toIntOrNull() ?: 45
|
||||||
|
|
||||||
|
@ -95,9 +100,6 @@ open class BasePgpActivity : AppCompatActivity() {
|
||||||
} else {
|
} else {
|
||||||
startService(service)
|
startService(service)
|
||||||
}
|
}
|
||||||
snackbar(message = resources.getString(R.string.clipboard_password_toast_text, clearAfter))
|
|
||||||
} else {
|
|
||||||
snackbar(message = resources.getString(R.string.clipboard_password_no_clear_toast_text))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class DecryptActivity : BasePgpActivity() {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> onBackPressed()
|
android.R.id.home -> onBackPressedDispatcher.onBackPressed()
|
||||||
R.id.edit_password -> editPassword()
|
R.id.edit_password -> editPassword()
|
||||||
R.id.share_password_as_plaintext -> shareAsPlaintext()
|
R.id.share_password_as_plaintext -> shareAsPlaintext()
|
||||||
R.id.copy_password -> copyPasswordToClipboard(passwordEntry?.password)
|
R.id.copy_password -> copyPasswordToClipboard(passwordEntry?.password)
|
||||||
|
|
|
@ -262,7 +262,7 @@ class PasswordCreationActivity : BasePgpActivity() {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
R.id.save_password -> {
|
R.id.save_password -> {
|
||||||
copy = false
|
copy = false
|
||||||
|
|
|
@ -49,7 +49,7 @@ class SelectFolderActivity : AppCompatActivity(R.layout.select_folder_layout) {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
R.id.crypto_select -> selectFolder()
|
R.id.crypto_select -> selectFolder()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
|
|
@ -69,7 +69,7 @@ class GitConfigActivity : BaseGitActivity() {
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
|
|
@ -202,7 +202,7 @@ class GitServerConfigActivity : BaseGitActivity() {
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
package app.passwordstore.ui.onboarding.activity
|
package app.passwordstore.ui.onboarding.activity
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
|
|
||||||
|
@ -14,13 +15,11 @@ class OnboardingActivity : AppCompatActivity(R.layout.activity_onboarding) {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
}
|
val callback = onBackPressedDispatcher.addCallback(enabled = false) { finishAffinity() }
|
||||||
|
supportFragmentManager.addOnBackStackChangedListener {
|
||||||
override fun onBackPressed() {
|
if (supportFragmentManager.backStackEntryCount == 0) {
|
||||||
if (supportFragmentManager.backStackEntryCount == 0) {
|
callback.isEnabled = true
|
||||||
finishAffinity()
|
}
|
||||||
} else {
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
package app.passwordstore.ui.passwords
|
package app.passwordstore.ui.passwords
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -14,7 +13,6 @@ import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.MenuItem.OnActionExpandListener
|
import android.view.MenuItem.OnActionExpandListener
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
@ -77,18 +75,6 @@ class PasswordStore : BaseGitActivity() {
|
||||||
ViewModelProvider.AndroidViewModelFactory(application)
|
ViewModelProvider.AndroidViewModelFactory(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val storagePermissionRequest =
|
|
||||||
registerForActivityResult(RequestPermission()) { granted ->
|
|
||||||
if (granted) checkLocalRepository()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val directorySelectAction =
|
|
||||||
registerForActivityResult(StartActivityForResult()) { result ->
|
|
||||||
if (result.resultCode == RESULT_OK) {
|
|
||||||
checkLocalRepository()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val listRefreshAction =
|
private val listRefreshAction =
|
||||||
registerForActivityResult(StartActivityForResult()) { result ->
|
registerForActivityResult(StartActivityForResult()) { result ->
|
||||||
if (result.resultCode == RESULT_OK) {
|
if (result.resultCode == RESULT_OK) {
|
||||||
|
@ -196,7 +182,6 @@ class PasswordStore : BaseGitActivity() {
|
||||||
return super.onKeyDown(keyCode, event)
|
return super.onKeyDown(keyCode, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_pwdstore)
|
setContentView(R.layout.activity_pwdstore)
|
||||||
|
@ -313,12 +298,14 @@ class PasswordStore : BaseGitActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.refresh -> refreshPasswordList()
|
R.id.refresh -> refreshPasswordList()
|
||||||
android.R.id.home -> onBackPressed()
|
android.R.id.home -> onBackPressedDispatcher.onBackPressed()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if (getPasswordFragment()?.onBackPressedInActivity() != true) super.onBackPressed()
|
if (getPasswordFragment()?.onBackPressedInActivity() != true) super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.view.MenuItem
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
|
import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
|
||||||
|
import app.passwordstore.util.extensions.getParcelableCompat
|
||||||
import app.passwordstore.util.extensions.viewBinding
|
import app.passwordstore.util.extensions.viewBinding
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import de.Maxr1998.modernpreferences.Preference
|
import de.Maxr1998.modernpreferences.Preference
|
||||||
|
@ -84,7 +85,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
savedInstanceState
|
savedInstanceState
|
||||||
?.getParcelable<PreferencesAdapter.SavedState>("adapter")
|
?.getParcelableCompat<PreferencesAdapter.SavedState>("adapter")
|
||||||
?.let(adapter::loadSavedState)
|
?.let(adapter::loadSavedState)
|
||||||
binding.preferenceRecyclerView.adapter = adapter
|
binding.preferenceRecyclerView.adapter = adapter
|
||||||
}
|
}
|
||||||
|
@ -106,6 +107,8 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if (!preferencesAdapter.goBack()) super.onBackPressed()
|
if (!preferencesAdapter.goBack()) super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class SshKeyGenActivity : AppCompatActivity() {
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
|
|
@ -7,9 +7,11 @@ package app.passwordstore.util.autofill
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.IntentSender
|
import android.content.IntentSender
|
||||||
|
import android.os.Build
|
||||||
import android.service.autofill.Dataset
|
import android.service.autofill.Dataset
|
||||||
import android.service.autofill.FillCallback
|
import android.service.autofill.FillCallback
|
||||||
import android.service.autofill.FillResponse
|
import android.service.autofill.FillResponse
|
||||||
|
import android.service.autofill.Presentations
|
||||||
import android.service.autofill.SaveInfo
|
import android.service.autofill.SaveInfo
|
||||||
import android.view.inputmethod.InlineSuggestionsRequest
|
import android.view.inputmethod.InlineSuggestionsRequest
|
||||||
import android.widget.inline.InlinePresentationSpec
|
import android.widget.inline.InlinePresentationSpec
|
||||||
|
@ -60,6 +62,23 @@ constructor(
|
||||||
intentSender: IntentSender,
|
intentSender: IntentSender,
|
||||||
metadata: DatasetMetadata,
|
metadata: DatasetMetadata,
|
||||||
imeSpec: InlinePresentationSpec?,
|
imeSpec: InlinePresentationSpec?,
|
||||||
|
): Dataset {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
makeIntentDataSetTiramisu(context, action, intentSender, metadata, imeSpec)
|
||||||
|
} else {
|
||||||
|
makeIntentDataSetR(context, action, intentSender, metadata, imeSpec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper for creating an Autofill [Dataset]s for Android R and above. */
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
private fun makeIntentDataSetR(
|
||||||
|
context: Context,
|
||||||
|
action: AutofillAction,
|
||||||
|
intentSender: IntentSender,
|
||||||
|
metadata: DatasetMetadata,
|
||||||
|
imeSpec: InlinePresentationSpec?,
|
||||||
): Dataset {
|
): Dataset {
|
||||||
return Dataset.Builder(makeRemoteView(context, metadata)).run {
|
return Dataset.Builder(makeRemoteView(context, metadata)).run {
|
||||||
fillWith(scenario, action, credentials = null)
|
fillWith(scenario, action, credentials = null)
|
||||||
|
@ -74,6 +93,30 @@ constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Helper for creating Autofill [Dataset]s for Android Tiramisu and above. */
|
||||||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
|
private fun makeIntentDataSetTiramisu(
|
||||||
|
context: Context,
|
||||||
|
action: AutofillAction,
|
||||||
|
intentSender: IntentSender,
|
||||||
|
metadata: DatasetMetadata,
|
||||||
|
imeSpec: InlinePresentationSpec?,
|
||||||
|
): Dataset {
|
||||||
|
val presentationsBuilder = Presentations.Builder()
|
||||||
|
if (imeSpec != null) {
|
||||||
|
val inlinePresentation = makeInlinePresentation(context, imeSpec, metadata)
|
||||||
|
if (inlinePresentation != null) {
|
||||||
|
presentationsBuilder.setInlinePresentation(inlinePresentation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val presentations = presentationsBuilder.build()
|
||||||
|
return Dataset.Builder(presentations).run {
|
||||||
|
fillWith(scenario, action, credentials = null)
|
||||||
|
setAuthentication(intentSender)
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun makeMatchDataset(
|
private fun makeMatchDataset(
|
||||||
context: Context,
|
context: Context,
|
||||||
file: File,
|
file: File,
|
||||||
|
|
|
@ -54,6 +54,7 @@ constructor(
|
||||||
private val scenarioSupportsSave = scenario.hasPasswordFieldsToSave
|
private val scenarioSupportsSave = scenario.hasPasswordFieldsToSave
|
||||||
private val canBeSaved = saveFlags != null && scenarioSupportsSave
|
private val canBeSaved = saveFlags != null && scenarioSupportsSave
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private fun makeIntentDataset(
|
private fun makeIntentDataset(
|
||||||
context: Context,
|
context: Context,
|
||||||
action: AutofillAction,
|
action: AutofillAction,
|
||||||
|
@ -212,7 +213,7 @@ constructor(
|
||||||
if (Build.VERSION.SDK_INT >= 28) {
|
if (Build.VERSION.SDK_INT >= 28) {
|
||||||
Dataset.Builder()
|
Dataset.Builder()
|
||||||
} else {
|
} else {
|
||||||
Dataset.Builder(makeRemoteView(context, makeEmptyMetadata()))
|
@Suppress("DEPRECATION") Dataset.Builder(makeRemoteView(context, makeEmptyMetadata()))
|
||||||
}
|
}
|
||||||
return builder.run {
|
return builder.run {
|
||||||
if (scenario != null) fillWith(scenario, action, credentials)
|
if (scenario != null) fillWith(scenario, action, credentials)
|
||||||
|
|
|
@ -10,7 +10,14 @@ import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageManager.ApplicationInfoFlags
|
||||||
|
import android.content.pm.PackageManager.PackageInfoFlags
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -132,3 +139,45 @@ fun SharedPreferences.getString(key: String): String? = getString(key, null)
|
||||||
fun String.base64(): String {
|
fun String.base64(): String {
|
||||||
return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP)
|
return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> Bundle.getParcelableCompat(key: String): T? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getParcelable(key, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getParcelable(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Parcelable> Bundle.getParcelableArrayListCompat(
|
||||||
|
key: String
|
||||||
|
): ArrayList<T>? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getParcelableArrayList(key, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getParcelableArrayList(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Parcelable> Intent.getParcelableExtraCompat(key: String): T? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getParcelableExtra(key, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getParcelableExtra(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int): PackageInfo {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getPackageInfo(packageName, PackageInfoFlags.of(flags.toLong()))
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getPackageInfo(packageName, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): ApplicationInfo {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getApplicationInfo(packageName, ApplicationInfoFlags.of(flags.toLong()))
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getApplicationInfo(packageName, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,7 +39,11 @@ class ClipboardService : Service() {
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
ACTION_CLEAR -> {
|
ACTION_CLEAR -> {
|
||||||
clearClipboard()
|
clearClipboard()
|
||||||
stopForeground(true)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") stopForeground(true)
|
||||||
|
}
|
||||||
stopSelf()
|
stopSelf()
|
||||||
return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +59,11 @@ class ClipboardService : Service() {
|
||||||
withContext(Dispatchers.IO) { startTimer(time) }
|
withContext(Dispatchers.IO) { startTimer(time) }
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
clearClipboard()
|
clearClipboard()
|
||||||
stopForeground(true)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") stopForeground(true)
|
||||||
|
}
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import androidx.core.content.getSystemService
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.data.repo.PasswordRepository
|
import app.passwordstore.data.repo.PasswordRepository
|
||||||
|
import app.passwordstore.util.extensions.getParcelableExtraCompat
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
@ -29,7 +30,7 @@ class PasswordExportService : Service() {
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
ACTION_EXPORT_PASSWORD -> {
|
ACTION_EXPORT_PASSWORD -> {
|
||||||
val uri = intent.getParcelableExtra<Uri>("uri")
|
val uri = intent.getParcelableExtraCompat<Uri>("uri")
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
|
val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
<string name="git_commit_move_text">Benenne %1$s in %2$s um.</string>
|
<string name="git_commit_move_text">Benenne %1$s in %2$s um.</string>
|
||||||
<string name="git_commit_move_multiple_text">Verschiebe mehrere Passwörter nach %1$s.</string>
|
<string name="git_commit_move_multiple_text">Verschiebe mehrere Passwörter nach %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Passwort wurde in die Zwischenablage kopiert</string>
|
|
||||||
<string name="clipboard_copied_text">In die Zwischenablage kopiert</string>
|
<string name="clipboard_copied_text">In die Zwischenablage kopiert</string>
|
||||||
<string name="file_toast_text">Bitte setze einen Pfad</string>
|
<string name="file_toast_text">Bitte setze einen Pfad</string>
|
||||||
<string name="path_toast_text">Bitte setze einen Pfad</string>
|
<string name="path_toast_text">Bitte setze einen Pfad</string>
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
<string name="git_commit_move_text">Renommer %1$sà %2$s. </string>
|
<string name="git_commit_move_text">Renommer %1$sà %2$s. </string>
|
||||||
<string name="git_commit_move_multiple_text">Déplacement de mots de passe vers %1$s.</string>
|
<string name="git_commit_move_multiple_text">Déplacement de mots de passe vers %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Mot de passe copié dans le presse-papiers</string>
|
|
||||||
<string name="clipboard_copied_text">Copié dans le presse-papiers</string>
|
<string name="clipboard_copied_text">Copié dans le presse-papiers</string>
|
||||||
<string name="file_toast_text">Veuillez fournir un nom de fichier</string>
|
<string name="file_toast_text">Veuillez fournir un nom de fichier</string>
|
||||||
<string name="path_toast_text">Veuillez fournir un chemin d\'accès au fichier</string>
|
<string name="path_toast_text">Veuillez fournir un chemin d\'accès au fichier</string>
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
<string name="git_commit_move_text">Mudar nome %1$s a %2$s.</string>
|
<string name="git_commit_move_text">Mudar nome %1$s a %2$s.</string>
|
||||||
<string name="git_commit_move_multiple_text">Mover varios contrasinais a %1$s.</string>
|
<string name="git_commit_move_multiple_text">Mover varios contrasinais a %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Contrasinal copiado ao portapapeis, tes %d segundos para pegala nalgures.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Contrasinal copiado ao portapapeis</string>
|
|
||||||
<string name="clipboard_copied_text">Copiada ó portapapeis</string>
|
<string name="clipboard_copied_text">Copiada ó portapapeis</string>
|
||||||
<string name="file_toast_text">Debes proporcionar un nome de ficheiro</string>
|
<string name="file_toast_text">Debes proporcionar un nome de ficheiro</string>
|
||||||
<string name="path_toast_text">Por favor indica a ruta ao ficheiro</string>
|
<string name="path_toast_text">Por favor indica a ruta ao ficheiro</string>
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
<string name="git_commit_move_text">Rinomina %1$s in %2$s.</string>
|
<string name="git_commit_move_text">Rinomina %1$s in %2$s.</string>
|
||||||
<string name="git_commit_move_multiple_text">Sposta più password in %1$s.</string>
|
<string name="git_commit_move_multiple_text">Sposta più password in %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Password copiata negli appunti, hai %d secondi per incollarla da qualche parte.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Password copiata negli appunti</string>
|
|
||||||
<string name="clipboard_copied_text">Copiato negli appunti</string>
|
<string name="clipboard_copied_text">Copiato negli appunti</string>
|
||||||
<string name="file_toast_text">Sei pregato di fornire il nome di un file</string>
|
<string name="file_toast_text">Sei pregato di fornire il nome di un file</string>
|
||||||
<string name="path_toast_text">Sei pregato di fornire il percorso di un file</string>
|
<string name="path_toast_text">Sei pregato di fornire il percorso di un file</string>
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
<string name="git_commit_move_text">Renomear %1$s para %2$s.</string>
|
<string name="git_commit_move_text">Renomear %1$s para %2$s.</string>
|
||||||
<string name="git_commit_move_multiple_text">Mova múltiplas senhas para %1$s.</string>
|
<string name="git_commit_move_multiple_text">Mova múltiplas senhas para %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Senha copiada para área de transferência, você tem %d segundos para colá-la em algum lugar.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Senha copiada para área de transferência</string>
|
|
||||||
<string name="clipboard_copied_text">Copiado para a área de transferência</string>
|
<string name="clipboard_copied_text">Copiado para a área de transferência</string>
|
||||||
<string name="file_toast_text">Por favor, informe um nome de arquivo</string>
|
<string name="file_toast_text">Por favor, informe um nome de arquivo</string>
|
||||||
<string name="path_toast_text">Por favor, forneça o caminho do arquivo</string>
|
<string name="path_toast_text">Por favor, forneça o caminho do arquivo</string>
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
<string name="git_commit_move_text">Переименовать %1$sв%2$s.</string>
|
<string name="git_commit_move_text">Переименовать %1$sв%2$s.</string>
|
||||||
<string name="git_commit_move_multiple_text">Переместить несколько паролей в %1$s.</string>
|
<string name="git_commit_move_multiple_text">Переместить несколько паролей в %1$s.</string>
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Пароль скопирован в буфер обмена</string>
|
|
||||||
<string name="clipboard_copied_text">Скопировано в буфер обмена</string>
|
<string name="clipboard_copied_text">Скопировано в буфер обмена</string>
|
||||||
<string name="file_toast_text">Пожалуйста, укажите имя файла</string>
|
<string name="file_toast_text">Пожалуйста, укажите имя файла</string>
|
||||||
<string name="path_toast_text">Пожалуйста, задайте путь к файлу</string>
|
<string name="path_toast_text">Пожалуйста, задайте путь к файлу</string>
|
||||||
|
|
|
@ -45,8 +45,6 @@
|
||||||
<string name="git_commit_move_multiple_text">Move multiple passwords to %1$s.</string>
|
<string name="git_commit_move_multiple_text">Move multiple passwords to %1$s.</string>
|
||||||
|
|
||||||
<!-- PGPHandler -->
|
<!-- PGPHandler -->
|
||||||
<string name="clipboard_password_toast_text">Password copied to clipboard, you have %d seconds to paste it somewhere.</string>
|
|
||||||
<string name="clipboard_password_no_clear_toast_text">Password copied to clipboard</string>
|
|
||||||
<string name="clipboard_copied_text">Copied to clipboard</string>
|
<string name="clipboard_copied_text">Copied to clipboard</string>
|
||||||
<string name="file_toast_text">Please provide a file name</string>
|
<string name="file_toast_text">Please provide a file name</string>
|
||||||
<string name="path_toast_text">Please provide a file path</string>
|
<string name="path_toast_text">Please provide a file path</string>
|
||||||
|
|
|
@ -7,7 +7,9 @@ package com.github.androidpasswordstore.autofillparser
|
||||||
import android.app.assist.AssistStructure
|
import android.app.assist.AssistStructure
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageManager.ApplicationInfoFlags
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.autofill.AutofillId
|
import android.view.autofill.AutofillId
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
@ -41,7 +43,15 @@ public sealed class FormOrigin(public open val identifier: String) {
|
||||||
is Web -> identifier
|
is Web -> identifier
|
||||||
is App -> {
|
is App -> {
|
||||||
val info =
|
val info =
|
||||||
context.packageManager.getApplicationInfo(identifier, PackageManager.GET_META_DATA)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
context.packageManager.getApplicationInfo(
|
||||||
|
identifier,
|
||||||
|
ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
context.packageManager.getApplicationInfo(identifier, PackageManager.GET_META_DATA)
|
||||||
|
}
|
||||||
val label = context.packageManager.getApplicationLabel(info)
|
val label = context.packageManager.getApplicationLabel(info)
|
||||||
if (untrusted) "“$label”" else "$label"
|
if (untrusted) "“$label”" else "$label"
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,15 @@ public fun computeCertificatesHash(context: Context, appPackage: String): String
|
||||||
val stableHashOld = stableHash(signaturesOld.map { it.toByteArray() })
|
val stableHashOld = stableHash(signaturesOld.map { it.toByteArray() })
|
||||||
if (Build.VERSION.SDK_INT >= 28) {
|
if (Build.VERSION.SDK_INT >= 28) {
|
||||||
val info =
|
val info =
|
||||||
context.packageManager.getPackageInfo(appPackage, PackageManager.GET_SIGNING_CERTIFICATES)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
context.packageManager.getPackageInfo(
|
||||||
|
appPackage,
|
||||||
|
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
context.packageManager.getPackageInfo(appPackage, PackageManager.GET_SIGNING_CERTIFICATES)
|
||||||
|
}
|
||||||
val signaturesNew =
|
val signaturesNew =
|
||||||
info.signingInfo.signingCertificateHistory ?: info.signingInfo.apkContentsSigners
|
info.signingInfo.signingCertificateHistory ?: info.signingInfo.apkContentsSigners
|
||||||
val stableHashNew = stableHash(signaturesNew.map { it.toByteArray() })
|
val stableHashNew = stableHash(signaturesNew.map { it.toByteArray() })
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
package com.github.androidpasswordstore.autofillparser
|
package com.github.androidpasswordstore.autofillparser
|
||||||
|
|
||||||
import android.app.assist.AssistStructure
|
import android.app.assist.AssistStructure
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.service.autofill.Dataset
|
import android.service.autofill.Dataset
|
||||||
|
import android.service.autofill.Field
|
||||||
import android.view.autofill.AutofillId
|
import android.view.autofill.AutofillId
|
||||||
import android.view.autofill.AutofillValue
|
import android.view.autofill.AutofillValue
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
@ -54,17 +57,19 @@ public sealed class AutofillScenario<out T : Any> {
|
||||||
return try {
|
return try {
|
||||||
Builder<AutofillId>()
|
Builder<AutofillId>()
|
||||||
.apply {
|
.apply {
|
||||||
username = clientState.getParcelable(BUNDLE_KEY_USERNAME_ID)
|
username = clientState.getParcelableCompat(BUNDLE_KEY_USERNAME_ID)
|
||||||
fillUsername = clientState.getBoolean(BUNDLE_KEY_FILL_USERNAME)
|
fillUsername = clientState.getBoolean(BUNDLE_KEY_FILL_USERNAME)
|
||||||
otp = clientState.getParcelable(BUNDLE_KEY_OTP_ID)
|
otp = clientState.getParcelableCompat(BUNDLE_KEY_OTP_ID)
|
||||||
currentPassword.addAll(
|
currentPassword.addAll(
|
||||||
clientState.getParcelableArrayList(BUNDLE_KEY_CURRENT_PASSWORD_IDS) ?: emptyList()
|
clientState.getParcelableArrayListCompat(BUNDLE_KEY_CURRENT_PASSWORD_IDS)
|
||||||
|
?: emptyList()
|
||||||
)
|
)
|
||||||
newPassword.addAll(
|
newPassword.addAll(
|
||||||
clientState.getParcelableArrayList(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList()
|
clientState.getParcelableArrayListCompat(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList()
|
||||||
)
|
)
|
||||||
genericPassword.addAll(
|
genericPassword.addAll(
|
||||||
clientState.getParcelableArrayList(BUNDLE_KEY_GENERIC_PASSWORD_IDS) ?: emptyList()
|
clientState.getParcelableArrayListCompat(BUNDLE_KEY_GENERIC_PASSWORD_IDS)
|
||||||
|
?: emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
@ -73,6 +78,24 @@ public sealed class AutofillScenario<out T : Any> {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> Bundle.getParcelableCompat(key: String): T? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getParcelable(key, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getParcelable(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : Parcelable> Bundle.getParcelableArrayListCompat(
|
||||||
|
key: String
|
||||||
|
): ArrayList<T>? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
getParcelableArrayList(key, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") getParcelableArrayList(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Builder<T : Any> {
|
internal class Builder<T : Any> {
|
||||||
|
@ -231,7 +254,11 @@ public fun Dataset.Builder.fillWith(
|
||||||
scenario.otp -> credentialsToFill.otp
|
scenario.otp -> credentialsToFill.otp
|
||||||
else -> credentialsToFill.password
|
else -> credentialsToFill.password
|
||||||
}
|
}
|
||||||
setValue(field, AutofillValue.forText(value))
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
setField(field, Field.Builder().setValue(AutofillValue.forText(value)).build())
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") setValue(field, AutofillValue.forText(value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ package com.github.androidpasswordstore.autofillparser
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageManager.ResolveInfoFlags
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
@ -247,7 +248,15 @@ public fun getInstalledBrowsersWithAutofillSupportLevel(
|
||||||
): List<Pair<String, BrowserAutofillSupportLevel>> {
|
): List<Pair<String, BrowserAutofillSupportLevel>> {
|
||||||
val testWebIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://example.org") }
|
val testWebIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://example.org") }
|
||||||
val installedBrowsers =
|
val installedBrowsers =
|
||||||
context.packageManager.queryIntentActivities(testWebIntent, PackageManager.MATCH_ALL)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
context.packageManager.queryIntentActivities(
|
||||||
|
testWebIntent,
|
||||||
|
ResolveInfoFlags.of(PackageManager.MATCH_ALL.toLong())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
context.packageManager.queryIntentActivities(testWebIntent, PackageManager.MATCH_ALL)
|
||||||
|
}
|
||||||
return installedBrowsers
|
return installedBrowsers
|
||||||
.map { it to getBrowserAutofillSupportLevel(context, it.activityInfo.packageName) }
|
.map { it to getBrowserAutofillSupportLevel(context, it.activityInfo.packageName) }
|
||||||
.filter { it.first.isDefault || it.second != BrowserAutofillSupportLevel.None }
|
.filter { it.first.isDefault || it.second != BrowserAutofillSupportLevel.None }
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.gradle.kotlin.dsl.configure
|
||||||
object AndroidCommon {
|
object AndroidCommon {
|
||||||
fun configure(project: Project) {
|
fun configure(project: Project) {
|
||||||
project.extensions.configure<TestedExtension> {
|
project.extensions.configure<TestedExtension> {
|
||||||
setCompileSdkVersion(32)
|
setCompileSdkVersion(33)
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = 31
|
targetSdk = 31
|
||||||
|
|
|
@ -158,11 +158,11 @@ complexity:
|
||||||
TooManyFunctions:
|
TooManyFunctions:
|
||||||
active: true
|
active: true
|
||||||
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
||||||
thresholdInFiles: 11
|
thresholdInFiles: 15
|
||||||
thresholdInClasses: 11
|
thresholdInClasses: 15
|
||||||
thresholdInInterfaces: 11
|
thresholdInInterfaces: 15
|
||||||
thresholdInObjects: 11
|
thresholdInObjects: 15
|
||||||
thresholdInEnums: 11
|
thresholdInEnums: 15
|
||||||
ignoreDeprecated: false
|
ignoreDeprecated: false
|
||||||
ignorePrivate: false
|
ignorePrivate: false
|
||||||
ignoreOverridden: false
|
ignoreOverridden: false
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue