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
|
You can use [PanicKit](https://guardianproject.info/code/panickit/), tile, shortcut or send a
|
||||||
message with a secret code. On trigger, using
|
message with a secret code. On trigger, using
|
||||||
[Device Administration API](https://developer.android.com/guide/topics/admin/device-admin), it
|
[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:
|
Also you can:
|
||||||
* fire when a device was not unlocked for X time
|
* fire when a device was not unlocked for X time
|
||||||
|
|
|
@ -10,8 +10,8 @@ android {
|
||||||
applicationId "me.lucky.wasted"
|
applicationId "me.lucky.wasted"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 32
|
targetSdk 32
|
||||||
versionCode 38
|
versionCode 39
|
||||||
versionName "1.5.9"
|
versionName "1.5.10"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ open class MainActivity : AppCompatActivity() {
|
||||||
R.id.nav_trigger_notification -> NotificationFragment()
|
R.id.nav_trigger_notification -> NotificationFragment()
|
||||||
R.id.nav_trigger_lock -> LockFragment()
|
R.id.nav_trigger_lock -> LockFragment()
|
||||||
R.id.nav_trigger_application -> ApplicationFragment()
|
R.id.nav_trigger_application -> ApplicationFragment()
|
||||||
R.id.top_settings -> SettingsFragment()
|
R.id.nav_recast -> RecastFragment()
|
||||||
else -> MainFragment()
|
else -> MainFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@ class Preferences(ctx: Context, encrypted: Boolean = true) {
|
||||||
private const val WIPE_DATA = "wipe_data"
|
private const val WIPE_DATA = "wipe_data"
|
||||||
private const val WIPE_EMBEDDED_SIM = "wipe_embedded_sim"
|
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 TRIGGERS = "triggers"
|
||||||
private const val TRIGGER_LOCK_COUNT = "trigger_lock_count"
|
private const val TRIGGER_LOCK_COUNT = "trigger_lock_count"
|
||||||
private const val TRIGGER_TILE_DELAY = "trigger_tile_delay"
|
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)
|
get() = prefs.getInt(TRIGGER_APPLICATION_OPTIONS, 0)
|
||||||
set(value) = prefs.edit { putInt(TRIGGER_APPLICATION_OPTIONS, value) }
|
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) =
|
fun registerListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) =
|
||||||
prefs.registerOnSharedPreferenceChangeListener(listener)
|
prefs.registerOnSharedPreferenceChangeListener(listener)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package me.lucky.wasted
|
package me.lucky.wasted
|
||||||
|
|
||||||
|
import android.app.KeyguardManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -7,6 +8,7 @@ import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
|
import me.lucky.wasted.admin.DeviceAdminManager
|
||||||
import me.lucky.wasted.trigger.notification.NotificationListenerService
|
import me.lucky.wasted.trigger.notification.NotificationListenerService
|
||||||
import me.lucky.wasted.trigger.panic.PanicConnectionActivity
|
import me.lucky.wasted.trigger.panic.PanicConnectionActivity
|
||||||
import me.lucky.wasted.trigger.panic.PanicResponderActivity
|
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) {
|
fun setEnabled(enabled: Boolean) {
|
||||||
val triggers = Preferences(ctx).triggers
|
val triggers = prefs.triggers
|
||||||
setPanicKitEnabled(enabled && triggers.and(Trigger.PANIC_KIT.value) != 0)
|
setPanicKitEnabled(enabled && triggers.and(Trigger.PANIC_KIT.value) != 0)
|
||||||
setTileEnabled(enabled && triggers.and(Trigger.TILE.value) != 0)
|
setTileEnabled(enabled && triggers.and(Trigger.TILE.value) != 0)
|
||||||
setShortcutEnabled(enabled && triggers.and(Trigger.SHORTCUT.value) != 0)
|
setShortcutEnabled(enabled && triggers.and(Trigger.SHORTCUT.value) != 0)
|
||||||
|
@ -50,6 +52,7 @@ class Utils(private val ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setShortcutEnabled(enabled: Boolean) {
|
fun setShortcutEnabled(enabled: Boolean) {
|
||||||
|
val shortcut = ShortcutManager(ctx)
|
||||||
if (!enabled) shortcut.remove()
|
if (!enabled) shortcut.remove()
|
||||||
setComponentEnabled(ShortcutActivity::class.java, enabled)
|
setComponentEnabled(ShortcutActivity::class.java, enabled)
|
||||||
if (enabled) shortcut.push()
|
if (enabled) shortcut.push()
|
||||||
|
@ -63,7 +66,6 @@ class Utils(private val ctx: Context) {
|
||||||
|
|
||||||
fun updateApplicationEnabled() {
|
fun updateApplicationEnabled() {
|
||||||
val prefix = "${ctx.packageName}.trigger.application"
|
val prefix = "${ctx.packageName}.trigger.application"
|
||||||
val prefs = Preferences(ctx)
|
|
||||||
val options = prefs.triggerApplicationOptions
|
val options = prefs.triggerApplicationOptions
|
||||||
val enabled = prefs.isEnabled && prefs.triggers.and(Trigger.APPLICATION.value) != 0
|
val enabled = prefs.isEnabled && prefs.triggers.and(Trigger.APPLICATION.value) != 0
|
||||||
setComponentEnabled(
|
setComponentEnabled(
|
||||||
|
@ -85,7 +87,6 @@ class Utils(private val ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateForegroundRequiredEnabled() {
|
fun updateForegroundRequiredEnabled() {
|
||||||
val prefs = Preferences(ctx)
|
|
||||||
val enabled = prefs.isEnabled
|
val enabled = prefs.isEnabled
|
||||||
val triggers = prefs.triggers
|
val triggers = prefs.triggers
|
||||||
val isUSB = triggers.and(Trigger.USB.value) != 0
|
val isUSB = triggers.and(Trigger.USB.value) != 0
|
||||||
|
@ -114,4 +115,36 @@ class Utils(private val ctx: Context) {
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||||
PackageManager.DONT_KILL_APP,
|
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 android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
|
||||||
import me.lucky.wasted.Preferences
|
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class ApplicationActivity : AppCompatActivity() {
|
class ApplicationActivity : AppCompatActivity() {
|
||||||
private val prefs by lazy { Preferences(this) }
|
|
||||||
private val admin by lazy { DeviceAdminManager(this) }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (!prefs.isEnabled || prefs.triggers.and(Trigger.APPLICATION.value) == 0) {
|
Utils(this).fire(Trigger.APPLICATION)
|
||||||
finishAndRemoveTask()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
admin.lockNow()
|
|
||||||
if (prefs.isWipeData) admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
finishAndRemoveTask()
|
finishAndRemoveTask()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,30 +6,23 @@ import android.content.Intent
|
||||||
|
|
||||||
import me.lucky.wasted.Preferences
|
import me.lucky.wasted.Preferences
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class BroadcastReceiver : BroadcastReceiver() {
|
class BroadcastReceiver : BroadcastReceiver() {
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY = "code"
|
const val KEY = "code"
|
||||||
const val ACTION = "me.lucky.wasted.action.TRIGGER"
|
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
|
if (intent?.action != ACTION) return
|
||||||
val prefs = Preferences.new(context)
|
val secret = Preferences.new(context).secret
|
||||||
if (!prefs.isEnabled) return
|
|
||||||
val secret = prefs.secret
|
|
||||||
assert(secret.isNotEmpty())
|
assert(secret.isNotEmpty())
|
||||||
if (intent.getStringExtra(KEY)?.trim() != secret) return
|
if (intent.getStringExtra(KEY)?.trim() != secret) return
|
||||||
val admin = DeviceAdminManager(context)
|
Utils(context).fire(trigger)
|
||||||
try {
|
|
||||||
admin.lockNow()
|
|
||||||
if (prefs.isWipeData) admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (Preferences.new(context ?: return).triggers.and(Trigger.BROADCAST.value) != 0)
|
panic(context ?: return, intent, Trigger.BROADCAST)
|
||||||
panic(context, intent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,19 +3,12 @@ package me.lucky.wasted.trigger.lock
|
||||||
import android.app.job.JobParameters
|
import android.app.job.JobParameters
|
||||||
import android.app.job.JobService
|
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.Trigger
|
||||||
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class LockJobService : JobService() {
|
class LockJobService : JobService() {
|
||||||
override fun onStartJob(params: JobParameters?): Boolean {
|
override fun onStartJob(params: JobParameters?): Boolean {
|
||||||
val prefs = Preferences.new(this)
|
Utils(this).fire(Trigger.LOCK)
|
||||||
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) {}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,13 @@ import android.os.Build
|
||||||
import android.service.notification.NotificationListenerService
|
import android.service.notification.NotificationListenerService
|
||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
|
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
|
||||||
import me.lucky.wasted.Preferences
|
import me.lucky.wasted.Preferences
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class NotificationListenerService : NotificationListenerService() {
|
class NotificationListenerService : NotificationListenerService() {
|
||||||
private lateinit var prefs: Preferences
|
private lateinit var prefs: Preferences
|
||||||
private lateinit var admin: DeviceAdminManager
|
private lateinit var utils: Utils
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
@ -20,22 +20,17 @@ class NotificationListenerService : NotificationListenerService() {
|
||||||
|
|
||||||
private fun init() {
|
private fun init() {
|
||||||
prefs = Preferences.new(this)
|
prefs = Preferences.new(this)
|
||||||
admin = DeviceAdminManager(this)
|
utils = Utils(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||||
super.onNotificationPosted(sbn)
|
super.onNotificationPosted(sbn)
|
||||||
if (sbn == null ||
|
if (sbn == null) return
|
||||||
!prefs.isEnabled ||
|
|
||||||
prefs.triggers.and(Trigger.NOTIFICATION.value) == 0) return
|
|
||||||
val secret = prefs.secret
|
val secret = prefs.secret
|
||||||
assert(secret.isNotEmpty())
|
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()
|
cancelAllNotifications()
|
||||||
try {
|
utils.fire(Trigger.NOTIFICATION)
|
||||||
admin.lockNow()
|
|
||||||
if (prefs.isWipeData) admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onListenerConnected() {
|
override fun onListenerConnected() {
|
||||||
|
|
|
@ -5,28 +5,20 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
|
|
||||||
import info.guardianproject.panic.Panic
|
import info.guardianproject.panic.Panic
|
||||||
import info.guardianproject.panic.PanicResponder
|
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.Trigger
|
||||||
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class PanicResponderActivity : AppCompatActivity() {
|
class PanicResponderActivity : AppCompatActivity() {
|
||||||
private val prefs by lazy { Preferences.new(this) }
|
|
||||||
private val admin by lazy { DeviceAdminManager(this) }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (!Panic.isTriggerIntent(intent) ||
|
if (!Panic.isTriggerIntent(intent)) {
|
||||||
!prefs.isEnabled ||
|
|
||||||
prefs.triggers.and(Trigger.PANIC_KIT.value) == 0)
|
|
||||||
{
|
|
||||||
finishAndRemoveTask()
|
finishAndRemoveTask()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
Utils(this).fire(
|
||||||
admin.lockNow()
|
Trigger.PANIC_KIT,
|
||||||
if (PanicResponder.receivedTriggerFromConnectedApp(this) &&
|
PanicResponder.receivedTriggerFromConnectedApp(this),
|
||||||
prefs.isWipeData) admin.wipeData()
|
)
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
finishAndRemoveTask()
|
finishAndRemoveTask()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ import androidx.core.app.NotificationCompat
|
||||||
import me.lucky.wasted.Preferences
|
import me.lucky.wasted.Preferences
|
||||||
import me.lucky.wasted.R
|
import me.lucky.wasted.R
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
import me.lucky.wasted.Utils
|
||||||
import me.lucky.wasted.trigger.lock.LockJobManager
|
import me.lucky.wasted.trigger.lock.LockJobManager
|
||||||
|
|
||||||
class ForegroundService : Service() {
|
class ForegroundService : Service() {
|
||||||
|
@ -113,17 +113,11 @@ class ForegroundService : Service() {
|
||||||
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (intent?.action != ACTION_USB_STATE) return
|
if (intent?.action != ACTION_USB_STATE) return
|
||||||
val prefs = Preferences.new(context ?: return)
|
val utils = Utils(context ?: return)
|
||||||
if (!prefs.isEnabled ||
|
if (!utils.isDeviceLocked()) return
|
||||||
prefs.triggers.and(Trigger.USB.value) == 0 ||
|
|
||||||
!context.getSystemService(KeyguardManager::class.java).isDeviceLocked) return
|
|
||||||
val extras = intent.extras ?: return
|
val extras = intent.extras ?: return
|
||||||
if (!extras.getBoolean(KEY_1) && !extras.getBoolean(KEY_2)) return
|
if (!extras.getBoolean(KEY_1) && !extras.getBoolean(KEY_2)) return
|
||||||
val admin = DeviceAdminManager(context)
|
utils.fire(Trigger.USB)
|
||||||
try {
|
|
||||||
admin.lockNow()
|
|
||||||
if (prefs.isWipeData) admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,15 +3,13 @@ package me.lucky.wasted.trigger.shortcut
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
|
||||||
import me.lucky.wasted.Preferences
|
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
import me.lucky.wasted.trigger.broadcast.BroadcastReceiver
|
import me.lucky.wasted.trigger.broadcast.BroadcastReceiver
|
||||||
|
|
||||||
class ShortcutActivity : AppCompatActivity() {
|
class ShortcutActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (Preferences(this).triggers.and(Trigger.SHORTCUT.value) != 0)
|
BroadcastReceiver.panic(this, intent, Trigger.SHORTCUT)
|
||||||
BroadcastReceiver.panic(this, intent)
|
|
||||||
finishAndRemoveTask()
|
finishAndRemoveTask()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,11 +10,13 @@ import kotlin.concurrent.timerTask
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
import me.lucky.wasted.admin.DeviceAdminManager
|
||||||
import me.lucky.wasted.Preferences
|
import me.lucky.wasted.Preferences
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
class TileService : TileService() {
|
class TileService : TileService() {
|
||||||
private lateinit var prefs: Preferences
|
private lateinit var prefs: Preferences
|
||||||
private lateinit var admin: DeviceAdminManager
|
private lateinit var admin: DeviceAdminManager
|
||||||
|
private lateinit var utils: Utils
|
||||||
private var counter = 0
|
private var counter = 0
|
||||||
private var timer: Timer? = null
|
private var timer: Timer? = null
|
||||||
|
|
||||||
|
@ -26,6 +28,7 @@ class TileService : TileService() {
|
||||||
private fun init() {
|
private fun init() {
|
||||||
prefs = Preferences.new(this)
|
prefs = Preferences.new(this)
|
||||||
admin = DeviceAdminManager(this)
|
admin = DeviceAdminManager(this)
|
||||||
|
utils = Utils(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartListening() {
|
override fun onStartListening() {
|
||||||
|
@ -38,11 +41,8 @@ class TileService : TileService() {
|
||||||
|
|
||||||
override fun onClick() {
|
override fun onClick() {
|
||||||
super.onClick()
|
super.onClick()
|
||||||
if (!prefs.isEnabled || prefs.triggers.and(Trigger.TILE.value) == 0) return
|
|
||||||
if (!prefs.isWipeData) {
|
if (!prefs.isWipeData) {
|
||||||
try {
|
utils.fire(Trigger.TILE, false)
|
||||||
admin.lockNow()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val v = counter
|
val v = counter
|
||||||
|
@ -53,10 +53,7 @@ class TileService : TileService() {
|
||||||
timer?.cancel()
|
timer?.cancel()
|
||||||
timer = Timer()
|
timer = Timer()
|
||||||
timer?.schedule(timerTask {
|
timer?.schedule(timerTask {
|
||||||
try {
|
utils.fire(Trigger.TILE)
|
||||||
admin.lockNow()
|
|
||||||
admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
}, prefs.triggerTileDelay)
|
}, prefs.triggerTileDelay)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
package me.lucky.wasted.trigger.usb
|
package me.lucky.wasted.trigger.usb
|
||||||
|
|
||||||
import android.app.KeyguardManager
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.hardware.usb.UsbManager
|
import android.hardware.usb.UsbManager
|
||||||
|
|
||||||
import me.lucky.wasted.Preferences
|
|
||||||
import me.lucky.wasted.Trigger
|
import me.lucky.wasted.Trigger
|
||||||
import me.lucky.wasted.admin.DeviceAdminManager
|
import me.lucky.wasted.Utils
|
||||||
|
|
||||||
class UsbReceiver : BroadcastReceiver() {
|
class UsbReceiver : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (intent?.action != UsbManager.ACTION_USB_DEVICE_ATTACHED &&
|
if (intent?.action != UsbManager.ACTION_USB_DEVICE_ATTACHED &&
|
||||||
intent?.action != UsbManager.ACTION_USB_ACCESSORY_ATTACHED) return
|
intent?.action != UsbManager.ACTION_USB_ACCESSORY_ATTACHED) return
|
||||||
val prefs = Preferences.new(context ?: return)
|
val utils = Utils(context ?: return)
|
||||||
if (!prefs.isEnabled ||
|
if (!utils.isDeviceLocked()) return
|
||||||
prefs.triggers.and(Trigger.USB.value) == 0 ||
|
utils.fire(Trigger.USB)
|
||||||
!context.getSystemService(KeyguardManager::class.java).isDeviceLocked) return
|
|
||||||
val admin = DeviceAdminManager(context)
|
|
||||||
try {
|
|
||||||
admin.lockNow()
|
|
||||||
if (prefs.isWipeData) admin.wipeData()
|
|
||||||
} catch (exc: SecurityException) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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>
|
</group>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_recast"
|
||||||
|
android:title="@string/recast"
|
||||||
|
android:checkable="true" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
|
@ -44,4 +44,11 @@
|
||||||
<string name="telegram">Telegram</string>
|
<string name="telegram">Telegram</string>
|
||||||
<string name="threema">Threema</string>
|
<string name="threema">Threema</string>
|
||||||
<string name="session">Session</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>
|
</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
|
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:
|
Also you can:
|
||||||
* fire when a device was not unlocked for X time
|
* fire when a device was not unlocked for X time
|
||||||
|
|
Loading…
Reference in New Issue