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.
This commit is contained in:
parent
ee9d77eafd
commit
ec696c1d8d
27 changed files with 63 additions and 164 deletions
|
@ -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`
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<ShortcutManager>()?.apply {
|
||||
removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
|
||||
}
|
||||
activity.getSystemService<ShortcutManager>()?.apply {
|
||||
removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ShortcutManager>()?.apply {
|
||||
removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
|
||||
}
|
||||
activity.getSystemService<ShortcutManager>()?.apply {
|
||||
removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
|
||||
}
|
||||
activity.sharedPrefs.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) }
|
||||
dialogInterface.cancel()
|
||||
|
|
|
@ -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 -> "/"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<NotificationManager>()
|
||||
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<NotificationManager>()
|
||||
if (manager != null) {
|
||||
manager.createNotificationChannel(serviceChannel)
|
||||
} else {
|
||||
logcat { "Failed to create notification channel" }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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%<tRZ", Calendar.getInstance(TimeZone.getTimeZone("Z")))
|
||||
}
|
||||
|
||||
val dateString = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)
|
||||
val passDir = targetDirectory.createDirectory("password_store_$dateString")
|
||||
|
||||
if (passDir != null) {
|
||||
|
@ -136,19 +127,17 @@ class PasswordExportService : 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<NotificationManager>()
|
||||
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<NotificationManager>()
|
||||
if (manager != null) {
|
||||
manager.createNotificationChannel(serviceChannel)
|
||||
} else {
|
||||
logcat { "Failed to create notification channel" }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <T> Task<T>.suspendableAwait() =
|
|||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
class AutofillSmsActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -19,14 +19,8 @@ object AndroidCommon {
|
|||
project.extensions.configure<TestedExtension> {
|
||||
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<Test> {
|
||||
|
||||
project.tasks.withType<Test>().configureEach {
|
||||
jvmArgs(
|
||||
"--add-opens=java.base/java.lang=ALL-UNNAMED",
|
||||
"--add-opens=java.base/java.util=ALL-UNNAMED",
|
||||
|
|
|
@ -23,7 +23,9 @@ class PublishedAndroidLibraryPlugin : Plugin<Project> {
|
|||
}
|
||||
project.extensions.configure<MavenPublishBaseExtension> {
|
||||
publishToMavenCentral(SonatypeHost.DEFAULT, true)
|
||||
signAllPublications()
|
||||
if (project.providers.environmentVariable("CI").isPresent) {
|
||||
signAllPublications()
|
||||
}
|
||||
}
|
||||
project.extensions.configure<MetalavaExtension> {
|
||||
documentation.set(Documentation.PUBLIC)
|
||||
|
|
Loading…
Reference in a new issue