mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/API34' into develop
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
KeePassDX(4.1.0)
|
||||
* Upgrade to API 34 (Android 14)
|
||||
|
||||
KeePassDX(4.0.8)
|
||||
* Fix graphical bug that prevented databases from being opened on some versions of Android #1848 #1850
|
||||
|
||||
|
||||
@@ -5,15 +5,14 @@ apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.keepass'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.2"
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 33
|
||||
versionCode = 131
|
||||
versionName = "4.0.8"
|
||||
targetSdkVersion 34
|
||||
versionCode = 132
|
||||
versionName = "4.1.0"
|
||||
multiDexEnabled true
|
||||
|
||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
android:anyDensity="true" />
|
||||
<uses-permission
|
||||
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
|
||||
android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission
|
||||
@@ -197,18 +201,27 @@
|
||||
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.services.DatabaseTaskNotificationService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.services.AttachmentFileNotificationService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
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:exported="false" />
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.services.AdvancedUnlockNotificationService"
|
||||
android:foregroundServiceType="specialUse"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<!-- Receiver for Autofill -->
|
||||
@@ -235,10 +248,6 @@
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.services.KeyboardEntryNotificationService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<receiver
|
||||
android:name="com.kunzisoft.keepass.receivers.DexModeReceiver"
|
||||
android:exported="true">
|
||||
|
||||
@@ -38,7 +38,11 @@ import android.graphics.RectF
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Build
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import android.view.ScaleGestureDetector
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.Interpolator
|
||||
@@ -202,7 +206,7 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
|
||||
override fun onDown(e: MotionEvent): Boolean = true
|
||||
|
||||
override fun onScroll(
|
||||
e1: MotionEvent,
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
distanceX: Float,
|
||||
distanceY: Float
|
||||
@@ -220,7 +224,7 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
|
||||
}
|
||||
|
||||
override fun onFling(
|
||||
e1: MotionEvent,
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData.Companion.BASE64_FLAG
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
|
||||
@@ -69,9 +70,11 @@ class CipherDatabaseAction(context: Context) {
|
||||
|
||||
@Synchronized
|
||||
private fun attachService(performedAction: () -> Unit) {
|
||||
applicationContext.registerReceiver(mAdvancedUnlockBroadcastReceiver, IntentFilter().apply {
|
||||
addAction(AdvancedUnlockNotificationService.REMOVE_ADVANCED_UNLOCK_KEY_ACTION)
|
||||
})
|
||||
ContextCompat.registerReceiver(applicationContext, mAdvancedUnlockBroadcastReceiver,
|
||||
IntentFilter().apply {
|
||||
addAction(AdvancedUnlockNotificationService.REMOVE_ADVANCED_UNLOCK_KEY_ACTION)
|
||||
}, ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
mServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
||||
@@ -97,7 +100,7 @@ class CipherDatabaseAction(context: Context) {
|
||||
private fun detachService() {
|
||||
try {
|
||||
applicationContext.unregisterReceiver(mAdvancedUnlockBroadcastReceiver)
|
||||
} catch (e: Exception) {}
|
||||
} catch (_: Exception) {}
|
||||
|
||||
mServiceConnection?.let {
|
||||
AdvancedUnlockNotificationService.unbindService(applicationContext, it)
|
||||
|
||||
@@ -40,6 +40,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kunzisoft.keepass.R
|
||||
@@ -330,11 +331,11 @@ class DatabaseTaskProvider(
|
||||
}
|
||||
}
|
||||
}
|
||||
context.registerReceiver(databaseTaskBroadcastReceiver,
|
||||
ContextCompat.registerReceiver(context, databaseTaskBroadcastReceiver,
|
||||
IntentFilter().apply {
|
||||
addAction(DATABASE_START_TASK_ACTION)
|
||||
addAction(DATABASE_STOP_TASK_ACTION)
|
||||
}
|
||||
}, RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
|
||||
// Check if a service is currently running else do nothing
|
||||
|
||||
@@ -86,11 +86,19 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
||||
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
||||
// Not necessarily a foreground service
|
||||
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
||||
defineTimerJob(notificationBuilder, notificationTimeoutMilliSecs) {
|
||||
defineTimerJob(
|
||||
notificationBuilder,
|
||||
NotificationServiceType.ADVANCED_UNLOCK,
|
||||
notificationTimeoutMilliSecs
|
||||
) {
|
||||
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
||||
}
|
||||
} else {
|
||||
startForeground(notificationId, notificationBuilder.build())
|
||||
startForegroundCompat(
|
||||
notificationId,
|
||||
notificationBuilder,
|
||||
NotificationServiceType.ADVANCED_UNLOCK
|
||||
)
|
||||
}
|
||||
|
||||
return mActionTaskBinder
|
||||
|
||||
@@ -36,13 +36,13 @@ import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
|
||||
@@ -282,15 +282,21 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
AttachmentState.ERROR -> {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||
try {
|
||||
notificationManager?.notify(
|
||||
attachmentNotification.notificationId,
|
||||
builder.build()
|
||||
)
|
||||
checkNotificationsPermission(this) {
|
||||
notificationManager?.notify(
|
||||
attachmentNotification.notificationId,
|
||||
builder.build()
|
||||
)
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
Log.e(TAG, "Unable to notify the attachment state", e)
|
||||
}
|
||||
} else -> {
|
||||
startForeground(attachmentNotification.notificationId, builder.build())
|
||||
startForegroundCompat(
|
||||
attachmentNotification.notificationId,
|
||||
builder,
|
||||
NotificationServiceType.ATTACHMENT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,12 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.services
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||
@@ -196,23 +192,29 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
||||
//Get settings
|
||||
val notificationTimeoutMilliSecs = PreferencesUtil.getClipboardTimeout(this)
|
||||
if (notificationTimeoutMilliSecs != NEVER) {
|
||||
defineTimerJob(builder, notificationTimeoutMilliSecs, {
|
||||
val newGeneratedValue = fieldToCopy.getGeneratedValue(mEntryInfo)
|
||||
// New auto generated value
|
||||
if (generatedValue != newGeneratedValue) {
|
||||
generatedValue = newGeneratedValue
|
||||
clipboardHelper?.copyToClipboard(
|
||||
fieldToCopy.label,
|
||||
generatedValue,
|
||||
fieldToCopy.isSensitive
|
||||
)
|
||||
defineTimerJob(
|
||||
builder,
|
||||
NotificationServiceType.CLIPBOARD,
|
||||
notificationTimeoutMilliSecs,
|
||||
{
|
||||
val newGeneratedValue = fieldToCopy.getGeneratedValue(mEntryInfo)
|
||||
// New auto generated value
|
||||
if (generatedValue != newGeneratedValue) {
|
||||
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 {
|
||||
// No timer
|
||||
checkNotificationsPermission {
|
||||
@@ -226,12 +228,11 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
||||
}
|
||||
|
||||
private fun checkNotificationsPermission(action: () -> Unit) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
action.invoke()
|
||||
} else {
|
||||
showPermissionErrorIfNeeded(this)
|
||||
}
|
||||
checkNotificationsPermission(
|
||||
this,
|
||||
PreferencesUtil.isClipboardNotificationsEnable(this),
|
||||
action
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
@@ -255,26 +256,14 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
||||
const val EXTRA_CLIPBOARD_FIELDS = "EXTRA_CLIPBOARD_FIELDS"
|
||||
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(
|
||||
activity: Activity,
|
||||
entry: EntryInfo
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
activity,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) == PackageManager.PERMISSION_GRANTED) {
|
||||
launchNotificationIfAllowed(activity, entry)
|
||||
} else {
|
||||
showPermissionErrorIfNeeded(activity)
|
||||
}
|
||||
} else {
|
||||
checkNotificationsPermission(
|
||||
activity,
|
||||
PreferencesUtil.isClipboardNotificationsEnable(activity)
|
||||
) {
|
||||
launchNotificationIfAllowed(activity, entry)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,7 +591,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
|
||||
// Create the notification
|
||||
startForeground(notificationId, notificationBuilder.build())
|
||||
startForegroundCompat(
|
||||
notificationId,
|
||||
notificationBuilder,
|
||||
NotificationServiceType.DATABASE_TASK
|
||||
)
|
||||
}
|
||||
|
||||
private fun removeIntentData(intent: Intent?) {
|
||||
|
||||
@@ -111,13 +111,18 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
.setContentIntent(null)
|
||||
.setDeleteIntent(pendingDeleteIntent)
|
||||
|
||||
notificationManager?.cancel(notificationId)
|
||||
notificationManager?.notify(notificationId, builder.build())
|
||||
checkNotificationsPermission(this, PreferencesUtil.isKeyboardNotificationEntryEnable(this)) {
|
||||
notificationManager?.notify(notificationId, builder.build())
|
||||
}
|
||||
|
||||
// Timeout only if notification clear is available
|
||||
if (PreferencesUtil.isClearKeyboardNotificationEnable(this)) {
|
||||
if (mNotificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
||||
defineTimerJob(builder, mNotificationTimeoutMilliSecs) {
|
||||
defineTimerJob(
|
||||
builder,
|
||||
NotificationServiceType.KEYBOARD,
|
||||
mNotificationTimeoutMilliSecs
|
||||
) {
|
||||
stopNotificationAndSendLockIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
package com.kunzisoft.keepass.services
|
||||
|
||||
import android.Manifest
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
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.IBinder
|
||||
import android.util.TypedValue
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
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() {
|
||||
@@ -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,
|
||||
type: NotificationServiceType,
|
||||
timeoutMilliseconds: Long,
|
||||
actionAfterASecond: (() -> Unit)? = null,
|
||||
actionEnd: () -> Unit) {
|
||||
@@ -87,7 +125,7 @@ abstract class NotificationService : Service() {
|
||||
builder.setProgress(100,
|
||||
(currentTime * 100 / timeoutInSeconds).toInt(),
|
||||
false)
|
||||
startForeground(notificationId, builder.build())
|
||||
startForegroundCompat(notificationId, builder, type)
|
||||
delay(1000)
|
||||
if (currentTime <= 0) {
|
||||
actionEnd()
|
||||
@@ -114,5 +152,25 @@ abstract class NotificationService : Service() {
|
||||
companion object {
|
||||
private const val CHANNEL_ID = "com.kunzisoft.keepass.notification.channel"
|
||||
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
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
@@ -45,9 +46,9 @@ const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK"
|
||||
const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD"
|
||||
const val BACK_PREVIOUS_KEYBOARD_ACTION = "com.kunzisoft.keepass.BACK_PREVIOUS_KEYBOARD"
|
||||
|
||||
class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
class LockReceiver(private var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
|
||||
var mLockPendingIntent: PendingIntent? = null
|
||||
private var mLockPendingIntent: PendingIntent? = null
|
||||
var backToPreviousKeyboardAction: (() -> Unit)? = null
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
@@ -60,7 +61,7 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
}
|
||||
Intent.ACTION_SCREEN_OFF -> {
|
||||
if (PreferencesUtil.isLockDatabaseWhenScreenShutOffEnable(context)) {
|
||||
mLockPendingIntent = PendingIntent.getBroadcast(context,
|
||||
val lockPendingIntent = PendingIntent.getBroadcast(context,
|
||||
4575,
|
||||
Intent(intent).apply {
|
||||
action = LOCK_ACTION
|
||||
@@ -71,6 +72,7 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
0
|
||||
}
|
||||
)
|
||||
this.mLockPendingIntent = lockPendingIntent
|
||||
// Launch the effective action after a small time
|
||||
val first: Long = System.currentTimeMillis() + context.getString(R.string.timeout_screen_off).toLong()
|
||||
(context.getSystemService(ALARM_SERVICE) as AlarmManager?)?.let { alarmManager ->
|
||||
@@ -80,20 +82,20 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
alarmManager.set(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
first,
|
||||
mLockPendingIntent
|
||||
lockPendingIntent
|
||||
)
|
||||
} else {
|
||||
alarmManager.setExact(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
first,
|
||||
mLockPendingIntent
|
||||
lockPendingIntent
|
||||
)
|
||||
}
|
||||
} else {
|
||||
alarmManager.set(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
first,
|
||||
mLockPendingIntent
|
||||
lockPendingIntent
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -120,9 +122,9 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
private fun cancelLockPendingIntent(context: Context) {
|
||||
mLockPendingIntent?.let {
|
||||
mLockPendingIntent?.let { lockPendingIntent ->
|
||||
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager?
|
||||
alarmManager?.cancel(mLockPendingIntent)
|
||||
alarmManager?.cancel(lockPendingIntent)
|
||||
mLockPendingIntent = null
|
||||
}
|
||||
}
|
||||
@@ -131,7 +133,7 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
fun Context.registerLockReceiver(lockReceiver: LockReceiver?,
|
||||
registerKeyboardAction: Boolean = false) {
|
||||
lockReceiver?.let {
|
||||
registerReceiver(it, IntentFilter().apply {
|
||||
ContextCompat.registerReceiver(this, it, IntentFilter().apply {
|
||||
addAction(Intent.ACTION_SCREEN_OFF)
|
||||
addAction(Intent.ACTION_SCREEN_ON)
|
||||
addAction(LOCK_ACTION)
|
||||
@@ -139,7 +141,7 @@ fun Context.registerLockReceiver(lockReceiver: LockReceiver?,
|
||||
addAction(REMOVE_ENTRY_MAGIKEYBOARD_ACTION)
|
||||
addAction(BACK_PREVIOUS_KEYBOARD_ACTION)
|
||||
}
|
||||
})
|
||||
}, ContextCompat.RECEIVER_EXPORTED)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,12 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.encrypt'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.2"
|
||||
compileSdkVersion 34
|
||||
ndkVersion "21.4.7075529"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion 34
|
||||
multiDexEnabled true
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
@@ -3,12 +3,11 @@ apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.keepass.database'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.2"
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdk 33
|
||||
targetSdk 34
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -3,12 +3,11 @@ apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.keepass.icon'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion '33.0.2'
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion 34
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
||||
@@ -2,12 +2,11 @@ apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.keepass.icon.classic'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion '33.0.2'
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion 34
|
||||
}
|
||||
|
||||
resourcePrefix 'classic_'
|
||||
|
||||
@@ -2,12 +2,11 @@ apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
namespace 'com.kunzisoft.keepass.icon.material'
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion '33.0.2'
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion 34
|
||||
}
|
||||
|
||||
resourcePrefix 'material_'
|
||||
|
||||
@@ -19,18 +19,19 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.icon
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.util.SparseIntArray
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Class who construct dynamically database icons contains in a separate library
|
||||
*
|
||||
*
|
||||
* It only supports icons with specific nomenclature **[stringId]_[%2d]_32dp**
|
||||
* where [stringId] contains in a string xml attribute with id **resource_id** and
|
||||
* [%2d] 2 numerical numbers between 00 and 68 included,
|
||||
* It only supports icons with specific nomenclature **{stringId}_{%2d}_32dp**
|
||||
* where {stringId} contains in a string xml attribute with id **resource_id** and
|
||||
* {%2d} 2 numerical numbers between 00 and 68 included,
|
||||
*
|
||||
*
|
||||
* See *icon-pack-classic* module as sample
|
||||
@@ -41,6 +42,7 @@ import java.util.*
|
||||
* @param packageName Context of the app to retrieve the resources
|
||||
* @param resourceId String Id of the pack (ex : com.kunzisoft.keepass.icon.classic.R.string.resource_id)
|
||||
*/
|
||||
@SuppressLint("DiscouragedApi")
|
||||
class IconPack(packageName: String, resources: Resources, resourceId: Int) {
|
||||
|
||||
private val icons: SparseIntArray = SparseIntArray()
|
||||
|
||||
Reference in New Issue
Block a user