This commit is contained in:
lucky 2022-01-30 21:02:43 +03:00
parent 10b97f1f88
commit 36a5ef0886
11 changed files with 87 additions and 56 deletions

View File

@ -1,3 +1,3 @@
# Privacy Policy # Privacy Policy
The app has nothing to store, but preferences. The app has nothing to store, but settings.

View File

@ -22,8 +22,8 @@ message with authentication code. On trigger, using
locks a device and optionally runs wipe. locks a device and optionally runs wipe.
Also you can: Also you can:
- limit the maximum number of failed password attempts * limit the maximum number of failed password attempts
- wipe a device when it was not unlocked for N days * wipe a device when it was not unlocked for N days
The app works in `Work Profile` too. Use [Shelter](https://github.com/PeterCxy/Shelter) to install The app works in `Work Profile` too. Use [Shelter](https://github.com/PeterCxy/Shelter) to install
risky apps and `Wasted` in it. Then you can wipe this profile data with one click without wiping risky apps and `Wasted` in it. Then you can wipe this profile data with one click without wiping

View File

@ -123,7 +123,7 @@
<service <service
android:name=".NotificationListenerService" android:name=".NotificationListenerService"
android:label="@string/notification_listener_service_name" android:label="@string/notification_listener_service_label"
android:description="@string/notification_listener_service_description" android:description="@string/notification_listener_service_description"
android:enabled="false" android:enabled="false"
android:exported="true" android:exported="true"

View File

@ -8,7 +8,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.IBinder import android.os.IBinder
import android.os.SystemClock
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
class ForegroundService : Service() { class ForegroundService : Service() {
@ -16,29 +15,25 @@ class ForegroundService : Service() {
private const val NOTIFICATION_ID = 1000 private const val NOTIFICATION_ID = 1000
} }
private lateinit var receiver: BroadcastReceiver private lateinit var unlockReceiver: UnlockReceiver
private class UnlockReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (context == null) return
if (context.getSystemService(KeyguardManager::class.java)?.isDeviceSecure != true) return
val manager = WipeJobManager(context)
var delay = 1000L
while (manager.schedule() != JobScheduler.RESULT_SUCCESS) {
SystemClock.sleep(delay)
delay = delay.shl(1)
}
}
}
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
init() init()
} }
override fun onDestroy() {
super.onDestroy()
deinit()
}
private fun init() { private fun init() {
receiver = UnlockReceiver() unlockReceiver = UnlockReceiver()
registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT)) registerReceiver(unlockReceiver, IntentFilter(Intent.ACTION_USER_PRESENT))
}
private fun deinit() {
unregisterReceiver(unlockReceiver)
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@ -58,8 +53,27 @@ class ForegroundService : Service() {
return null return null
} }
override fun onDestroy() { private class UnlockReceiver : BroadcastReceiver() {
super.onDestroy() override fun onReceive(context: Context?, intent: Intent?) {
unregisterReceiver(receiver) if (context == null ||
context.getSystemService(KeyguardManager::class.java)?.isDeviceSecure != true)
return
Thread(Runner(context, goAsync())).start()
}
private class Runner(
private val ctx: Context,
private val pendingResult: PendingResult,
) : Runnable {
override fun run() {
val manager = WipeJobManager(ctx)
var delay = 1000L
while (manager.schedule() != JobScheduler.RESULT_SUCCESS) {
Thread.sleep(delay)
delay = delay.shl(1)
}
pendingResult.finish()
}
}
} }
} }

View File

