mirror of https://github.com/x13a/Wasted.git
recast option
This commit is contained in:
parent
6fc8fa382b
commit
957bec3a33
|
@ -19,7 +19,8 @@ Lock a device and wipe its data on emergency.
|
|||
You can use [PanicKit](https://guardianproject.info/code/panickit/), tile, shortcut or send a
|
||||
message with a secret code. On trigger, using
|
||||
[Device Administration API](https://developer.android.com/guide/topics/admin/device-admin), it
|
||||
locks a device and optionally runs wipe.
|
||||
locks a device and optionally runs wipe (factory reset). Also it can send a broadcast message
|
||||
instead of the wipe.
|
||||
|
||||
Also you can:
|
||||
* fire when a device was not unlocked for X time
|
||||
|
|
|
@ -10,8 +10,8 @@ android {
|
|||
applicationId "me.lucky.wasted"
|
||||
minSdk 23
|
||||
targetSdk 32
|
||||
versionCode 38
|
||||
versionName "1.5.9"
|
||||
versionCode 39
|
||||
versionName "1.5.10"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ open class MainActivity : AppCompatActivity() {
|
|||
R.id.nav_trigger_notification -> NotificationFragment()
|
||||
R.id.nav_trigger_lock -> LockFragment()
|
||||
R.id.nav_trigger_application -> ApplicationFragment()
|
||||
R.id.top_settings -> SettingsFragment()
|
||||
R.id.nav_recast -> RecastFragment()
|
||||
else -> MainFragment()
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ class Preferences(ctx: Context, encrypted: Boolean = true) {
|
|||
private const val WIPE_DATA = "wipe_data"
|
||||
private const val WIPE_EMBEDDED_SIM = "wipe_embedded_sim"
|
||||
|
||||
private const val RECAST_ENABLED = "recast_enabled"
|
||||
private const val RECAST_ACTION = "recast_action"
|
||||
private const val RECAST_RECEIVER = "recast_receiver"
|
||||
private const val RECAST_EXTRA_KEY = "recast_extra_key"
|
||||
private const val RECAST_EXTRA_VALUE = "recast_extra_value"
|
||||
|
||||
private const val TRIGGERS = "triggers"
|
||||
private const val TRIGGER_LOCK_COUNT = "trigger_lock_count"
|
||||
private const val TRIGGER_TILE_DELAY = "trigger_tile_delay"
|
||||
|
@ -90,6 +96,26 @@ class Preferences(ctx: Context, encrypted: Boolean = true) {
|
|||
get() = prefs.getInt(TRIGGER_APPLICATION_OPTIONS, 0)
|
||||
set(value) = prefs.edit { putInt(TRIGGER_APPLICATION_OPTIONS, value) }
|
||||
|
||||
var isRecastEnabled: Boolean
|
||||
get() = prefs.getBoolean(RECAST_ENABLED, false)
|
||||
set(value) = prefs.edit { putBoolean(RECAST_ENABLED, value) }
|
||||
|
||||
var recastAction: String
|
||||
get() = prefs.getString(RECAST_ACTION, "") ?: ""
|
||||
set(value) = prefs.edit { putString(RECAST_ACTION, value) }
|
||||
|
||||
var recastReceiver: String
|
||||
get() = prefs.getString(RECAST_RECEIVER, "") ?: ""
|
||||
set(value) = prefs.edit { putString(RECAST_RECEIVER, value) }
|
||||
|
||||
var recastExtraKey: String
|
||||
get() = prefs.getString(RECAST_EXTRA_KEY, "") ?: ""
|
||||
set(value) = prefs.edit { putString(RECAST_EXTRA_KEY, value) }
|
||||
|
||||
var recastExtraValue: String
|
||||
get() = prefs.getString(RECAST_EXTRA_VALUE, "") ?: ""
|
||||
set(value) = prefs.edit { putString(RECAST_EXTRA_VALUE, value) }
|
||||
|
||||
fun registerListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) =
|
||||
prefs.registerOnSharedPreferenceChangeListener(listener)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package me.lucky.wasted
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -7,6 +8,7 @@ import android.content.pm.PackageManager
|
|||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.trigger.notification.NotificationListenerService
|
||||
import me.lucky.wasted.trigger.panic.PanicConnectionActivity
|
||||
import me.lucky.wasted.trigger.panic.PanicResponderActivity
|
||||
|
@ -26,10 +28,10 @@ class Utils(private val ctx: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
private val shortcut by lazy { ShortcutManager(ctx) }
|
||||
private val prefs by lazy { Preferences.new(ctx) }
|
||||
|
||||
fun setEnabled(enabled: Boolean) {
|
||||
val triggers = Preferences(ctx).triggers
|
||||
val triggers = prefs.triggers
|
||||
setPanicKitEnabled(enabled && triggers.and(Trigger.PANIC_KIT.value) != 0)
|
||||
setTileEnabled(enabled && triggers.and(Trigger.TILE.value) != 0)
|
||||
setShortcutEnabled(enabled && triggers.and(Trigger.SHORTCUT.value) != 0)
|
||||
|
@ -50,6 +52,7 @@ class Utils(private val ctx: Context) {
|
|||
}
|
||||
|
||||
fun setShortcutEnabled(enabled: Boolean) {
|
||||
val shortcut = ShortcutManager(ctx)
|
||||
if (!enabled) shortcut.remove()
|
||||
setComponentEnabled(ShortcutActivity::class.java, enabled)
|
||||
if (enabled) shortcut.push()
|
||||
|
@ -63,7 +66,6 @@ class Utils(private val ctx: Context) {
|
|||
|
||||
fun updateApplicationEnabled() {
|
||||
val prefix = "${ctx.packageName}.trigger.application"
|
||||
val prefs = Preferences(ctx)
|
||||
val options = prefs.triggerApplicationOptions
|
||||
val enabled = prefs.isEnabled && prefs.triggers.and(Trigger.APPLICATION.value) != 0
|
||||
setComponentEnabled(
|
||||
|
@ -85,7 +87,6 @@ class Utils(private val ctx: Context) {
|
|||
}
|
||||
|
||||
fun updateForegroundRequiredEnabled() {
|
||||
val prefs = Preferences(ctx)
|
||||
val enabled = prefs.isEnabled
|
||||
val triggers = prefs.triggers
|
||||
val isUSB = triggers.and(Trigger.USB.value) != 0
|
||||
|
@ -114,4 +115,36 @@ class Utils(private val ctx: Context) {
|
|||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
)
|
||||
|
||||
fun fire(trigger: Trigger, safe: Boolean = true) {
|
||||
if (!prefs.isEnabled || prefs.triggers.and(trigger.value) == 0) return
|
||||
val admin = DeviceAdminManager(ctx)
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData && safe) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
if (prefs.isRecastEnabled && safe) recast()
|
||||
}
|
||||
|
||||
fun isDeviceLocked() = ctx.getSystemService(KeyguardManager::class.java).isDeviceLocked
|
||||
|
||||
private fun recast() {
|
||||
val action = prefs.recastAction
|
||||
if (action.isEmpty()) return
|
||||
ctx.sendBroadcast(Intent(action).apply {
|
||||
val cls = prefs.recastReceiver.split('/')
|
||||
val packageName = cls.firstOrNull() ?: ""
|
||||
if (packageName.isNotEmpty()) {
|
||||
setPackage(packageName)
|
||||
if (cls.size == 2)
|
||||
setClassName(
|
||||
packageName,
|
||||
"$packageName.${cls[1].trimStart('.')}",
|
||||
)
|
||||
}
|
||||
addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||
val extraKey = prefs.recastExtraKey
|
||||
if (extraKey.isNotEmpty()) putExtra(extraKey, prefs.recastExtraValue)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package me.lucky.wasted.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.databinding.FragmentRecastBinding
|
||||
|
||||
class RecastFragment : Fragment() {
|
||||
private lateinit var binding: FragmentRecastBinding
|
||||
private lateinit var ctx: Context
|
||||
private lateinit var prefs: Preferences
|
||||
private lateinit var prefsdb: Preferences
|
||||
|
||||
private val prefsListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
|
||||
prefs.copyTo(prefsdb, key)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View {
|
||||
binding = FragmentRecastBinding.inflate(inflater, container, false)
|
||||
init()
|
||||
setup()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
prefs.registerListener(prefsListener)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
prefs.unregisterListener(prefsListener)
|
||||
}
|
||||
|
||||
private fun init() {
|
||||
ctx = requireContext()
|
||||
prefs = Preferences(ctx)
|
||||
prefsdb = Preferences(ctx, encrypted = false)
|
||||
binding.apply {
|
||||
enabled.isChecked = prefs.isRecastEnabled
|
||||
action.editText?.setText(prefs.recastAction)
|
||||
receiver.editText?.setText(prefs.recastReceiver)
|
||||
extraKey.editText?.setText(prefs.recastExtraKey)
|
||||
extraValue.editText?.setText(prefs.recastExtraValue)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setup() = binding.apply {
|
||||
enabled.setOnCheckedChangeListener { _, isChecked ->
|
||||
prefs.isRecastEnabled = isChecked
|
||||
}
|
||||
action.editText?.doAfterTextChanged {
|
||||
prefs.recastAction = it?.toString()?.trim() ?: return@doAfterTextChanged
|
||||
}
|
||||
receiver.editText?.doAfterTextChanged {
|
||||
prefs.recastReceiver = it?.toString()?.trim() ?: return@doAfterTextChanged
|
||||
}
|
||||
extraKey.editText?.doAfterTextChanged {
|
||||
prefs.recastExtraKey = it?.toString()?.trim() ?: return@doAfterTextChanged
|
||||
}
|
||||
extraValue.editText?.doAfterTextChanged {
|
||||
prefs.recastExtraValue = it?.toString()?.trim() ?: return@doAfterTextChanged
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,24 +3,13 @@ package me.lucky.wasted.trigger.application
|
|||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class ApplicationActivity : AppCompatActivity() {
|
||||
private val prefs by lazy { Preferences(this) }
|
||||
private val admin by lazy { DeviceAdminManager(this) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (!prefs.isEnabled || prefs.triggers.and(Trigger.APPLICATION.value) == 0) {
|
||||
finishAndRemoveTask()
|
||||
return
|
||||
}
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
Utils(this).fire(Trigger.APPLICATION)
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
|
@ -6,30 +6,23 @@ import android.content.Intent
|
|||
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class BroadcastReceiver : BroadcastReceiver() {
|
||||
companion object {
|
||||
const val KEY = "code"
|
||||
const val ACTION = "me.lucky.wasted.action.TRIGGER"
|
||||
|
||||
fun panic(context: Context, intent: Intent?) {
|
||||
fun panic(context: Context, intent: Intent?, trigger: Trigger) {
|
||||
if (intent?.action != ACTION) return
|
||||
val prefs = Preferences.new(context)
|
||||
if (!prefs.isEnabled) return
|
||||
val secret = prefs.secret
|
||||
val secret = Preferences.new(context).secret
|
||||
assert(secret.isNotEmpty())
|
||||
if (intent.getStringExtra(KEY)?.trim() != secret) return
|
||||
val admin = DeviceAdminManager(context)
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
Utils(context).fire(trigger)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (Preferences.new(context ?: return).triggers.and(Trigger.BROADCAST.value) != 0)
|
||||
panic(context, intent)
|
||||
panic(context ?: return, intent, Trigger.BROADCAST)
|
||||
}
|
||||
}
|
|
@ -3,19 +3,12 @@ package me.lucky.wasted.trigger.lock
|
|||
import android.app.job.JobParameters
|
||||
import android.app.job.JobService
|
||||
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class LockJobService : JobService() {
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
val prefs = Preferences.new(this)
|
||||
if (!prefs.isEnabled || prefs.triggers.and(Trigger.LOCK.value) == 0) return false
|
||||
val admin = DeviceAdminManager(this)
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
Utils(this).fire(Trigger.LOCK)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ import android.os.Build
|
|||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class NotificationListenerService : NotificationListenerService() {
|
||||
private lateinit var prefs: Preferences
|
||||
private lateinit var admin: DeviceAdminManager
|
||||
private lateinit var utils: Utils
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
@ -20,22 +20,17 @@ class NotificationListenerService : NotificationListenerService() {
|
|||
|
||||
private fun init() {
|
||||
prefs = Preferences.new(this)
|
||||
admin = DeviceAdminManager(this)
|
||||
utils = Utils(this)
|
||||
}
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||
super.onNotificationPosted(sbn)
|
||||
if (sbn == null ||
|
||||
!prefs.isEnabled ||
|
||||
prefs.triggers.and(Trigger.NOTIFICATION.value) == 0) return
|
||||
if (sbn == null) return
|
||||
val secret = prefs.secret
|
||||
assert(secret.isNotEmpty())
|
||||
if (sbn.notification.extras[Notification.EXTRA_TEXT]?.toString() != secret) return
|
||||
if (sbn.notification.extras[Notification.EXTRA_TEXT]?.toString()?.trim() != secret) return
|
||||
cancelAllNotifications()
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
utils.fire(Trigger.NOTIFICATION)
|
||||
}
|
||||
|
||||
override fun onListenerConnected() {
|
||||
|
|
|
@ -5,28 +5,20 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
|
||||
import info.guardianproject.panic.Panic
|
||||
import info.guardianproject.panic.PanicResponder
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class PanicResponderActivity : AppCompatActivity() {
|
||||
private val prefs by lazy { Preferences.new(this) }
|
||||
private val admin by lazy { DeviceAdminManager(this) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (!Panic.isTriggerIntent(intent) ||
|
||||
!prefs.isEnabled ||
|
||||
prefs.triggers.and(Trigger.PANIC_KIT.value) == 0)
|
||||
{
|
||||
if (!Panic.isTriggerIntent(intent)) {
|
||||
finishAndRemoveTask()
|
||||
return
|
||||
}
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (PanicResponder.receivedTriggerFromConnectedApp(this) &&
|
||||
prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
Utils(this).fire(
|
||||
Trigger.PANIC_KIT,
|
||||
PanicResponder.receivedTriggerFromConnectedApp(this),
|
||||
)
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import androidx.core.app.NotificationCompat
|
|||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.R
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Utils
|
||||
import me.lucky.wasted.trigger.lock.LockJobManager
|
||||
|
||||
class ForegroundService : Service() {
|
||||
|
@ -113,17 +113,11 @@ class ForegroundService : Service() {
|
|||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.action != ACTION_USB_STATE) return
|
||||
val prefs = Preferences.new(context ?: return)
|
||||
if (!prefs.isEnabled ||
|
||||
prefs.triggers.and(Trigger.USB.value) == 0 ||
|
||||
!context.getSystemService(KeyguardManager::class.java).isDeviceLocked) return
|
||||
val utils = Utils(context ?: return)
|
||||
if (!utils.isDeviceLocked()) return
|
||||
val extras = intent.extras ?: return
|
||||
if (!extras.getBoolean(KEY_1) && !extras.getBoolean(KEY_2)) return
|
||||
val admin = DeviceAdminManager(context)
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
utils.fire(Trigger.USB)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,15 +3,13 @@ package me.lucky.wasted.trigger.shortcut
|
|||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.trigger.broadcast.BroadcastReceiver
|
||||
|
||||
class ShortcutActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (Preferences(this).triggers.and(Trigger.SHORTCUT.value) != 0)
|
||||
BroadcastReceiver.panic(this, intent)
|
||||
BroadcastReceiver.panic(this, intent, Trigger.SHORTCUT)
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
|
@ -10,11 +10,13 @@ import kotlin.concurrent.timerTask
|
|||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
class TileService : TileService() {
|
||||
private lateinit var prefs: Preferences
|
||||
private lateinit var admin: DeviceAdminManager
|
||||
private lateinit var utils: Utils
|
||||
private var counter = 0
|
||||
private var timer: Timer? = null
|
||||
|
||||
|
@ -26,6 +28,7 @@ class TileService : TileService() {
|
|||
private fun init() {
|
||||
prefs = Preferences.new(this)
|
||||
admin = DeviceAdminManager(this)
|
||||
utils = Utils(this)
|
||||
}
|
||||
|
||||
override fun onStartListening() {
|
||||
|
@ -38,11 +41,8 @@ class TileService : TileService() {
|
|||
|
||||
override fun onClick() {
|
||||
super.onClick()
|
||||
if (!prefs.isEnabled || prefs.triggers.and(Trigger.TILE.value) == 0) return
|
||||
if (!prefs.isWipeData) {
|
||||
try {
|
||||
admin.lockNow()
|
||||
} catch (exc: SecurityException) {}
|
||||
utils.fire(Trigger.TILE, false)
|
||||
return
|
||||
}
|
||||
val v = counter
|
||||
|
@ -53,10 +53,7 @@ class TileService : TileService() {
|
|||
timer?.cancel()
|
||||
timer = Timer()
|
||||
timer?.schedule(timerTask {
|
||||
try {
|
||||
admin.lockNow()
|
||||
admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
utils.fire(Trigger.TILE)
|
||||
}, prefs.triggerTileDelay)
|
||||
}
|
||||
else -> {
|
||||
|
|
|
@ -1,27 +1,19 @@
|
|||
package me.lucky.wasted.trigger.usb
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.hardware.usb.UsbManager
|
||||
|
||||
import me.lucky.wasted.Preferences
|
||||
import me.lucky.wasted.Trigger
|
||||
import me.lucky.wasted.admin.DeviceAdminManager
|
||||
import me.lucky.wasted.Utils
|
||||
|
||||
class UsbReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.action != UsbManager.ACTION_USB_DEVICE_ATTACHED &&
|
||||
intent?.action != UsbManager.ACTION_USB_ACCESSORY_ATTACHED) return
|
||||
val prefs = Preferences.new(context ?: return)
|
||||
if (!prefs.isEnabled ||
|
||||
prefs.triggers.and(Trigger.USB.value) == 0 ||
|
||||
!context.getSystemService(KeyguardManager::class.java).isDeviceLocked) return
|
||||
val admin = DeviceAdminManager(context)
|
||||
try {
|
||||
admin.lockNow()
|
||||
if (prefs.isWipeData) admin.wipeData()
|
||||
} catch (exc: SecurityException) {}
|
||||
val utils = Utils(context ?: return)
|
||||
if (!utils.isDeviceLocked()) return
|
||||
utils.fire(Trigger.USB)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragment.RecastFragment">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/enabled"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
android:text="@string/enable" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/recast_description"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/action">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="5dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/receiver"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/receiver">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="5dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/extraKey"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/extra_key">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="5dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/extraValue"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/extra_value">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</FrameLayout>
|
|
@ -29,4 +29,9 @@
|
|||
|
||||
</group>
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_recast"
|
||||
android:title="@string/recast"
|
||||
android:checkable="true" />
|
||||
|
||||
</menu>
|
|
@ -44,4 +44,11 @@
|
|||
<string name="telegram">Telegram</string>
|
||||
<string name="threema">Threema</string>
|
||||
<string name="session">Session</string>
|
||||
<string name="recast">Recast</string>
|
||||
<string name="recast_description">Instead of wipe data you may want to send a broadcast message.</string>
|
||||
<string name="enable">Enable</string>
|
||||
<string name="action">action*</string>
|
||||
<string name="receiver">receiver</string>
|
||||
<string name="extra_key">extra key</string>
|
||||
<string name="extra_value">extra value</string>
|
||||
</resources>
|
|
@ -0,0 +1 @@
|
|||
recast option
|
|
@ -1,5 +1,6 @@
|
|||
You can use PanicKit, tile, shortcut or send a message with a secret code. On trigger, using
|
||||
Device Administration API, it locks a device and optionally runs wipe.
|
||||
Device Administration API, it locks a device and optionally runs wipe (factory reset). Also it can
|
||||
send a broadcast message instead of the wipe.
|
||||
|
||||
Also you can:
|
||||
* fire when a device was not unlocked for X time
|
||||
|
|
Loading…
Reference in New Issue