lock screen: use device admin instead of accessibility service

This commit is contained in:
Josia Pietsch 2024-11-01 21:35:31 +01:00
parent 3c73a7f49d
commit 3423534085
Signed by: jrpie
GPG key ID: E70B571D66986A2D
7 changed files with 80 additions and 96 deletions

View file

@ -52,17 +52,18 @@
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".actions.LauncherAccessibilityService"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
</application>
<receiver android:name=".actions.LauncherDeviceAdmin"
android:exported="true"
android:label="@string/app_name"
android:description="@string/device_admin_description"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="@xml/device_admin_config" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
</manifest> </manifest>

View file

@ -1,51 +0,0 @@
package de.jrpie.android.launcher.actions
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Intent
import android.os.Build
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import android.widget.Toast
import androidx.core.content.getSystemService
import de.jrpie.android.launcher.R
class LauncherAccessibilityService : AccessibilityService() {
override fun onInterrupt() {
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
}
companion object {
const val ACTION_LOCK_SCREEN = "ACTION_LOCK_SCREEN"
}
private fun isServiceEnabled(): Boolean {
val accessibilityManager = getSystemService<AccessibilityManager>() ?: 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))
return START_NOT_STICKY
}
when (action) {
ACTION_LOCK_SCREEN -> handleLockScreen()
}
}
return super.onStartCommand(intent, flags, startId)
}
private fun handleLockScreen(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN)
} else {
Toast.makeText(this, getText(R.string.toast_lock_screen_not_supported), Toast.LENGTH_SHORT).show()
}
}
}

View file

@ -10,7 +10,6 @@ import android.os.SystemClock
import android.view.KeyEvent import android.view.KeyEvent
import android.widget.Toast import android.widget.Toast
import de.jrpie.android.launcher.R 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.AppFilter
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
import de.jrpie.android.launcher.ui.list.ListActivity import de.jrpie.android.launcher.ui.list.ListActivity
@ -76,7 +75,7 @@ enum class LauncherAction(
"launcher:lockScreen", "launcher:lockScreen",
R.string.list_other_lock_screen, R.string.list_other_lock_screen,
R.drawable.baseline_lock_24px, R.drawable.baseline_lock_24px,
::lockScreen LauncherDeviceAdmin::lockScreen
), ),
NOP("launcher:nop", R.string.list_other_nop, R.drawable.baseline_not_interested_24, {}); NOP("launcher:nop", R.string.list_other_nop, R.drawable.baseline_not_interested_24, {});
@ -206,20 +205,6 @@ private fun expandSettingsPanel(context: Context) {
} }
} }
private fun lockScreen(context: Context){
try {
context.startService(Intent(context, LauncherAccessibilityService::class.java).apply {
action = ACTION_LOCK_SCREEN
})
} catch (e: Exception) {
Toast.makeText(
context,
context.getString(R.string.alert_lock_screen_failed),
Toast.LENGTH_LONG
).show()
}
}
private fun openSettings(context: Context) { private fun openSettings(context: Context) {
context.startActivity(Intent(context, SettingsActivity::class.java)) context.startActivity(Intent(context, SettingsActivity::class.java))
} }

View file

@ -0,0 +1,53 @@
package de.jrpie.android.launcher.actions
import android.app.Activity
import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.widget.Toast
import de.jrpie.android.launcher.R
class LauncherDeviceAdmin : DeviceAdminReceiver() {
companion object {
private fun getComponentName(context: Context): ComponentName {
return ComponentName(context, LauncherDeviceAdmin::class.java)
}
private fun requestDeviceAdmin(context: Context) {
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))
}
context.startActivity(intent)
}
private fun assertDeviceAdmin(context: Context): Boolean {
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if (!dpm.isAdminActive(getComponentName(context))) {
Toast.makeText(
context,
context.getString(R.string.toast_device_admin_not_enabled),
Toast.LENGTH_LONG
).show()
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()
}
}
}

View file

@ -1,5 +1,4 @@
<resources> <resources>
<string name="accessibility_service_description">Enable lock screen action</string>
<!-- <!--
- -
- Home - Home
@ -7,12 +6,8 @@
--> -->
<string name="alert_cant_open_title">Can\'t open app</string> <string name="alert_cant_open_title">Can\'t open app</string>
<string name="alert_cant_open_message">Want to change its settings?</string> <string name="alert_cant_open_message">Want to change its settings?</string>
<string name="alert_lock_screen_failed">Failed to lock screen</string>
<string name="toast_cant_open_message">Open settings to choose an action for this gesture</string> <string name="toast_cant_open_message">Open settings to choose an action for this gesture</string>
<string name="toast_accessibility_service_not_enabled">μLauncher\'s accessibility service is not enabled. Please enable it in settings</string>
<string name="toast_lock_screen_not_supported">Sorry, lock screen is available on Android 9+</string>
<!-- <!--
- -
@ -207,11 +202,13 @@
<string name="tutorial_finish_button">Start</string> <string name="tutorial_finish_button">Start</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="ic_menu_alt">More options</string> <string name="ic_menu_alt">More options</string>
<string name="alert_cant_expand_status_bar_panel">Error: Can\'t expand status bar.\nThis action is using functionality that is not part of the published Android API. Unfortunately, it does not seem to work on your device.</string> <string name="alert_cant_expand_status_bar_panel">Error: Can\'t expand status bar.\nThis action is using functionality that is not part of the published Android API. Unfortunately, it does not seem to work on your device.</string>
<string name="snackbar_app_hidden">App hidden. You can make it visible again in settings.</string> <string name="snackbar_app_hidden">App hidden. You can make it visible again in settings.</string>
<string name="undo">Undo</string> <string name="undo">Undo</string>
<string name="list_other_expand_settings_panel">Quick Settings</string> <string name="list_other_expand_settings_panel">Quick Settings</string>
<string name="toast_device_admin_not_enabled">µLauncher needs to be a device admin in order to lock the screen.</string>
<string name="device_admin_explanation">This is required for the lock screen action.</string>
<string name="device_admin_description">Enable the lock screen action</string>
</resources> </resources>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault"
android:description="@string/accessibility_service_description"
/>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<force-lock />
</uses-policies>
</device-admin>