Skip to content

Commit f4f8eec

Browse files
refactor(auth): Implement Device Admin for screen lock
This commit refactors the screen lock functionality to prioritize using the Device Administrator API, which is more stable than the Accessibility Service method. Key changes include: - A new `DeviceAdmin` receiver to handle device admin enabling/disabling. - Updated `lockPhone` logic in `HomeFragment` to check for and use Device Admin permissions first. - If Device Admin is not enabled, the system will prompt the user to grant permission. - The Accessibility Service (`ActionService`) is now a fallback method for locking the screen. - Necessary permissions and receiver declarations have been added to `AndroidManifest.xml`. - XML configuration for the Device Admin receiver has been created.
1 parent 20fbeb0 commit f4f8eec

File tree

5 files changed

+95
-33
lines changed

5 files changed

+95
-33
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,11 @@
33
xmlns:dist="http://schemas.android.com/apk/distribution"
44
xmlns:tools="http://schemas.android.com/tools">
55
<!-- Enable instant apps (optional) -->
6-
<dist:module dist:instant="true" /> <!-- Permissions your launcher uses -->
6+
<dist:module dist:instant="true" />
7+
<!-- Permissions your launcher uses -->
78
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
8-
<uses-permission
9-
android:name="android.permission.PACKAGE_USAGE_STATS"
10-
tools:ignore="ProtectedPermissions" />
11-
<uses-permission
12-
android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
13-
tools:ignore="ProtectedPermissions" />
14-
<uses-permission
15-
android:name="android.permission.QUERY_ALL_PACKAGES"
16-
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
9+
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
10+
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
1711
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
1812
<uses-permission android:name="android.permission.ACCESS_HIDDEN_PROFILES" />
1913
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
@@ -23,15 +17,8 @@
2317
<uses-permission android:name="android.permission.READ_CONTACTS" />
2418
<uses-permission android:name="android.permission.SET_WALLPAPER" />
2519
<uses-permission android:name="android.permission.VIBRATE" />
26-
<uses-permission
27-
android:name="android.permission.BIND_APPWIDGET"
28-
tools:ignore="ProtectedPermissions" />
29-
<uses-permission
30-
android:name="android.permission.BIND_REMOTEVIEWS"
31-
tools:ignore="ProtectedPermissions" />
32-
<uses-permission
33-
android:name="android.permission.FOREGROUND_SERVICE"
34-
tools:ignore="ForegroundServicesPolicy" />
20+
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
21+
<uses-permission android:name="android.permission.BIND_REMOTEVIEWS" />
3522
<uses-permission android:name="android.permission.INTERNET" />
3623

3724
<application
@@ -59,12 +46,14 @@
5946
<meta-data
6047
android:name="android.support.FILE_PROVIDER_PATHS"
6148
android:resource="@xml/file_paths" />
62-
</provider> <!-- Init provider to run early initialization code -->
49+
</provider>
50+
<!-- Init provider to run early initialization code -->
6351
<provider
6452
android:name=".init.MlauncherInitProvider"
6553
android:authorities="${applicationId}.mlauncher.initprovider"
6654
android:exported="false"
67-
android:initOrder="100" /> <!-- MAIN LAUNCHER ACTIVITY -->
55+
android:initOrder="100" />
56+
<!-- MAIN LAUNCHER ACTIVITY -->
6857
<activity
6958
android:name=".MainActivity"
7059
android:excludeFromRecents="true"
@@ -79,18 +68,21 @@
7968
<category android:name="android.intent.category.DEFAULT" />
8069
<category android:name="android.intent.category.LAUNCHER" />
8170
</intent-filter>
82-
</activity> <!-- ONBOARDING ACTIVITY -->
71+
</activity>
72+
<!-- ONBOARDING ACTIVITY -->
8373
<activity
8474
android:name=".ui.onboarding.OnboardingActivity"
8575
android:enabled="true"
8676
android:excludeFromRecents="true"
8777
android:exported="false"
88-
android:launchMode="singleTask" /> <!-- CRASH REPORT ACTIVITY -->
78+
android:launchMode="singleTask" />
79+
<!-- CRASH REPORT ACTIVITY -->
8980
<activity
9081
android:name=".CrashReportActivity"
9182
android:enabled="true"
9283
android:excludeFromRecents="true"
93-
android:exported="false" /> <!-- ICON PACK ACTIVITIES -->
84+
android:exported="false" />
85+
<!-- ICON PACK ACTIVITIES -->
9486
<activity
9587
android:name=".ui.iconpack.ApplyIconPackActivity"
9688
android:excludeFromRecents="true"
@@ -104,7 +96,8 @@
10496
<activity
10597
android:name=".ui.iconpack.CustomIconSelectionActivity"
10698
android:excludeFromRecents="true"
107-
android:exported="false" /> <!-- Accessibility Service -->
99+
android:exported="false" />
100+
<!-- Accessibility Service -->
108101
<service
109102
android:name=".services.ActionService"
110103
android:enabled="true"
@@ -119,7 +112,8 @@
119112
<meta-data
120113
android:name="android.accessibilityservice"
121114
android:resource="@xml/accessibility_service_config" />
122-
</service> <!-- Notification Manager -->
115+
</service>
116+
<!-- Notification Manager -->
123117
<service
124118
android:name=".listener.NotificationManager"
125119
android:enabled="true"
@@ -130,6 +124,21 @@
130124
<action android:name="android.service.notification.NotificationListenerService" />
131125
</intent-filter>
132126
</service>
127+
<!-- Device Admin Receiver -->
128+
<receiver
129+
android:name=".helper.receivers.DeviceAdmin"
130+
android:exported="true"
131+
android:permission="android.permission.BIND_DEVICE_ADMIN">
132+
133+
<meta-data
134+
android:name="android.app.device_admin"
135+
android:resource="@xml/device_admin_receiver" />
136+
137+
<intent-filter>
138+
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
139+
</intent-filter>
140+
</receiver>
141+
133142

