diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt index dd54b8eb..ac85a92a 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt @@ -22,6 +22,9 @@ import app.passwordstore.databinding.ActivityOreoAutofillPublisherChangedBinding import app.passwordstore.util.autofill.AutofillMatcher import app.passwordstore.util.autofill.AutofillPublisherChangedException 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 com.github.androidpasswordstore.autofillparser.FormOrigin import com.github.androidpasswordstore.autofillparser.computeCertificatesHash @@ -93,7 +96,8 @@ class AutofillPublisherChangedActivity : AppCompatActivity() { this@AutofillPublisherChangedActivity, FormOrigin.App(appPackage) ) - val fillResponse = intent.getParcelableExtra(EXTRA_FILL_RESPONSE_AFTER_RESET) + val fillResponse = + intent.getParcelableExtraCompat(EXTRA_FILL_RESPONSE_AFTER_RESET) setResult( RESULT_OK, Intent().apply { putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillResponse) } @@ -106,11 +110,13 @@ class AutofillPublisherChangedActivity : AppCompatActivity() { private fun showPackageInfo() { runCatching { 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) warningAppInstallDate.text = 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 = getString( R.string.oreo_autofill_warning_publisher_app_name, diff --git a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt index b6bb481f..fa85ffdd 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt @@ -10,6 +10,7 @@ import android.content.Intent import android.content.SharedPreferences import android.os.Build import android.os.Bundle +import android.os.PersistableBundle import android.view.WindowManager import androidx.annotation.CallSuper import androidx.annotation.StringRes @@ -68,8 +69,12 @@ open class BasePgpActivity : AppCompatActivity() { ) { val clipboard = clipboard ?: return 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) - if (showSnackbar) { + if (showSnackbar && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { snackbar(message = resources.getString(snackbarTextRes)) } } @@ -80,7 +85,7 @@ open class BasePgpActivity : AppCompatActivity() { * clearing the clipboard. */ fun copyPasswordToClipboard(password: String?) { - copyTextToClipboard(password, showSnackbar = false) + copyTextToClipboard(password) val clearAfter = settings.getString(PreferenceKeys.GENERAL_SHOW_TIME)?.toIntOrNull() ?: 45 @@ -95,9 +100,6 @@ open class BasePgpActivity : AppCompatActivity() { } else { 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)) } } diff --git a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt index 7b288ca6..3fb0d52f 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt @@ -78,7 +78,7 @@ class DecryptActivity : BasePgpActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - android.R.id.home -> onBackPressed() + android.R.id.home -> onBackPressedDispatcher.onBackPressed() R.id.edit_password -> editPassword() R.id.share_password_as_plaintext -> shareAsPlaintext() R.id.copy_password -> copyPasswordToClipboard(passwordEntry?.password) diff --git a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt index b8221a46..8fee21b4 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt @@ -262,7 +262,7 @@ class PasswordCreationActivity : BasePgpActivity() { when (item.itemId) { android.R.id.home -> { setResult(RESULT_CANCELED) - onBackPressed() + onBackPressedDispatcher.onBackPressed() } R.id.save_password -> { copy = false diff --git a/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt b/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt index 009267e2..9ab146fe 100644 --- a/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt @@ -49,7 +49,7 @@ class SelectFolderActivity : AppCompatActivity(R.layout.select_folder_layout) { when (item.itemId) { android.R.id.home -> { setResult(RESULT_CANCELED) - onBackPressed() + onBackPressedDispatcher.onBackPressed() } R.id.crypto_select -> selectFolder() else -> return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt b/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt index 2b5ecae5..5b9a04be 100644 --- a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt @@ -69,7 +69,7 @@ class GitConfigActivity : BaseGitActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - onBackPressed() + onBackPressedDispatcher.onBackPressed() true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt b/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt index a7ecd697..a07b409f 100644 --- a/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt @@ -202,7 +202,7 @@ class GitServerConfigActivity : BaseGitActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - onBackPressed() + onBackPressedDispatcher.onBackPressed() true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt b/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt index 2fe92098..f5257530 100644 --- a/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt @@ -6,6 +6,7 @@ package app.passwordstore.ui.onboarding.activity import android.os.Bundle +import androidx.activity.addCallback import androidx.appcompat.app.AppCompatActivity import app.passwordstore.R @@ -14,13 +15,11 @@ class OnboardingActivity : AppCompatActivity(R.layout.activity_onboarding) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) supportActionBar?.hide() - } - - override fun onBackPressed() { - if (supportFragmentManager.backStackEntryCount == 0) { - finishAffinity() - } else { - super.onBackPressed() + val callback = onBackPressedDispatcher.addCallback(enabled = false) { finishAffinity() } + supportFragmentManager.addOnBackStackChangedListener { + if (supportFragmentManager.backStackEntryCount == 0) { + callback.isEnabled = true + } } } } diff --git a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt index 0078f08e..c97782b0 100644 --- a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt +++ b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt @@ -4,7 +4,6 @@ */ package app.passwordstore.ui.passwords -import android.annotation.SuppressLint import android.content.ComponentName import android.content.Context import android.content.Intent @@ -14,7 +13,6 @@ import android.view.Menu import android.view.MenuItem import android.view.MenuItem.OnActionExpandListener import android.view.WindowManager -import androidx.activity.result.contract.ActivityResultContracts.RequestPermission import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.activity.viewModels import androidx.appcompat.widget.SearchView @@ -77,18 +75,6 @@ class PasswordStore : BaseGitActivity() { 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 = registerForActivityResult(StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -196,7 +182,6 @@ class PasswordStore : BaseGitActivity() { return super.onKeyDown(keyCode, event) } - @SuppressLint("NewApi") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_pwdstore) @@ -313,12 +298,14 @@ class PasswordStore : BaseGitActivity() { } } R.id.refresh -> refreshPasswordList() - android.R.id.home -> onBackPressed() + android.R.id.home -> onBackPressedDispatcher.onBackPressed() else -> return super.onOptionsItemSelected(item) } return true } + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") override fun onBackPressed() { if (getPasswordFragment()?.onBackPressedInActivity() != true) super.onBackPressed() } diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt index 7fc20d5d..e4a9de8c 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt @@ -10,6 +10,7 @@ import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import app.passwordstore.R import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding +import app.passwordstore.util.extensions.getParcelableCompat import app.passwordstore.util.extensions.viewBinding import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.Maxr1998.modernpreferences.Preference @@ -84,7 +85,7 @@ class SettingsActivity : AppCompatActivity() { } } savedInstanceState - ?.getParcelable("adapter") + ?.getParcelableCompat("adapter") ?.let(adapter::loadSavedState) binding.preferenceRecyclerView.adapter = adapter } @@ -106,6 +107,8 @@ class SettingsActivity : AppCompatActivity() { } } + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") override fun onBackPressed() { if (!preferencesAdapter.goBack()) super.onBackPressed() } diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt index 8a3d3edf..67528d24 100644 --- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt @@ -103,7 +103,7 @@ class SshKeyGenActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - onBackPressed() + onBackPressedDispatcher.onBackPressed() true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt b/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt index f46d3c1a..997e27b4 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt @@ -7,9 +7,11 @@ package app.passwordstore.util.autofill import android.content.Context import android.content.IntentSender +import android.os.Build import android.service.autofill.Dataset import android.service.autofill.FillCallback import android.service.autofill.FillResponse +import android.service.autofill.Presentations import android.service.autofill.SaveInfo import android.view.inputmethod.InlineSuggestionsRequest import android.widget.inline.InlinePresentationSpec @@ -60,6 +62,23 @@ constructor( intentSender: IntentSender, metadata: DatasetMetadata, 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 { return Dataset.Builder(makeRemoteView(context, metadata)).run { 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( context: Context, file: File, diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt index 94a4a564..a198297c 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt @@ -54,6 +54,7 @@ constructor( private val scenarioSupportsSave = scenario.hasPasswordFieldsToSave private val canBeSaved = saveFlags != null && scenarioSupportsSave + @Suppress("DEPRECATION") private fun makeIntentDataset( context: Context, action: AutofillAction, @@ -212,7 +213,7 @@ constructor( if (Build.VERSION.SDK_INT >= 28) { Dataset.Builder() } else { - Dataset.Builder(makeRemoteView(context, makeEmptyMetadata())) + @Suppress("DEPRECATION") Dataset.Builder(makeRemoteView(context, makeEmptyMetadata())) } return builder.run { if (scenario != null) fillWith(scenario, action, credentials) diff --git a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt index ebb24a78..948d3827 100644 --- a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt +++ b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt @@ -10,7 +10,14 @@ import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.content.SharedPreferences +import android.content.pm.ApplicationInfo +import android.content.pm.PackageInfo 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.TypedValue import android.view.View @@ -132,3 +139,45 @@ fun SharedPreferences.getString(key: String): String? = getString(key, null) fun String.base64(): String { return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP) } + +inline fun 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 Bundle.getParcelableArrayListCompat( + key: String +): ArrayList? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + getParcelableArrayList(key, T::class.java) + } else { + @Suppress("DEPRECATION") getParcelableArrayList(key) + } +} + +inline fun 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) + } +} diff --git a/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt b/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt index 3d57e29b..c56c319b 100644 --- a/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt +++ b/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt @@ -39,7 +39,11 @@ class ClipboardService : Service() { when (intent.action) { ACTION_CLEAR -> { clearClipboard() - stopForeground(true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + stopForeground(STOP_FOREGROUND_REMOVE) + } else { + @Suppress("DEPRECATION") stopForeground(true) + } stopSelf() return super.onStartCommand(intent, flags, startId) } @@ -55,7 +59,11 @@ class ClipboardService : Service() { withContext(Dispatchers.IO) { startTimer(time) } withContext(Dispatchers.Main) { clearClipboard() - stopForeground(true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + stopForeground(STOP_FOREGROUND_REMOVE) + } else { + @Suppress("DEPRECATION") stopForeground(true) + } stopSelf() } } diff --git a/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt b/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt index 536006f6..4d587621 100644 --- a/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt +++ b/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt @@ -17,6 +17,7 @@ import androidx.core.content.getSystemService import androidx.documentfile.provider.DocumentFile import app.passwordstore.R import app.passwordstore.data.repo.PasswordRepository +import app.passwordstore.util.extensions.getParcelableExtraCompat import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.Calendar @@ -29,7 +30,7 @@ class PasswordExportService : Service() { if (intent != null) { when (intent.action) { ACTION_EXPORT_PASSWORD -> { - val uri = intent.getParcelableExtra("uri") + val uri = intent.getParcelableExtraCompat("uri") if (uri != null) { val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index bb54499a..885293f7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -33,8 +33,6 @@ Benenne %1$s in %2$s um. Verschiebe mehrere Passwörter nach %1$s. - Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen. - Passwort wurde in die Zwischenablage kopiert In die Zwischenablage kopiert Bitte setze einen Pfad Bitte setze einen Pfad diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 711e91ed..ae0f27da 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -37,8 +37,6 @@ Renommer %1$sà %2$s. Déplacement de mots de passe vers %1$s. - Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci. - Mot de passe copié dans le presse-papiers Copié dans le presse-papiers Veuillez fournir un nom de fichier Veuillez fournir un chemin d\'accès au fichier diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index c2974b1c..2341f6b0 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -37,8 +37,6 @@ Mudar nome %1$s a %2$s. Mover varios contrasinais a %1$s. - Contrasinal copiado ao portapapeis, tes %d segundos para pegala nalgures. - Contrasinal copiado ao portapapeis Copiada ó portapapeis Debes proporcionar un nome de ficheiro Por favor indica a ruta ao ficheiro diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 1b994b28..ee70dd4f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -37,8 +37,6 @@ Rinomina %1$s in %2$s. Sposta più password in %1$s. - Password copiata negli appunti, hai %d secondi per incollarla da qualche parte. - Password copiata negli appunti Copiato negli appunti Sei pregato di fornire il nome di un file Sei pregato di fornire il percorso di un file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index bd3290bb..847a89cd 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -37,8 +37,6 @@ Renomear %1$s para %2$s. Mova múltiplas senhas para %1$s. - Senha copiada para área de transferência, você tem %d segundos para colá-la em algum lugar. - Senha copiada para área de transferência Copiado para a área de transferência Por favor, informe um nome de arquivo Por favor, forneça o caminho do arquivo diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5119ed4d..54f2669f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -41,8 +41,6 @@ Переименовать %1$sв%2$s. Переместить несколько паролей в %1$s. - Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его. - Пароль скопирован в буфер обмена Скопировано в буфер обмена Пожалуйста, укажите имя файла Пожалуйста, задайте путь к файлу diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 66e9374d..d2c9ab06 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,8 +45,6 @@ Move multiple passwords to %1$s. - Password copied to clipboard, you have %d seconds to paste it somewhere. - Password copied to clipboard Copied to clipboard Please provide a file name Please provide a file path diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt index 78af009d..952bc3f0 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt @@ -7,7 +7,9 @@ package com.github.androidpasswordstore.autofillparser import android.app.assist.AssistStructure import android.content.Context import android.content.pm.PackageManager +import android.content.pm.PackageManager.ApplicationInfoFlags import android.net.Uri +import android.os.Build import android.os.Bundle import android.view.autofill.AutofillId import androidx.annotation.RequiresApi @@ -41,7 +43,15 @@ public sealed class FormOrigin(public open val identifier: String) { is Web -> identifier is App -> { 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) if (untrusted) "“$label”" else "$label" } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt index 5874bf77..7e5a3d33 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt @@ -54,7 +54,15 @@ public fun computeCertificatesHash(context: Context, appPackage: String): String val stableHashOld = stableHash(signaturesOld.map { it.toByteArray() }) if (Build.VERSION.SDK_INT >= 28) { 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 = info.signingInfo.signingCertificateHistory ?: info.signingInfo.apkContentsSigners val stableHashNew = stableHash(signaturesNew.map { it.toByteArray() }) diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt index 7476f56c..d2a95b40 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt @@ -5,8 +5,11 @@ package com.github.androidpasswordstore.autofillparser import android.app.assist.AssistStructure +import android.os.Build import android.os.Bundle +import android.os.Parcelable import android.service.autofill.Dataset +import android.service.autofill.Field import android.view.autofill.AutofillId import android.view.autofill.AutofillValue import androidx.annotation.RequiresApi @@ -54,17 +57,19 @@ public sealed class AutofillScenario { return try { Builder() .apply { - username = clientState.getParcelable(BUNDLE_KEY_USERNAME_ID) + username = clientState.getParcelableCompat(BUNDLE_KEY_USERNAME_ID) fillUsername = clientState.getBoolean(BUNDLE_KEY_FILL_USERNAME) - otp = clientState.getParcelable(BUNDLE_KEY_OTP_ID) + otp = clientState.getParcelableCompat(BUNDLE_KEY_OTP_ID) currentPassword.addAll( - clientState.getParcelableArrayList(BUNDLE_KEY_CURRENT_PASSWORD_IDS) ?: emptyList() + clientState.getParcelableArrayListCompat(BUNDLE_KEY_CURRENT_PASSWORD_IDS) + ?: emptyList() ) newPassword.addAll( - clientState.getParcelableArrayList(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList() + clientState.getParcelableArrayListCompat(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList() ) genericPassword.addAll( - clientState.getParcelableArrayList(BUNDLE_KEY_GENERIC_PASSWORD_IDS) ?: emptyList() + clientState.getParcelableArrayListCompat(BUNDLE_KEY_GENERIC_PASSWORD_IDS) + ?: emptyList() ) } .build() @@ -73,6 +78,24 @@ public sealed class AutofillScenario { null } } + + private inline fun 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 Bundle.getParcelableArrayListCompat( + key: String + ): ArrayList? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + getParcelableArrayList(key, T::class.java) + } else { + @Suppress("DEPRECATION") getParcelableArrayList(key) + } + } } internal class Builder { @@ -231,7 +254,11 @@ public fun Dataset.Builder.fillWith( scenario.otp -> credentialsToFill.otp 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)) + } } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt index 58f400ef..7c4d0c2e 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt @@ -7,6 +7,7 @@ package com.github.androidpasswordstore.autofillparser import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.content.pm.PackageManager.ResolveInfoFlags import android.net.Uri import android.os.Build import android.provider.Settings @@ -247,7 +248,15 @@ public fun getInstalledBrowsersWithAutofillSupportLevel( ): List> { val testWebIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://example.org") } 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 .map { it to getBrowserAutofillSupportLevel(context, it.activityInfo.packageName) } .filter { it.first.isDefault || it.second != BrowserAutofillSupportLevel.None } diff --git a/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt b/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt index b90666c9..52357171 100644 --- a/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt +++ b/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt @@ -10,7 +10,7 @@ import org.gradle.kotlin.dsl.configure object AndroidCommon { fun configure(project: Project) { project.extensions.configure { - setCompileSdkVersion(32) + setCompileSdkVersion(33) defaultConfig { minSdk = 23 targetSdk = 31 diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 69a60690..78d50515 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -158,11 +158,11 @@ complexity: TooManyFunctions: active: true excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - thresholdInFiles: 11 - thresholdInClasses: 11 - thresholdInInterfaces: 11 - thresholdInObjects: 11 - thresholdInEnums: 11 + thresholdInFiles: 15 + thresholdInClasses: 15 + thresholdInInterfaces: 15 + thresholdInObjects: 15 + thresholdInEnums: 15 ignoreDeprecated: false ignorePrivate: false ignoreOverridden: false