mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Upgrade Foreground service and version to 4.1.0
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
KeePassDX(4.1.0)
|
||||||
|
* Upgrade to API 34 (Android 14)
|
||||||
|
|
||||||
KeePassDX(4.0.8)
|
KeePassDX(4.0.8)
|
||||||
* Fix graphical bug that prevented databases from being opened on some versions of Android #1848 #1850
|
* Fix graphical bug that prevented databases from being opened on some versions of Android #1848 #1850
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ apply plugin: 'kotlin-kapt'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'com.kunzisoft.keepass'
|
namespace 'com.kunzisoft.keepass'
|
||||||
compileSdkVersion 33
|
compileSdkVersion 34
|
||||||
buildToolsVersion "33.0.2"
|
buildToolsVersion "33.0.2"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.kunzisoft.keepass"
|
applicationId "com.kunzisoft.keepass"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 33
|
targetSdkVersion 34
|
||||||
versionCode = 131
|
versionCode = 132
|
||||||
versionName = "4.0.8"
|
versionName = "4.1.0"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
android:anyDensity="true" />
|
android:anyDensity="true" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.FOREGROUND_SERVICE" />
|
android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.POST_NOTIFICATIONS" />
|
android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
@@ -197,18 +201,27 @@
|
|||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="com.kunzisoft.keepass.services.DatabaseTaskNotificationService"
|
android:name="com.kunzisoft.keepass.services.DatabaseTaskNotificationService"
|
||||||
|
android:foregroundServiceType="dataSync"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name="com.kunzisoft.keepass.services.AttachmentFileNotificationService"
|
android:name="com.kunzisoft.keepass.services.AttachmentFileNotificationService"
|
||||||
|
android:foregroundServiceType="dataSync"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name="com.kunzisoft.keepass.services.ClipboardEntryNotificationService"
|
android:name="com.kunzisoft.keepass.services.ClipboardEntryNotificationService"
|
||||||
|
android:foregroundServiceType="specialUse"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false" />
|
||||||
|
<service
|
||||||
|
android:name="com.kunzisoft.keepass.services.KeyboardEntryNotificationService"
|
||||||
|
android:foregroundServiceType="specialUse"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name="com.kunzisoft.keepass.services.AdvancedUnlockNotificationService"
|
android:name="com.kunzisoft.keepass.services.AdvancedUnlockNotificationService"
|
||||||
|
android:foregroundServiceType="specialUse"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<!-- Receiver for Autofill -->
|
<!-- Receiver for Autofill -->
|
||||||
@@ -235,10 +248,6 @@
|
|||||||
<action android:name="android.view.InputMethod" />
|
<action android:name="android.view.InputMethod" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
<service
|
|
||||||
android:name="com.kunzisoft.keepass.services.KeyboardEntryNotificationService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false" />
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.kunzisoft.keepass.receivers.DexModeReceiver"
|
android:name="com.kunzisoft.keepass.receivers.DexModeReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|||||||
@@ -86,11 +86,19 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
||||||
// Not necessarily a foreground service
|
// Not necessarily a foreground service
|
||||||
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
||||||
defineTimerJob(notificationBuilder, notificationTimeoutMilliSecs) {
|
defineTimerJob(
|
||||||
|
notificationBuilder,
|
||||||
|
NotificationServiceType.ADVANCED_UNLOCK,
|
||||||
|
notificationTimeoutMilliSecs
|
||||||
|
) {
|
||||||
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startForeground(notificationId, notificationBuilder.build())
|
startForegroundCompat(
|
||||||
|
notificationId,
|
||||||
|
notificationBuilder,
|
||||||
|
NotificationServiceType.ADVANCED_UNLOCK
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mActionTaskBinder
|
return mActionTaskBinder
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ import com.kunzisoft.keepass.model.AttachmentState
|
|||||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||||
import com.kunzisoft.keepass.model.StreamDirection
|
import com.kunzisoft.keepass.model.StreamDirection
|
||||||
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
||||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
|
||||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||||
|
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.LinkedList
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|
||||||
|
|
||||||
@@ -282,15 +282,21 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
|||||||
AttachmentState.ERROR -> {
|
AttachmentState.ERROR -> {
|
||||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||||
try {
|
try {
|
||||||
notificationManager?.notify(
|
checkNotificationsPermission(this) {
|
||||||
attachmentNotification.notificationId,
|
notificationManager?.notify(
|
||||||
builder.build()
|
attachmentNotification.notificationId,
|
||||||
)
|
builder.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
Log.e(TAG, "Unable to notify the attachment state", e)
|
Log.e(TAG, "Unable to notify the attachment state", e)
|
||||||
}
|
}
|
||||||
} else -> {
|
} else -> {
|
||||||
startForeground(attachmentNotification.notificationId, builder.build())
|
startForegroundCompat(
|
||||||
|
attachmentNotification.notificationId,
|
||||||
|
builder,
|
||||||
|
NotificationServiceType.ATTACHMENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.services
|
package com.kunzisoft.keepass.services
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.model.EntryInfo
|
import com.kunzisoft.keepass.model.EntryInfo
|
||||||
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||||
@@ -196,23 +192,29 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
|||||||
//Get settings
|
//Get settings
|
||||||
val notificationTimeoutMilliSecs = PreferencesUtil.getClipboardTimeout(this)
|
val notificationTimeoutMilliSecs = PreferencesUtil.getClipboardTimeout(this)
|
||||||
if (notificationTimeoutMilliSecs != NEVER) {
|
if (notificationTimeoutMilliSecs != NEVER) {
|
||||||
defineTimerJob(builder, notificationTimeoutMilliSecs, {
|
defineTimerJob(
|
||||||
val newGeneratedValue = fieldToCopy.getGeneratedValue(mEntryInfo)
|
builder,
|
||||||
// New auto generated value
|
NotificationServiceType.CLIPBOARD,
|
||||||
if (generatedValue != newGeneratedValue) {
|
notificationTimeoutMilliSecs,
|
||||||
generatedValue = newGeneratedValue
|
{
|
||||||
clipboardHelper?.copyToClipboard(
|
val newGeneratedValue = fieldToCopy.getGeneratedValue(mEntryInfo)
|
||||||
fieldToCopy.label,
|
// New auto generated value
|
||||||
generatedValue,
|
if (generatedValue != newGeneratedValue) {
|
||||||
fieldToCopy.isSensitive
|
generatedValue = newGeneratedValue
|
||||||
)
|
clipboardHelper?.copyToClipboard(
|
||||||
|
fieldToCopy.label,
|
||||||
|
generatedValue,
|
||||||
|
fieldToCopy.isSensitive
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stopNotificationAndSendLockIfNeeded()
|
||||||
|
// Clean password only if no next field
|
||||||
|
if (nextFields.size <= 0)
|
||||||
|
clipboardHelper?.cleanClipboard()
|
||||||
}
|
}
|
||||||
}) {
|
)
|
||||||
stopNotificationAndSendLockIfNeeded()
|
|
||||||
// Clean password only if no next field
|
|
||||||
if (nextFields.size <= 0)
|
|
||||||
clipboardHelper?.cleanClipboard()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// No timer
|
// No timer
|
||||||
checkNotificationsPermission {
|
checkNotificationsPermission {
|
||||||
@@ -226,12 +228,11 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkNotificationsPermission(action: () -> Unit) {
|
private fun checkNotificationsPermission(action: () -> Unit) {
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
|
checkNotificationsPermission(
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
this,
|
||||||
action.invoke()
|
PreferencesUtil.isClipboardNotificationsEnable(this),
|
||||||
} else {
|
action
|
||||||
showPermissionErrorIfNeeded(this)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
@@ -255,26 +256,14 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
|||||||
const val EXTRA_CLIPBOARD_FIELDS = "EXTRA_CLIPBOARD_FIELDS"
|
const val EXTRA_CLIPBOARD_FIELDS = "EXTRA_CLIPBOARD_FIELDS"
|
||||||
const val ACTION_CLEAN_CLIPBOARD = "ACTION_CLEAN_CLIPBOARD"
|
const val ACTION_CLEAN_CLIPBOARD = "ACTION_CLEAN_CLIPBOARD"
|
||||||
|
|
||||||
private fun showPermissionErrorIfNeeded(context: Context) {
|
|
||||||
if (PreferencesUtil.isClipboardNotificationsEnable(context)) {
|
|
||||||
Toast.makeText(context, R.string.warning_copy_permission, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkAndLaunchNotification(
|
fun checkAndLaunchNotification(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
entry: EntryInfo
|
entry: EntryInfo
|
||||||
) {
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
checkNotificationsPermission(
|
||||||
if (ContextCompat.checkSelfPermission(
|
activity,
|
||||||
activity,
|
PreferencesUtil.isClipboardNotificationsEnable(activity)
|
||||||
Manifest.permission.POST_NOTIFICATIONS
|
) {
|
||||||
) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
launchNotificationIfAllowed(activity, entry)
|
|
||||||
} else {
|
|
||||||
showPermissionErrorIfNeeded(activity)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
launchNotificationIfAllowed(activity, entry)
|
launchNotificationIfAllowed(activity, entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -591,7 +591,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the notification
|
// Create the notification
|
||||||
startForeground(notificationId, notificationBuilder.build())
|
startForegroundCompat(
|
||||||
|
notificationId,
|
||||||
|
notificationBuilder,
|
||||||
|
NotificationServiceType.DATABASE_TASK
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeIntentData(intent: Intent?) {
|
private fun removeIntentData(intent: Intent?) {
|
||||||
|
|||||||
@@ -111,13 +111,18 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
|||||||
.setContentIntent(null)
|
.setContentIntent(null)
|
||||||
.setDeleteIntent(pendingDeleteIntent)
|
.setDeleteIntent(pendingDeleteIntent)
|
||||||
|
|
||||||
notificationManager?.cancel(notificationId)
|
checkNotificationsPermission(this, PreferencesUtil.isKeyboardNotificationEntryEnable(this)) {
|
||||||
notificationManager?.notify(notificationId, builder.build())
|
notificationManager?.notify(notificationId, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
// Timeout only if notification clear is available
|
// Timeout only if notification clear is available
|
||||||
if (PreferencesUtil.isClearKeyboardNotificationEnable(this)) {
|
if (PreferencesUtil.isClearKeyboardNotificationEnable(this)) {
|
||||||
if (mNotificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
if (mNotificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
||||||
defineTimerJob(builder, mNotificationTimeoutMilliSecs) {
|
defineTimerJob(
|
||||||
|
builder,
|
||||||
|
NotificationServiceType.KEYBOARD,
|
||||||
|
mNotificationTimeoutMilliSecs
|
||||||
|
) {
|
||||||
stopNotificationAndSendLockIfNeeded()
|
stopNotificationAndSendLockIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
package com.kunzisoft.keepass.services
|
package com.kunzisoft.keepass.services
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||||
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
|
||||||
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.stylish.Stylish
|
import com.kunzisoft.keepass.activities.stylish.Stylish
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
abstract class NotificationService : Service() {
|
abstract class NotificationService : Service() {
|
||||||
@@ -74,7 +87,32 @@ abstract class NotificationService : Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun startForegroundCompat(notificationId: Int,
|
||||||
|
builder: NotificationCompat.Builder,
|
||||||
|
type: NotificationServiceType
|
||||||
|
) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
val foregroundServiceTimer = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
|
FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||||
|
} else {
|
||||||
|
FOREGROUND_SERVICE_TYPE_NONE
|
||||||
|
}
|
||||||
|
val foregroundType = when (type) {
|
||||||
|
NotificationServiceType.DATABASE_TASK -> FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||||
|
NotificationServiceType.ATTACHMENT -> FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||||
|
NotificationServiceType.CLIPBOARD -> foregroundServiceTimer
|
||||||
|
NotificationServiceType.KEYBOARD -> foregroundServiceTimer
|
||||||
|
NotificationServiceType.ADVANCED_UNLOCK -> foregroundServiceTimer
|
||||||
|
}
|
||||||
|
startForeground(notificationId, builder.build(), foregroundType)
|
||||||
|
} else {
|
||||||
|
startForeground(notificationId, builder.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun defineTimerJob(builder: NotificationCompat.Builder,
|
protected fun defineTimerJob(builder: NotificationCompat.Builder,
|
||||||
|
type: NotificationServiceType,
|
||||||
timeoutMilliseconds: Long,
|
timeoutMilliseconds: Long,
|
||||||
actionAfterASecond: (() -> Unit)? = null,
|
actionAfterASecond: (() -> Unit)? = null,
|
||||||
actionEnd: () -> Unit) {
|
actionEnd: () -> Unit) {
|
||||||
@@ -87,7 +125,7 @@ abstract class NotificationService : Service() {
|
|||||||
builder.setProgress(100,
|
builder.setProgress(100,
|
||||||
(currentTime * 100 / timeoutInSeconds).toInt(),
|
(currentTime * 100 / timeoutInSeconds).toInt(),
|
||||||
false)
|
false)
|
||||||
startForeground(notificationId, builder.build())
|
startForegroundCompat(notificationId, builder, type)
|
||||||
delay(1000)
|
delay(1000)
|
||||||
if (currentTime <= 0) {
|
if (currentTime <= 0) {
|
||||||
actionEnd()
|
actionEnd()
|
||||||
@@ -114,5 +152,25 @@ abstract class NotificationService : Service() {
|
|||||||
companion object {
|
companion object {
|
||||||
private const val CHANNEL_ID = "com.kunzisoft.keepass.notification.channel"
|
private const val CHANNEL_ID = "com.kunzisoft.keepass.notification.channel"
|
||||||
private const val CHANNEL_NAME = "KeePassDX notification"
|
private const val CHANNEL_NAME = "KeePassDX notification"
|
||||||
|
|
||||||
|
fun checkNotificationsPermission(
|
||||||
|
context: Context,
|
||||||
|
showError: Boolean = true,
|
||||||
|
action: () -> Unit
|
||||||
|
) {
|
||||||
|
if (ContextCompat.checkSelfPermission(context,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
|
action.invoke()
|
||||||
|
} else {
|
||||||
|
if (showError) {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.warning_copy_permission,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.kunzisoft.keepass.services
|
||||||
|
|
||||||
|
enum class NotificationServiceType {
|
||||||
|
DATABASE_TASK,
|
||||||
|
ATTACHMENT,
|
||||||
|
CLIPBOARD,
|
||||||
|
KEYBOARD,
|
||||||
|
ADVANCED_UNLOCK
|
||||||
|
}
|
||||||
1
fastlane/metadata/android/en-US/changelogs/132.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/132.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* Upgrade to API 34 (Android 14)
|
||||||
1
fastlane/metadata/android/fr-FR/changelogs/132.txt
Normal file
1
fastlane/metadata/android/fr-FR/changelogs/132.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* Mise à jour vers API 34 (Android 14)
|
||||||
Reference in New Issue
Block a user