134143
<receiver
135144
android:name=".ui.widgets.wordoftheday.WordOfTheDayWidget"
@@ -145,8 +154,7 @@
145154
</receiver>
146155
<receiver
147156
android:name=".ui.widgets.wordoftheday.WordOfTheDayUpdateReceiver"
148-
android:exported="false"
149-
tools:ignore="Instantiatable" />
157+
android:exported="false" />
150158
<receiver
151159
android:name=".ui.widgets.fab.FabWidget"
152160
android:exported="false"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.github.droidworksstudio.mlauncher.helper.receivers
2+
3+
import android.app.admin.DeviceAdminReceiver
4+
import android.content.Context
5+
import android.content.Intent
6+
import android.os.Handler
7+
import android.os.Looper
8+
import com.github.droidworksstudio.common.AppLogger
9+
import com.github.droidworksstudio.common.showShortToast
10+
11+
class DeviceAdmin : DeviceAdminReceiver() {
12+
override fun onEnabled(context: Context, intent: Intent) {
13+
Handler(Looper.getMainLooper()).post {
14+
AppLogger.d("DeviceAdminReceiver", "Device Admin Enabled")
15+
context.showShortToast("Device Admin Enabled")
16+
}
17+
}
18+
19+
override fun onDisabled(context: Context, intent: Intent) {
20+
Handler(Looper.getMainLooper()).post {
21+
AppLogger.d("DeviceAdminReceiver", "Device Admin Disabled")
22+
context.showShortToast("Device Admin Disabled")
23+
}
24+
}
25+
}

app/src/main/java/com/github/droidworksstudio/mlauncher/services/ActionService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.droidworksstudio.mlauncher.services
22

33
import android.accessibilityservice.AccessibilityService
4+
import android.annotation.SuppressLint
45
import android.content.Context
56
import android.content.Intent
67
import android.content.pm.PackageManager
@@ -9,6 +10,7 @@ import com.github.droidworksstudio.common.AppLogger
910
import com.github.droidworksstudio.common.CrashHandler
1011
import java.lang.ref.WeakReference
1112

13+
@SuppressLint("AccessibilityPolicy")
1214
class ActionService : AccessibilityService() {
1315
private var suppressEventsUntil = 0L
1416

app/src/main/java/com/github/droidworksstudio/mlauncher/ui/HomeFragment.kt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.droidworksstudio.mlauncher.ui
22

33
import android.annotation.SuppressLint
44
import android.app.admin.DevicePolicyManager
5+
import android.content.ComponentName
56
import android.content.Context
67
import android.content.Context.VIBRATOR_SERVICE
78
import android.content.Intent
@@ -45,7 +46,6 @@ import com.github.droidworksstudio.common.attachGestureManager
4546
import com.github.droidworksstudio.common.getLocalizedString
4647
import com.github.droidworksstudio.common.isGestureNavigationEnabled
4748
import com.github.droidworksstudio.common.launchCalendar
48-
import com.github.droidworksstudio.common.openAccessibilitySettings
4949
import com.github.droidworksstudio.common.openAlarmApp
5050
import com.github.droidworksstudio.common.openBatteryManager
5151
import com.github.droidworksstudio.common.openCameraApp
@@ -76,6 +76,7 @@ import com.github.droidworksstudio.mlauncher.helper.hasUsageAccessPermission
7676
import com.github.droidworksstudio.mlauncher.helper.initActionService
7777
import com.github.droidworksstudio.mlauncher.helper.ismlauncherDefault
7878
import com.github.droidworksstudio.mlauncher.helper.receivers.BatteryReceiver
79+
import com.github.droidworksstudio.mlauncher.helper.receivers.DeviceAdmin
7980
import com.github.droidworksstudio.mlauncher.helper.receivers.PrivateSpaceReceiver
8081
import com.github.droidworksstudio.mlauncher.helper.setTopPadding
8182
import com.github.droidworksstudio.mlauncher.helper.showPermissionDialog
@@ -743,14 +744,33 @@ class HomeFragment : BaseFragment(), View.OnClickListener, View.OnLongClickListe
743744
}
744745

745746
private fun lockPhone() {
747+
val context = requireContext()
748+
val deviceAdmin = ComponentName(context, DeviceAdmin::class.java)
749+
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
746750
val actionService = ActionService.instance()
747-
if (actionService != null) {
748-
actionService.lockScreen()
749-
} else {
750-
requireContext().openAccessibilitySettings()
751+
752+
when {
753+
// Use Device Admin if active
754+
dpm.isAdminActive(deviceAdmin) -> {
755+
dpm.lockNow()
756+
CrashHandler.logUserAction("Lock Screen via Device Admin")
757+
}
758+
// Fallback to ActionService if available
759+
actionService != null -> {
760+
actionService.lockScreen()
761+
CrashHandler.logUserAction("Lock Screen via ActionService")
762+
}
763+
// Otherwise prompt the user to enable Device Admin
764+
else -> {
765+
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN).apply {
766+
putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceAdmin)
767+
}
768+
startActivity(intent)
769+
}
751770
}
752771
}
753772

773+
754774
private fun showLongPressToast() = showShortToast(getLocalizedString(longPressToSelectApp))
755775

756776
private fun textOnClick(view: View) = onClick(view)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<device-admin>
3+
<uses-policies>
4+
<!-- Choose policies your app needs -->
5+
<force-lock />
6+
</uses-policies>
7+
</device-admin>

0 commit comments

Comments
 (0)