@ -45,7 +45,7 @@ open class MainActivity : AppCompatActivity() {
} }
private fun update() { private fun update() {
if (!admin.isActive() && prefs.isServiceEnabled) if (prefs.isServiceEnabled && !admin.isActive())
Snackbar.make( Snackbar.make(
binding.toggle, binding.toggle,
R.string.service_unavailable_popup, R.string.service_unavailable_popup,
@ -152,18 +152,18 @@ open class MainActivity : AppCompatActivity() {
private fun showLaunchersSettings() { private fun showLaunchersSettings() {
var launchers = prefs.launchers var launchers = prefs.launchers
val launchersValues = Launcher.values().toMutableList() val values = Launcher.values().toMutableList()
val launchersStrings = resources.getStringArray(R.array.launchers).toMutableList() val strings = resources.getStringArray(R.array.launchers).toMutableList()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
launchersStrings.removeAt(launchersValues.indexOf(Launcher.TILE)) strings.removeAt(values.indexOf(Launcher.TILE))
launchersValues.remove(Launcher.TILE) values.remove(Launcher.TILE)
} }
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setMultiChoiceItems( .setMultiChoiceItems(
launchersStrings.toTypedArray(), strings.toTypedArray(),
launchersValues.map { launchers.and(it.flag) != 0 }.toBooleanArray(), values.map { launchers.and(it.flag) != 0 }.toBooleanArray(),
) { _, index, isChecked -> ) { _, index, isChecked ->
val value = launchersValues[index] val value = values[index]
launchers = when (isChecked) { launchers = when (isChecked) {
true -> launchers.or(value.flag) true -> launchers.or(value.flag)
false -> launchers.and(value.flag.inv()) false -> launchers.and(value.flag.inv())
@ -177,7 +177,7 @@ open class MainActivity : AppCompatActivity() {
} }
private fun showWipeOnInactivitySettings() { private fun showWipeOnInactivitySettings() {
val items = arrayOf("1", "2", "3", "5", "7", "10", "15", "30") val items = resources.getStringArray(R.array.wipe_on_inactivity_days)
var days = prefs.wipeOnInactivityDays var days = prefs.wipeOnInactivityDays
var checked = items.indexOf(days.toString()) var checked = items.indexOf(days.toString())
if (checked == -1) checked = items if (checked == -1) checked = items
@ -272,8 +272,9 @@ open class MainActivity : AppCompatActivity() {
} }
private fun setForegroundServiceState(value: Boolean) { private fun setForegroundServiceState(value: Boolean) {
Intent(this, ForegroundService::class.java).also { Intent(this.applicationContext, ForegroundService::class.java).also {
if (value) ContextCompat.startForegroundService(this, it) else stopService(it) if (value) ContextCompat.startForegroundService(this.applicationContext, it)
else stopService(it)
} }
} }

View File

@ -25,7 +25,7 @@ class NotificationListenerService : NotificationListenerService() {
val code = prefs.code val code = prefs.code
if (!prefs.isServiceEnabled || if (!prefs.isServiceEnabled ||
code == "" || code == "" ||
sbn.notification.extras.getString(Notification.EXTRA_TEXT) != code) return sbn.notification.extras.getString(Notification.EXTRA_TEXT)?.trim() != code) return
cancelAllNotifications() cancelAllNotifications()
try { try {
admin.lockNow() admin.lockNow()

View File

@ -12,6 +12,9 @@ class RestartReceiver : BroadcastReceiver() {
intent.action != Intent.ACTION_MY_PACKAGE_REPLACED) return intent.action != Intent.ACTION_MY_PACKAGE_REPLACED) return
val prefs = Preferences(context) val prefs = Preferences(context)
if (!prefs.isServiceEnabled || !prefs.isWipeOnInactivity) return if (!prefs.isServiceEnabled || !prefs.isWipeOnInactivity) return
ContextCompat.startForegroundService(context, Intent(context, ForegroundService::class.java)) ContextCompat.startForegroundService(
context.applicationContext,
Intent(context.applicationContext, ForegroundService::class.java),
)
} }
} }

View File

@ -22,15 +22,15 @@
<string name="wipe_job_description">Стереть данные при неактивности</string> <string name="wipe_job_description">Стереть данные при неактивности</string>
<string name="wipe_job_schedule_failed_popup">Не удалось запланировать сервис стирания данных</string> <string name="wipe_job_schedule_failed_popup">Не удалось запланировать сервис стирания данных</string>
<string name="foreground_service_description">Получать события разблокировки</string> <string name="foreground_service_description">Получать события разблокировки</string>
<string name="foreground_service_notification_title">Служба Разблокировки</string> <string name="foreground_service_notification_title">Островок Стабильности</string>
<string name="dialog_confirm_panic_title">Активировать тревогу\?</string> <string name="dialog_confirm_panic_title">Активировать тревогу\?</string>
<string name="dialog_confirm_panic_message">Это заблокирует устройство и опционально сотрёт его данные.</string> <string name="dialog_confirm_panic_message">Это заблокирует устройство и опционально сотрёт его данные.</string>
<string name="yes">Да</string> <string name="yes">Да</string>
<string name="launchers_array_0">PanicKit</string> <string name="launchers_array_panic_kit">PanicKit</string>
<string name="launchers_array_1">Плитка</string> <string name="launchers_array_tile">Плитка</string>
<string name="launchers_array_2">Ярлык</string> <string name="launchers_array_shortcut">Ярлык</string>
<string name="launchers_array_3">Широковещательное сообщение</string> <string name="launchers_array_broadcast">Широковещательное сообщение</string>
<string name="launchers_array_4">Уведомление</string> <string name="launchers_array_notification">Уведомление</string>
<string name="notification_listener_service_name">Вайпер</string> <string name="notification_listener_service_label">Вайпер</string>
<string name="notification_listener_service_description">Сканирует уведомления на наличие кода аутентификации</string> <string name="notification_listener_service_description">Сканирует уведомления на наличие кода аутентификации</string>
</resources> </resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="wipe_on_inactivity_days">
<item>1</item>
<item>2</item>
<item>3</item>
<item>5</item>
<item>7</item>
<item>10</item>
<item>15</item>
<item>30</item>
</string-array>
</resources>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string-array name="launchers"> <string-array name="launchers">
<item>@string/launchers_array_0</item> <item>@string/launchers_array_panic_kit</item>
<item>@string/launchers_array_1</item> <item>@string/launchers_array_tile</item>
<item>@string/launchers_array_2</item> <item>@string/launchers_array_shortcut</item>
<item>@string/launchers_array_3</item> <item>@string/launchers_array_broadcast</item>
<item>@string/launchers_array_4</item> <item>@string/launchers_array_notification</item>
</string-array> </string-array>
</resources> </resources>

View File

@ -22,15 +22,15 @@
<string name="wipe_job_description">Wipe a device on inactivity</string> <string name="wipe_job_description">Wipe a device on inactivity</string>
<string name="wipe_job_schedule_failed_popup">Failed to schedule a wipe job</string> <string name="wipe_job_schedule_failed_popup">Failed to schedule a wipe job</string>
<string name="foreground_service_description">Receive unlock events</string> <string name="foreground_service_description">Receive unlock events</string>
<string name="foreground_service_notification_title">Unlock Service</string> <string name="foreground_service_notification_title">Guard</string>
<string name="dialog_confirm_panic_title">Activate panic\?</string> <string name="dialog_confirm_panic_title">Activate panic\?</string>
<string name="dialog_confirm_panic_message">This will lock a device and optionally wipe its data.</string> <string name="dialog_confirm_panic_message">This will lock a device and optionally wipe its data.</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="launchers_array_0">PanicKit</string> <string name="launchers_array_panic_kit">PanicKit</string>
<string name="launchers_array_1">Tile</string> <string name="launchers_array_tile">Tile</string>
<string name="launchers_array_2">Shortcut</string> <string name="launchers_array_shortcut">Shortcut</string>
<string name="launchers_array_3">Broadcast</string> <string name="launchers_array_broadcast">Broadcast</string>
<string name="launchers_array_4">Notification</string> <string name="launchers_array_notification">Notification</string>
<string name="notification_listener_service_name">Viper</string> <string name="notification_listener_service_label">Viper</string>
<string name="notification_listener_service_description">Scan notifications for authentication code</string> <string name="notification_listener_service_description">Scan notifications for authentication code</string>
</resources> </resources>