diff --git a/README.md b/README.md index 6dd6c1b..821853c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Duress password trigger. height="80">](https://play.google.com/store/apps/details?id=me.lucky.duress) @@ -30,8 +30,16 @@ When found, it can send a broadcast message or wipe the device. * ACCESSIBILITY - listen for a duress password on the lockscreen * DEVICE_ADMIN - wipe the device (optional) +## Localization + +[Crowdin](https://crwd.in/me-lucky-duress) + ## Related +* [pam_duress](https://github.com/rafket/pam_duress) * [pam_panic](https://github.com/pampanic/pam_panic) * [pam-party](https://github.com/x13a/pam-party) * [lockup](https://github.com/nekohasekai/lockup) diff --git a/app/build.gradle b/app/build.gradle index 184f287..d401221 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "me.lucky.duress" minSdk 23 targetSdk 32 - versionCode 9 - versionName "1.0.8" + versionCode 10 + versionName "1.0.9" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -40,7 +40,7 @@ android { dependencies { implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.appcompat:appcompat:1.4.2' + implementation 'androidx.appcompat:appcompat:1.5.0' implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' testImplementation 'junit:junit:4.13.2' @@ -48,6 +48,10 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation 'androidx.security:security-crypto:1.0.0' - implementation 'androidx.preference:preference-ktx:1.2.0' + // https://issuetracker.google.com/issues/238425626 + implementation('androidx.preference:preference-ktx:1.2.0') { + exclude group: 'androidx.lifecycle', module:'lifecycle-viewmodel' + exclude group: 'androidx.lifecycle', module:'lifecycle-viewmodel-ktx' + } implementation 'androidx.biometric:biometric:1.1.0' } \ No newline at end of file diff --git a/app/src/main/java/me/lucky/duress/AccessibilityService.kt b/app/src/main/java/me/lucky/duress/AccessibilityService.kt index 7283768..a76e7a1 100644 --- a/app/src/main/java/me/lucky/duress/AccessibilityService.kt +++ b/app/src/main/java/me/lucky/duress/AccessibilityService.kt @@ -16,7 +16,6 @@ class AccessibilityService : AccessibilityService() { companion object { private const val MIN_KEYGUARD_LEN = 4 private const val MIN_LEN = MIN_KEYGUARD_LEN + 2 - private const val KEY = "code" private const val BUTTON_DELETE_DESC = "delete" private const val BUTTON_OK_DESC = "ok" private const val BUTTON_ENTER_DESC = "enter" @@ -226,8 +225,8 @@ class AccessibilityService : AccessibilityService() { ) } addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - val secret = prefs.secret - if (secret.isNotEmpty()) putExtra(KEY, secret) + val extraKey = prefs.extraKey + if (extraKey.isNotEmpty()) putExtra(extraKey, prefs.extraValue) }) } diff --git a/app/src/main/java/me/lucky/duress/MainActivity.kt b/app/src/main/java/me/lucky/duress/MainActivity.kt index bba9bf2..7ddb126 100644 --- a/app/src/main/java/me/lucky/duress/MainActivity.kt +++ b/app/src/main/java/me/lucky/duress/MainActivity.kt @@ -57,7 +57,6 @@ class MainActivity : AppCompatActivity() { prefsdb = Preferences(this, encrypted = false) prefs.copyTo(prefsdb) accessibilityManager = getSystemService(AccessibilityManager::class.java) - NotificationManager(this).createNotificationChannels() } private fun init2() { @@ -66,7 +65,8 @@ class MainActivity : AppCompatActivity() { tabs.selectTab(tabs.getTabAt(prefs.mode)) action.editText?.setText(prefs.action) receiver.editText?.setText(prefs.receiver) - secret.editText?.setText(prefs.secret) + extraKey.editText?.setText(prefs.extraKey) + extraValue.editText?.setText(prefs.extraValue) passwordOrLen.editText?.setText(prefs.passwordOrLen) keyguardType.check(when (prefs.keyguardType) { KeyguardType.A.value -> R.id.keyguardTypeA @@ -139,8 +139,11 @@ class MainActivity : AppCompatActivity() { receiver.editText?.doAfterTextChanged { prefs.receiver = it?.toString()?.trim() ?: "" } - secret.editText?.doAfterTextChanged { - prefs.secret = it?.toString()?.trim() ?: "" + extraKey.editText?.doAfterTextChanged { + prefs.extraKey = it?.toString()?.trim() ?: "" + } + extraValue.editText?.doAfterTextChanged { + prefs.extraValue = it?.toString()?.trim() ?: "" } passwordOrLen.editText?.doAfterTextChanged { prefs.passwordOrLen = it?.toString()?.trim() ?: "" @@ -166,16 +169,21 @@ class MainActivity : AppCompatActivity() { val v = when (prefs.mode) { Mode.BROADCAST.value -> View.VISIBLE Mode.WIPE.value -> View.GONE - Mode.TEST.value -> View.GONE + Mode.TEST.value -> { + NotificationManager(this).createNotificationChannels() + View.GONE + } else -> View.GONE } binding.apply { action.visibility = v receiver.visibility = v - secret.visibility = v + extraKey.visibility = v + extraValue.visibility = v space1.visibility = v space2.visibility = v space3.visibility = v + space4.visibility = v } } diff --git a/app/src/main/java/me/lucky/duress/Preferences.kt b/app/src/main/java/me/lucky/duress/Preferences.kt index d4234a4..fcd3e26 100644 --- a/app/src/main/java/me/lucky/duress/Preferences.kt +++ b/app/src/main/java/me/lucky/duress/Preferences.kt @@ -15,7 +15,8 @@ class Preferences(ctx: Context, encrypted: Boolean = true) { private const val MODE = "mode" private const val ACTION = "action" private const val RECEIVER = "receiver" - private const val SECRET = "secret" + private const val EXTRA_KEY = "extra_key" + private const val EXTRA_VALUE = "extra_value" private const val PASSWORD_OR_LEN = "password_or_len" private const val KEYGUARD_TYPE = "keyguard_type" private const val SHOW_PROMINENT_DISCLOSURE = "show_prominent_disclosure" @@ -25,6 +26,7 @@ class Preferences(ctx: Context, encrypted: Boolean = true) { private const val SERVICE_ENABLED = "service_enabled" private const val AUTHENTICATION_CODE = "authentication_code" private const val PASSWORD_LEN = "password_len" + private const val SECRET = "secret" fun new(ctx: Context) = Preferences( ctx, @@ -64,12 +66,22 @@ class Preferences(ctx: Context, encrypted: Boolean = true) { get() = prefs.getString(RECEIVER, "") ?: "" set(value) = prefs.edit { putString(RECEIVER, value) } - var secret: String - get() = prefs.getString(SECRET, prefs.getString(AUTHENTICATION_CODE, "")) ?: "" - set(value) = prefs.edit { putString(SECRET, value) } + var extraKey: String + get() = prefs.getString(EXTRA_KEY, "code") ?: "" + set(value) = prefs.edit { putString(EXTRA_KEY, value) } + + var extraValue: String + get() = prefs.getString( + EXTRA_VALUE, + prefs.getString(SECRET, prefs.getString(AUTHENTICATION_CODE, "")), + ) ?: "" + set(value) = prefs.edit { putString(EXTRA_VALUE, value) } var passwordOrLen: String - get() = prefs.getString(PASSWORD_OR_LEN, prefs.getString(PASSWORD_LEN, "")) ?: "" + get() = prefs.getString( + PASSWORD_OR_LEN, + prefs.getInt(PASSWORD_LEN, 0).toString(), + ) ?: "" set(value) = prefs.edit { putString(PASSWORD_OR_LEN, value) } var keyguardType: Int diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ae53dee..c193755 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -84,10 +84,10 @@ android:layout_marginVertical="5dp" /> + android:hint="@string/extra_key"> + + + + + + + + + + Duress + Service indisponible + Divulgation Importante + L\'application utilise le service d\'accessibilité pour écouter un mot de passe de contrainte sur l\'écran de verrouillage. Une fois trouvé, il peut envoyer un message de diffusion ou effacer l\'appareil. + Accepter + Quitter + action* + récepteur + Code PIN/mot de passe ou longueur* + La longueur doit être d\'au moins la longueur de votre code PIN/mot de passe plus deux. + DIFFUSER + EFFACER + TEST + Garde-clefs: + A + B (PIN uniquement) + Si vous utilisez un code PIN/mot de passe (et non la longueur), le Garde-clefs A requiert que l\'option d\'affichage des caractères du mot de passe lors de la saisie soit activée. Garde-clefs B peut être dépendant de la langue (EN). Si vous changez le type de Garde-clefs, redémarrez le service d\'accessibilité. + Authentification + Défaut + Test + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 11b3574..c733493 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -8,5 +8,4 @@ Выйти Действие * Получатель - Код аутентификации \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000..db601b0 --- /dev/null +++ b/app/src/main/res/values-uk/strings.xml @@ -0,0 +1,23 @@ + + + Duress + Сервіс недоступний + Помітне розкриття інформації + Додаток використовує службу доступності, щоб прослуховувати примусовий пароль на екрані блокування. Коли він знайдений, він може надіслати широкомовне повідомлення або стерти пристрій. + Прийняти + Вихід + дія* + приймач + PIN-код/пароль або довжина* + Довжина має бути принаймні довжиною вашого PIN-коду/пароля не менше 2. + ТРАНСЛЯЦІЯ + ОЧИЩЕННЯ + ТЕСТ + Блокування клавіш: + A + B (лише PIN-код) + Якщо ви використовуєте PIN-код/пароль (а не довжину), функція блокування клавіатури A вимагає відображення символів пароля під час введення. Блокування клавіатури B може залежати від мови (EN). Якщо ви змінили тип блокування клавіатури, перезапустіть службу доступності. + Автентифікація + За замовчуванням + Тест + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000..d992253 --- /dev/null +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,24 @@ + + + 緊急脅迫 + 服務無法使用 + 重要訊息揭露 + 這個APP使用無障礙服務來在鎖定螢幕上監聽脅迫密碼。當發現時會發送廣播訊息或清除裝置。 + 接受 + 離開 + 動作* + 接收器 + PIN/密碼或長度* + 長度至少要是你的PIN或密碼的長度加2 + 廣播 + 清除裝置 + 測試 + 鍵盤類型: + A + B(僅限PIN) + 如果你使用PIN或密碼(而非長度),鍵盤A需要啟用輸入時顯示密碼字元之選項,鍵盤B可能限定語言(如英文) +如果你改變鍵盤類型,需重啟無障礙服務 + 驗證 + 預設值 + 測試 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52fbfcb..7d7bf7f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,7 +8,8 @@ Exit action* receiver - secret + key + value PIN/password or length* The length has to be at least your PIN/password length plus two. BROADCAST diff --git a/build.gradle b/build.gradle index 4711aa7..255b9b3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '7.2.1' apply false - id 'com.android.library' version '7.2.1' apply false + id 'com.android.application' version '7.2.2' apply false + id 'com.android.library' version '7.2.2' apply false id 'org.jetbrains.kotlin.android' version '1.7.0' apply false } diff --git a/fastlane/metadata/android/en-US/changelogs/10.txt b/fastlane/metadata/android/en-US/changelogs/10.txt new file mode 100644 index 0000000..7a8728b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10.txt @@ -0,0 +1,5 @@ +custom extra key +prepare Android 13 +add Ukrainian translation, thanks to GNCanva +add French translation, thanks to Nathanaël Gagnepain (@Ilithy) +add Chinese Traditional translation, thanks to rdol724 diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png index e906b9c..bcd9949 100644 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