From ec696c1d8d2ad91ca2844a791ae38f68444bad81 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Fri, 12 May 2023 20:28:36 +0530 Subject: [PATCH] feat: raise min SDK to 26 Autofill is only available on API 26 and above and I do not want to deal with bugs on these older Android releases. --- CHANGELOG.md | 3 +- .../ic_launcher_foreground.xml | 0 .../ic_launcher.xml | 0 .../autofill/oreo/ui/AutofillSmsActivity.kt | 3 - .../java/app/passwordstore/Application.kt | 4 +- .../ui/autofill/AutofillDecryptActivity.kt | 2 - .../ui/autofill/AutofillFilterView.kt | 2 - .../AutofillPublisherChangedActivity.kt | 2 - .../ui/autofill/AutofillSaveActivity.kt | 3 - .../ui/crypto/BasePgpActivity.kt | 14 +-- .../ui/settings/AutofillSettings.kt | 6 -- .../ui/settings/GeneralSettings.kt | 7 +- .../passwordstore/ui/settings/MiscSettings.kt | 7 +- .../ui/settings/RepositorySettings.kt | 7 +- .../util/autofill/AutofillPreferences.kt | 3 - .../util/autofill/AutofillResponseBuilder.kt | 2 - .../util/extensions/AndroidExtensions.kt | 3 +- .../util/services/ClipboardService.kt | 90 ++++++------------- .../util/services/OreoAutofillService.kt | 2 - .../util/services/PasswordExportService.kt | 35 +++----- .../util/shortcuts/ShortcutHandler.kt | 6 -- .../ic_launcher_foreground.xml | 0 .../ic_launcher.xml | 0 .../autofill/oreo/ui/AutofillSmsActivity.kt | 2 - autofill-parser/build.gradle.kts | 7 +- .../app/passwordstore/gradle/AndroidCommon.kt | 13 +-- .../gradle/PublishedAndroidLibraryPlugin.kt | 4 +- 27 files changed, 63 insertions(+), 164 deletions(-) rename app/src/debug/res/{drawable-v24 => drawable}/ic_launcher_foreground.xml (100%) rename app/src/debug/res/{mipmap-anydpi-v26 => mipmap-anydpi}/ic_launcher.xml (100%) rename app/src/main/res/{drawable-v24 => drawable}/ic_launcher_foreground.xml (100%) rename app/src/main/res/{mipmap-anydpi-v26 => mipmap-anydpi}/ic_launcher.xml (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66fa6554..1e3936f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,8 @@ All notable changes to this project will be documented in this file. - **BREAKING**: The app's package name has been changed to `app.passwordstore` so users are aware that this is a new project with no compatibility guarantees with Password Store 1.x.y. - **BREAKING**: Introduce a new PGP backend powered by [PGPainless](https://github.com/pgpainless/pgpainless) which completely replaces OpenKeychain - **BREAKING**: Accessibility autofill has been removed completely due to being buggy, insecure and lacking in features. Upgrade to Android 8 or preferably later to gain access to our advanced Autofill implementation. -- **BREAKING***: Support for stores outside the hidden app directory has been removed due to technical restrictions, see [this issue](https://github.com/Android-Password-Store/Android-Password-Store/issues/1849) for details. +- **BREAKING**: Support for stores outside the hidden app directory has been removed due to technical restrictions, see [this issue](https://github.com/Android-Password-Store/Android-Password-Store/issues/1849) for details. +- **BREAKING**: The app's minimum supported Android version has been raised to Android Oreo (API level 26). - The settings UI has been completely re-done to dramatically improve discoverability and navigation for users - Using the `git://` protocol in the server URL now presents an explicit discouragement rather than a generic error - Encrypted data is no longer ASCII armored, bringing it in line with `pass` diff --git a/app/src/debug/res/drawable-v24/ic_launcher_foreground.xml b/app/src/debug/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from app/src/debug/res/drawable-v24/ic_launcher_foreground.xml rename to app/src/debug/res/drawable/ic_launcher_foreground.xml diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/debug/res/mipmap-anydpi/ic_launcher.xml similarity index 100% rename from app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml rename to app/src/debug/res/mipmap-anydpi/ic_launcher.xml diff --git a/app/src/free/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt b/app/src/free/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt index 71cd28a8..72274e58 100644 --- a/app/src/free/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt +++ b/app/src/free/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt @@ -6,11 +6,8 @@ package app.passwordstore.autofill.oreo.ui import android.content.Context import android.content.IntentSender -import android.os.Build -import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity -@RequiresApi(Build.VERSION_CODES.O) @Suppress("UNUSED_PARAMETER") class AutofillSmsActivity : AppCompatActivity() { diff --git a/app/src/main/java/app/passwordstore/Application.kt b/app/src/main/java/app/passwordstore/Application.kt index 6df4ef17..2f1aca88 100644 --- a/app/src/main/java/app/passwordstore/Application.kt +++ b/app/src/main/java/app/passwordstore/Application.kt @@ -96,9 +96,7 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere .detectLeakedRegistrationObjects() .detectLeakedSqlLiteObjects() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.detectContentUriWithoutPermission() - } + builder.detectContentUriWithoutPermission() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { builder.detectCredentialProtectedWhileLocked().detectImplicitDirectBoot() diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt index 10db9775..8dccacc3 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt @@ -11,7 +11,6 @@ import android.content.IntentSender import android.os.Build import android.os.Bundle import android.view.autofill.AutofillManager -import androidx.annotation.RequiresApi import androidx.lifecycle.lifecycleScope import app.passwordstore.data.crypto.GPGPassphraseCache import app.passwordstore.data.passfile.PasswordEntry @@ -41,7 +40,6 @@ import kotlinx.coroutines.withContext import logcat.LogPriority.ERROR import logcat.logcat -@RequiresApi(Build.VERSION_CODES.O) @AndroidEntryPoint class AutofillDecryptActivity : BasePgpActivity() { diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt index 3795f7e6..3a5e5d19 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt @@ -4,7 +4,6 @@ */ package app.passwordstore.ui.autofill -import android.annotation.TargetApi import android.app.PendingIntent import android.content.Context import android.content.Intent @@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.onEach import logcat.LogPriority.ERROR import logcat.logcat -@TargetApi(Build.VERSION_CODES.O) @AndroidEntryPoint class AutofillFilterView : AppCompatActivity() { 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 25075746..30347c0c 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt @@ -4,7 +4,6 @@ */ package app.passwordstore.ui.autofill -import android.annotation.TargetApi import android.app.PendingIntent import android.content.Context import android.content.Intent @@ -33,7 +32,6 @@ import com.github.michaelbull.result.runCatching import logcat.LogPriority.ERROR import logcat.logcat -@TargetApi(Build.VERSION_CODES.O) class AutofillPublisherChangedActivity : AppCompatActivity() { companion object { diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt index 801b9627..b0cfde5b 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt @@ -8,11 +8,9 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.IntentSender -import android.os.Build import android.os.Bundle import android.view.autofill.AutofillManager import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult -import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf import app.passwordstore.data.repo.PasswordRepository @@ -29,7 +27,6 @@ import java.io.File import logcat.LogPriority.ERROR import logcat.logcat -@RequiresApi(Build.VERSION_CODES.O) @AndroidEntryPoint class AutofillSaveActivity : AppCompatActivity() { 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 f171d3c5..fe59b4ff 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt @@ -57,7 +57,7 @@ open class BasePgpActivity : AppCompatActivity() { val name: String by unsafeLazy { File(fullPath).nameWithoutExtension } /** Action to invoke if [keyImportAction] succeeds. */ - var onKeyImport: (() -> Unit)? = null + private var onKeyImport: (() -> Unit)? = null private val keyImportAction = registerForActivityResult(StartActivityForResult()) { if (it.resultCode == RESULT_OK) { @@ -94,10 +94,8 @@ 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) } - } + clip.description.extras = + PersistableBundle().apply { putBoolean("android.content.extra.IS_SENSITIVE", true) } clipboard.setPrimaryClip(clip) if (showSnackbar && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { snackbar(message = resources.getString(snackbarTextRes)) @@ -144,11 +142,7 @@ open class BasePgpActivity : AppCompatActivity() { action = ClipboardService.ACTION_START putExtra(ClipboardService.EXTRA_NOTIFICATION_TIME, clearAfter) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(service) - } else { - startService(service) - } + startForegroundService(service) } } diff --git a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt index 403c342d..45d7d131 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt @@ -8,9 +8,7 @@ package app.passwordstore.ui.settings import android.annotation.SuppressLint import android.content.Intent import android.net.Uri -import android.os.Build import android.provider.Settings -import androidx.annotation.RequiresApi import androidx.appcompat.widget.AppCompatTextView import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Lifecycle @@ -35,11 +33,9 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide private val isAutofillServiceEnabled: Boolean get() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return false return activity.autofillManager?.hasEnabledAutofillServices() == true } - @RequiresApi(Build.VERSION_CODES.O) private fun showAutofillDialog(pref: SwitchPreference) { val observer = LifecycleEventObserver { _, event -> when (event) { @@ -95,10 +91,8 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide builder.apply { switch(PreferenceKeys.AUTOFILL_ENABLE) { titleRes = R.string.pref_autofill_enable_title - visible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O defaultValue = isAutofillServiceEnabled onClick { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return@onClick true if (isAutofillServiceEnabled) { activity.autofillManager?.disableAutofillServices() } else { diff --git a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt index a06a1dc8..7d2ecbf2 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt @@ -6,7 +6,6 @@ package app.passwordstore.ui.settings import android.content.pm.ShortcutManager -import android.os.Build import androidx.core.content.edit import androidx.core.content.getSystemService import androidx.fragment.app.FragmentActivity @@ -97,10 +96,8 @@ class GeneralSettings(private val activity: FragmentActivity) : SettingsProvider } } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - activity.getSystemService()?.apply { - removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList()) - } + activity.getSystemService()?.apply { + removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList()) } false } diff --git a/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt index 35f63e5b..837a21f6 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt @@ -8,7 +8,6 @@ package app.passwordstore.ui.settings import android.content.Context import android.content.Intent import android.net.Uri -import android.os.Build import androidx.activity.result.contract.ActivityResultContracts import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.FragmentActivity @@ -47,11 +46,7 @@ class MiscSettings(activity: FragmentActivity) : SettingsProvider { putExtra("uri", uri) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - activity.startForegroundService(service) - } else { - activity.startService(service) - } + activity.startForegroundService(service) } } diff --git a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt index d0c08439..d61a6b93 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt @@ -8,7 +8,6 @@ package app.passwordstore.ui.settings import android.content.Intent import android.content.SharedPreferences import android.content.pm.ShortcutManager -import android.os.Build import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.content.edit import androidx.core.content.getSystemService @@ -172,10 +171,8 @@ class RepositorySettings( } .onFailure { it.message?.let { message -> activity.snackbar(message = message) } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - activity.getSystemService()?.apply { - removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList()) - } + activity.getSystemService()?.apply { + removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList()) } activity.sharedPrefs.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) } dialogInterface.cancel() diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt index f9b07fa1..f1eb8835 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt @@ -5,8 +5,6 @@ package app.passwordstore.util.autofill import android.content.Context -import android.os.Build -import androidx.annotation.RequiresApi import app.passwordstore.data.passfile.PasswordEntry import app.passwordstore.util.extensions.getString import app.passwordstore.util.extensions.sharedPrefs @@ -101,7 +99,6 @@ enum class DirectoryStructure(val value: String) { ?: file.nameWithoutExtension } - @RequiresApi(Build.VERSION_CODES.O) fun getSaveFolderName(sanitizedIdentifier: String, username: String?) = when (this) { EncryptedUsername -> "/" 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 2b2154c0..050ded17 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt @@ -12,7 +12,6 @@ import android.service.autofill.Dataset import android.service.autofill.FillCallback import android.service.autofill.FillResponse import android.service.autofill.SaveInfo -import androidx.annotation.RequiresApi import app.passwordstore.autofill.oreo.ui.AutofillSmsActivity import app.passwordstore.ui.autofill.AutofillDecryptActivity import app.passwordstore.ui.autofill.AutofillFilterView @@ -32,7 +31,6 @@ import logcat.LogPriority.ERROR import logcat.asLog import logcat.logcat -@RequiresApi(Build.VERSION_CODES.O) class AutofillResponseBuilder @AssistedInject constructor( 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 f66fd33c..69a2d9db 100644 --- a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt +++ b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt @@ -21,7 +21,6 @@ import android.util.TypedValue import android.view.View import android.view.autofill.AutofillManager import androidx.activity.ComponentActivity -import androidx.annotation.RequiresApi import androidx.compose.ui.Modifier import androidx.core.content.ContextCompat import androidx.core.content.getSystemService @@ -39,7 +38,7 @@ import logcat.logcat /** Get an instance of [AutofillManager]. Only available on Android Oreo and above */ val Context.autofillManager: AutofillManager? - @RequiresApi(Build.VERSION_CODES.O) get() = getSystemService() + get() = getSystemService() /** Get an instance of [ClipboardManager] */ val Context.clipboard 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 e1771386..dccbd865 100644 --- a/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt +++ b/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt @@ -14,7 +14,6 @@ import android.content.ClipData import android.content.Intent import android.os.Build import android.os.IBinder -import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.content.getSystemService import app.passwordstore.R @@ -40,11 +39,7 @@ class ClipboardService : Service() { when (intent.action) { ACTION_CLEAR -> { clearClipboard() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - stopForeground(STOP_FOREGROUND_REMOVE) - } else { - @Suppress("DEPRECATION") stopForeground(true) - } + stopForeground(STOP_FOREGROUND_REMOVE) stopSelf() return super.onStartCommand(intent, flags, startId) } @@ -60,11 +55,7 @@ class ClipboardService : Service() { withContext(Dispatchers.IO) { startTimer(time) } withContext(Dispatchers.Main) { clearClipboard() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - stopForeground(STOP_FOREGROUND_REMOVE) - } else { - @Suppress("DEPRECATION") stopForeground(true) - } + stopForeground(STOP_FOREGROUND_REMOVE) stopSelf() } } @@ -122,52 +113,23 @@ class ClipboardService : Service() { val clearTimeMs = clearTime * 1000L val clearIntent = Intent(this, ClipboardService::class.java).apply { action = ACTION_CLEAR } val pendingIntent = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - PendingIntent.getForegroundService( - this, - 0, - clearIntent, - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - } else { - PendingIntent.FLAG_UPDATE_CURRENT - } - ) - } else { - PendingIntent.getService( - this, - 0, - clearIntent, - PendingIntent.FLAG_UPDATE_CURRENT, - ) - } - val notification = - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) { - createNotificationApi23(pendingIntent) - } else { - createNotificationApi24(pendingIntent, clearTimeMs) - } + PendingIntent.getForegroundService( + this, + 0, + clearIntent, + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + } else { + PendingIntent.FLAG_UPDATE_CURRENT + } + ) + val notification = createNotification(pendingIntent, clearTimeMs) createNotificationChannel() startForeground(1, notification) } - private fun createNotificationApi23(pendingIntent: PendingIntent): Notification { - return NotificationCompat.Builder(this, CHANNEL_ID) - .setContentTitle(getString(R.string.app_name)) - .setContentText(getString(R.string.tap_clear_clipboard)) - .setSmallIcon(R.drawable.ic_action_secure_24dp) - .setContentIntent(pendingIntent) - .setUsesChronometer(true) - .setPriority(NotificationCompat.PRIORITY_LOW) - .build() - } - - @RequiresApi(Build.VERSION_CODES.N) - private fun createNotificationApi24( - pendingIntent: PendingIntent, - clearTimeMs: Long - ): Notification { + private fun createNotification(pendingIntent: PendingIntent, clearTimeMs: Long): Notification { return NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle(getString(R.string.app_name)) .setContentText(getString(R.string.tap_clear_clipboard)) @@ -182,19 +144,17 @@ class ClipboardService : Service() { } private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val serviceChannel = - NotificationChannel( - CHANNEL_ID, - getString(R.string.app_name), - NotificationManager.IMPORTANCE_LOW - ) - val manager = getSystemService() - if (manager != null) { - manager.createNotificationChannel(serviceChannel) - } else { - logcat { "Failed to create notification channel" } - } + val serviceChannel = + NotificationChannel( + CHANNEL_ID, + getString(R.string.app_name), + NotificationManager.IMPORTANCE_LOW + ) + val manager = getSystemService() + if (manager != null) { + manager.createNotificationChannel(serviceChannel) + } else { + logcat { "Failed to create notification channel" } } } diff --git a/app/src/main/java/app/passwordstore/util/services/OreoAutofillService.kt b/app/src/main/java/app/passwordstore/util/services/OreoAutofillService.kt index fca44be2..60891367 100644 --- a/app/src/main/java/app/passwordstore/util/services/OreoAutofillService.kt +++ b/app/src/main/java/app/passwordstore/util/services/OreoAutofillService.kt @@ -13,7 +13,6 @@ import android.service.autofill.FillRequest import android.service.autofill.FillResponse import android.service.autofill.SaveCallback import android.service.autofill.SaveRequest -import androidx.annotation.RequiresApi import app.passwordstore.BuildConfig import app.passwordstore.R import app.passwordstore.ui.autofill.AutofillSaveActivity @@ -37,7 +36,6 @@ import javax.inject.Inject import logcat.LogPriority.ERROR import logcat.logcat -@RequiresApi(Build.VERSION_CODES.O) @AndroidEntryPoint class OreoAutofillService : AutofillService() { 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 ec1e654e..9243f52d 100644 --- a/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt +++ b/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt @@ -10,7 +10,6 @@ import android.app.NotificationManager import android.app.Service import android.content.Intent import android.net.Uri -import android.os.Build import android.os.IBinder import androidx.core.app.NotificationCompat import androidx.core.content.IntentCompat @@ -20,8 +19,6 @@ import app.passwordstore.R import app.passwordstore.data.repo.PasswordRepository import java.time.LocalDateTime import java.time.format.DateTimeFormatter -import java.util.Calendar -import java.util.TimeZone import logcat.logcat class PasswordExportService : Service() { @@ -65,13 +62,7 @@ class PasswordExportService : Service() { logcat { "Copying ${repositoryDirectory.path} to $targetDirectory" } - val dateString = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) - } else { - String.format("%tFT%= Build.VERSION_CODES.O) { - val serviceChannel = - NotificationChannel( - CHANNEL_ID, - getString(R.string.app_name), - NotificationManager.IMPORTANCE_LOW - ) - val manager = getSystemService() - if (manager != null) { - manager.createNotificationChannel(serviceChannel) - } else { - logcat { "Failed to create notification channel" } - } + val serviceChannel = + NotificationChannel( + CHANNEL_ID, + getString(R.string.app_name), + NotificationManager.IMPORTANCE_LOW + ) + val manager = getSystemService() + if (manager != null) { + manager.createNotificationChannel(serviceChannel) + } else { + logcat { "Failed to create notification channel" } } } diff --git a/app/src/main/java/app/passwordstore/util/shortcuts/ShortcutHandler.kt b/app/src/main/java/app/passwordstore/util/shortcuts/ShortcutHandler.kt index 6e58f446..86f38a8d 100644 --- a/app/src/main/java/app/passwordstore/util/shortcuts/ShortcutHandler.kt +++ b/app/src/main/java/app/passwordstore/util/shortcuts/ShortcutHandler.kt @@ -10,8 +10,6 @@ import android.content.Intent import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager import android.graphics.drawable.Icon -import android.os.Build -import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import app.passwordstore.R import app.passwordstore.data.password.PasswordItem @@ -42,7 +40,6 @@ constructor( * [MAX_SHORTCUT_COUNT] and older items are removed by a simple LRU sweep. */ fun addDynamicShortcut(item: PasswordItem, intent: Intent) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return val shortcutManager: ShortcutManager = context.getSystemService() ?: return val shortcut = buildShortcut(item, intent) val shortcuts = shortcutManager.dynamicShortcuts @@ -67,7 +64,6 @@ constructor( * a no-op if the user's default launcher does not support pinned shortcuts. */ fun addPinnedShortcut(item: PasswordItem, intent: Intent) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return val shortcutManager: ShortcutManager = context.getSystemService() ?: return if (!shortcutManager.isRequestPinShortcutSupported) { logcat { "addPinnedShortcut: pin shortcuts unsupported" } @@ -78,7 +74,6 @@ constructor( } /** Creates a [ShortcutInfo] from [item] and assigns [intent] to it. */ - @RequiresApi(Build.VERSION_CODES.N_MR1) private fun buildShortcut(item: PasswordItem, intent: Intent): ShortcutInfo { return ShortcutInfo.Builder(context, item.fullPathToParent) .setShortLabel(item.toString()) @@ -93,7 +88,6 @@ constructor( * data, which ensures that the get/set dance in [addDynamicShortcut] does not cause invalidation * of icon assets, resulting in invisible icons in all but the newest launcher shortcut. */ - @RequiresApi(Build.VERSION_CODES.N_MR1) private fun rebuildShortcut(shortcut: ShortcutInfo): ShortcutInfo { // Non-null assertions are fine since we know these values aren't null. return ShortcutInfo.Builder(context, shortcut.id) diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to app/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to app/src/main/res/mipmap-anydpi/ic_launcher.xml diff --git a/app/src/nonFree/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt b/app/src/nonFree/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt index c352f5d0..7641ad95 100644 --- a/app/src/nonFree/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt +++ b/app/src/nonFree/java/app/passwordstore/autofill/oreo/ui/AutofillSmsActivity.kt @@ -14,7 +14,6 @@ import android.content.IntentSender import android.os.Build import android.os.Bundle import android.view.autofill.AutofillManager -import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import app.passwordstore.databinding.ActivityOreoAutofillSmsBinding @@ -52,7 +51,6 @@ suspend fun Task.suspendableAwait() = } } -@RequiresApi(Build.VERSION_CODES.O) class AutofillSmsActivity : AppCompatActivity() { companion object { diff --git a/autofill-parser/build.gradle.kts b/autofill-parser/build.gradle.kts index fa67cf7e..5622e63d 100644 --- a/autofill-parser/build.gradle.kts +++ b/autofill-parser/build.gradle.kts @@ -2,6 +2,8 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception */ +@file:Suppress("UnstableApiUsage") + plugins { id("com.github.android-password-store.published-android-library") id("com.github.android-password-store.kotlin-android") @@ -9,7 +11,10 @@ plugins { } android { - defaultConfig { consumerProguardFiles("consumer-rules.pro") } + defaultConfig { + minSdk = 23 + consumerProguardFiles("consumer-rules.pro") + } sourceSets { getByName("test") { resources.srcDir("src/main/assets") } } namespace = "com.github.androidpasswordstore.autofillparser" } diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt index c337d9d5..53c93f6c 100644 --- a/build-logic/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt +++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt @@ -19,14 +19,8 @@ object AndroidCommon { project.extensions.configure { setCompileSdkVersion(33) defaultConfig { - minSdk = 23 - targetSdk = 31 - } - - sourceSets { - named("main") { java.srcDirs("src/main/kotlin") } - named("test") { java.srcDirs("src/test/kotlin") } - named("androidTest") { java.srcDirs("src/androidTest/kotlin") } + minSdk = 26 + targetSdk = 33 } packagingOptions { @@ -47,7 +41,8 @@ object AndroidCommon { animationsDisabled = true unitTests.isReturnDefaultValues = true } - project.tasks.withType { + + project.tasks.withType().configureEach { jvmArgs( "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.util=ALL-UNNAMED", diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/PublishedAndroidLibraryPlugin.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/PublishedAndroidLibraryPlugin.kt index 17ab5431..ac07df2d 100644 --- a/build-logic/src/main/kotlin/app/passwordstore/gradle/PublishedAndroidLibraryPlugin.kt +++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/PublishedAndroidLibraryPlugin.kt @@ -23,7 +23,9 @@ class PublishedAndroidLibraryPlugin : Plugin { } project.extensions.configure { publishToMavenCentral(SonatypeHost.DEFAULT, true) - signAllPublications() + if (project.providers.environmentVariable("CI").isPresent) { + signAllPublications() + } } project.extensions.configure { documentation.set(Documentation.PUBLIC)