diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a4e5122..d1c53c7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -53,7 +53,7 @@
-
-
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt
index 8848e3a..6c23bf0 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt
@@ -12,9 +12,9 @@ import android.view.KeyEvent
import android.widget.Toast
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R
-import de.jrpie.android.launcher.actions.LauncherAccessibilityService.Companion.ACTION_LOCK_SCREEN
import de.jrpie.android.launcher.apps.AppFilter
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
+import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.settings.SettingsActivity
@@ -78,7 +78,7 @@ enum class LauncherAction(
"launcher:lockScreen",
R.string.list_other_lock_screen,
R.drawable.baseline_lock_24px,
- LauncherDeviceAdmin::lockScreen
+ { c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) }
),
TORCH(
"launcher:toggleTorch",
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAccessibilityService.kt b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherAccessibilityService.kt
similarity index 55%
rename from app/src/main/java/de/jrpie/android/launcher/actions/LauncherAccessibilityService.kt
rename to app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherAccessibilityService.kt
index bd46dab..969b493 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAccessibilityService.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherAccessibilityService.kt
@@ -1,19 +1,19 @@
-package de.jrpie.android.launcher.actions
+package de.jrpie.android.launcher.actions.lock
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Context
import android.content.Intent
import android.os.Build
-import android.util.Log
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import android.widget.Toast
import androidx.core.content.getSystemService
+import de.jrpie.android.launcher.BuildConfig
import de.jrpie.android.launcher.R
class LauncherAccessibilityService : AccessibilityService() {
- override fun onInterrupt() { }
+ override fun onInterrupt() {}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// Intentionally left blank, we are not interested in any AccessibilityEvents.
@@ -23,11 +23,15 @@ class LauncherAccessibilityService : AccessibilityService() {
companion object {
const val ACTION_LOCK_SCREEN = "ACTION_LOCK_SCREEN"
- private fun lockScreen(context: Context){
+ fun lockScreen(context: Context) {
try {
- context.startService(Intent(context, LauncherAccessibilityService::class.java).apply {
- action = ACTION_LOCK_SCREEN
- })
+ context.startService(
+ Intent(
+ context,
+ LauncherAccessibilityService::class.java
+ ).apply {
+ action = ACTION_LOCK_SCREEN
+ })
} catch (e: Exception) {
Toast.makeText(
context,
@@ -36,19 +40,33 @@ class LauncherAccessibilityService : AccessibilityService() {
).show()
}
}
+
+ fun isEnabled(context: Context): Boolean {
+ val accessibilityManager =
+ context.getSystemService() ?: return false
+ val enabledServices =
+ accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
+ return enabledServices.any {
+ it.id.startsWith(BuildConfig.APPLICATION_ID)
+ }
+ }
+
}
- private fun isServiceEnabled(): Boolean {
- val accessibilityManager = getSystemService() ?: return false
- val enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
- return enabledServices.any { it.id.contains(packageName) }
- }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
intent?.action?.let { action ->
- if (!isServiceEnabled()) {
- Toast.makeText(this, getString(R.string.toast_accessibility_service_not_enabled), Toast.LENGTH_LONG).show()
- startActivity(Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+ if (!isEnabled(this)) {
+ Toast.makeText(
+ this,
+ getString(R.string.toast_accessibility_service_not_enabled),
+ Toast.LENGTH_LONG
+ ).show()
+ startActivity(
+ Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ )
+ )
return START_NOT_STICKY
}
@@ -59,7 +77,7 @@ class LauncherAccessibilityService : AccessibilityService() {
return super.onStartCommand(intent, flags, startId)
}
- private fun handleLockScreen(){
+ private fun handleLockScreen() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
Toast.makeText(
this,
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherDeviceAdmin.kt b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherDeviceAdmin.kt
similarity index 80%
rename from app/src/main/java/de/jrpie/android/launcher/actions/LauncherDeviceAdmin.kt
rename to app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherDeviceAdmin.kt
index d6aa3a2..47c57d2 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherDeviceAdmin.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LauncherDeviceAdmin.kt
@@ -1,4 +1,4 @@
-package de.jrpie.android.launcher.actions
+package de.jrpie.android.launcher.actions.lock
import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
@@ -18,11 +18,17 @@ class LauncherDeviceAdmin : DeviceAdminReceiver() {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN).apply {
putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, getComponentName(context))
- putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
- context.getString(R.string.device_admin_explanation))
+ putExtra(
+ DevicePolicyManager.EXTRA_ADD_EXPLANATION,
+ context.getString(R.string.device_admin_explanation)
+ )
}
context.startActivity(intent)
+ }
+ fun isDeviceAdmin(context: Context): Boolean {
+ val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
+ return dpm.isAdminActive(getComponentName(context))
}
private fun assertDeviceAdmin(context: Context): Boolean {
@@ -36,17 +42,15 @@ class LauncherDeviceAdmin : DeviceAdminReceiver() {
requestDeviceAdmin(context)
return false
}
-
return true
}
fun lockScreen(context: Context) {
+
assertDeviceAdmin(context) || return
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
dpm.lockNow()
}
}
-
-
}
\ No newline at end of file
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt
new file mode 100644
index 0000000..4e1fb15
--- /dev/null
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt
@@ -0,0 +1,74 @@
+package de.jrpie.android.launcher.actions.lock
+
+import android.content.Context
+import android.os.Build
+import android.view.LayoutInflater
+import androidx.appcompat.app.AlertDialog
+import de.jrpie.android.launcher.R
+import de.jrpie.android.launcher.preferences.LauncherPreferences
+
+
+@Suppress("unused")
+enum class LockMethod(
+ private val lock: (Context) -> Unit,
+ private val isEnabled: (Context) -> Boolean,
+ private val enable: (Context) -> Unit
+) {
+ DEVICE_ADMIN(
+ LauncherDeviceAdmin::lockScreen,
+ LauncherDeviceAdmin::isDeviceAdmin,
+ LauncherDeviceAdmin::lockScreen
+ ),
+ ACCESSIBILITY_SERVICE(
+ LauncherAccessibilityService::lockScreen,
+ LauncherAccessibilityService::isEnabled,
+ LauncherAccessibilityService::lockScreen
+ ),
+ ;
+
+ fun lockOrEnable(context: Context) {
+ if (!this.isEnabled(context)) {
+ chooseMethod(context)
+ return
+ }
+ this.lock(context)
+ }
+
+ companion object {
+ fun chooseMethod(context: Context) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
+ // only device admin is available
+ setMethod(context, DEVICE_ADMIN)
+ return
+ }
+ val builder = AlertDialog.Builder(context, R.style.AlertDialogCustom)
+ builder.setNegativeButton("cancel") { _, _ -> }
+ builder.setCustomTitle(
+ LayoutInflater.from(context).inflate(R.layout.dialog_select_lock_method, null)
+ )
+
+ builder.setItems(
+ arrayOf(
+ context.getString(R.string.screen_lock_method_use_accessibility),
+ context.getString(R.string.screen_lock_method_use_device_admin)
+ )
+ ) { _, i ->
+ val method = when (i) {
+ 0 -> ACCESSIBILITY_SERVICE
+ 1 -> DEVICE_ADMIN
+ else -> return@setItems
+ }
+ setMethod(context, method)
+ }
+ builder.show()
+
+ return
+ }
+
+ private fun setMethod(context: Context, m: LockMethod) {
+ LauncherPreferences.actions().lockMethod(m)
+ if (!m.isEnabled(context))
+ m.enable(context)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java
index 904893b..c876fc3 100644
--- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java
+++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java
@@ -5,6 +5,7 @@ import java.util.Set;
import de.jrpie.android.launcher.R;
import de.jrpie.android.launcher.apps.AppInfo;
+import de.jrpie.android.launcher.actions.lock.LockMethod;
import de.jrpie.android.launcher.preferences.theme.Background;
import de.jrpie.android.launcher.preferences.theme.ColorTheme;
import de.jrpie.android.launcher.preferences.theme.Font;
@@ -62,6 +63,9 @@ import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSeriali
@Preference(name = "edge_swipe", type = boolean.class, defaultValue = "true"),
@Preference(name = "edge_swipe_edge_width", type = int.class, defaultValue = "15"),
}),
+ @PreferenceGroup(name = "actions", prefix = "settings_actions_", suffix = "_key", value = {
+ @Preference(name = "lock_method", type = LockMethod.class, defaultValue = "DEVICE_ADMIN"),
+ }),
})
public final class LauncherPreferences$Config {
public static class AppInfoSetSerializer implements PreferenceSerializer, Set> {
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt
index 1c6e0df..f945b5a 100644
--- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt
@@ -7,6 +7,7 @@ import androidx.preference.PreferenceFragmentCompat
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.actions.openAppsList
import de.jrpie.android.launcher.preferences.LauncherPreferences
+import de.jrpie.android.launcher.actions.lock.LockMethod
import de.jrpie.android.launcher.setDefaultHomeScreen
@@ -74,6 +75,15 @@ class SettingsFragmentLauncher : PreferenceFragmentCompat() {
openAppsList(requireContext(), favorite = false, hidden = true)
true
}
+
+ val lockMethod = findPreference(
+ LauncherPreferences.actions().keys().lockMethod()
+ )
+
+ lockMethod?.setOnPreferenceClickListener {
+ LockMethod.chooseMethod(requireContext())
+ true
+ }
updateVisibility()
}
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt
new file mode 100644
index 0000000..549f10f
--- /dev/null
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt
@@ -0,0 +1,18 @@
+package de.jrpie.android.launcher.ui.util
+
+import android.content.Context
+import android.text.Html
+import android.text.method.LinkMovementMethod
+import android.util.AttributeSet
+import androidx.appcompat.widget.AppCompatTextView
+
+class HtmlTextView(context: Context, attr: AttributeSet?, int: Int) :
+ AppCompatTextView(context, attr, int) {
+ constructor(context: Context, attr: AttributeSet?) : this(context, attr, 0)
+ constructor(context: Context) : this(context, null, 0)
+
+ init {
+ text = Html.fromHtml(text.toString())
+ movementMethod = LinkMovementMethod.getInstance()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_select_lock_method.xml b/app/src/main/res/layout/dialog_select_lock_method.xml
new file mode 100644
index 0000000..8f19e45
--- /dev/null
+++ b/app/src/main/res/layout/dialog_select_lock_method.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml
index f81eca0..d3cac4b 100644
--- a/app/src/main/res/values/donottranslate.xml
+++ b/app/src/main/res/values/donottranslate.xml
@@ -102,6 +102,8 @@
functionality.search_auto_keyboard
+ settings_action_lock_method
+