Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {
minSdk = 26
targetSdk = 36
// targetSdkPreview = "CANARY"
versionCode = 223
versionName = "2.2.3"
versionCode = 22301
versionName = "2.2.3.01(08-03-26)"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppLock"
Expand Down Expand Up @@ -85,7 +84,7 @@
<service
android:name=".services.AppLockAccessibilityService"
android:exported="false"
android:foregroundServiceType="specialUse"
android:foregroundServiceType="specialUse|systemExempted"
android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
tools:ignore="AccessibilityPolicy">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ class DeviceAdmin : DeviceAdminReceiver() {
context.getSharedPreferences("app_lock_settings", Context.MODE_PRIVATE).edit {
putBoolean("anti_uninstall", true)
}

val component = ComponentName(context, DeviceAdmin::class.java)

getManager(context).setUninstallBlocked(component, context.packageName, true)
}

override fun onDisabled(context: Context, intent: android.content.Intent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,31 @@ class AppLockRepository(private val context: Context) {
preferencesRepository.setAntiUninstallEnabled(enabled)

fun isAntiUninstallEnabled(): Boolean = preferencesRepository.isAntiUninstallEnabled()

fun setAntiUninstallAdminSettingsEnabled(enabled: Boolean) =
preferencesRepository.setAntiUninstallAdminSettingsEnabled(enabled)

fun isAntiUninstallAdminSettingsEnabled(): Boolean =
preferencesRepository.isAntiUninstallAdminSettingsEnabled()

fun setAntiUninstallUsageStatsEnabled(enabled: Boolean) =
preferencesRepository.setAntiUninstallUsageStatsEnabled(enabled)

fun isAntiUninstallUsageStatsEnabled(): Boolean =
preferencesRepository.isAntiUninstallUsageStatsEnabled()

fun setAntiUninstallAccessibilityEnabled(enabled: Boolean) =
preferencesRepository.setAntiUninstallAccessibilityEnabled(enabled)

fun isAntiUninstallAccessibilityEnabled(): Boolean =
preferencesRepository.isAntiUninstallAccessibilityEnabled()

fun setAntiUninstallOverlayEnabled(enabled: Boolean) =
preferencesRepository.setAntiUninstallOverlayEnabled(enabled)

fun isAntiUninstallOverlayEnabled(): Boolean =
preferencesRepository.isAntiUninstallOverlayEnabled()

fun setProtectEnabled(enabled: Boolean) = preferencesRepository.setProtectEnabled(enabled)
fun isProtectEnabled(): Boolean = preferencesRepository.isProtectEnabled()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class PreferencesRepository(context: Context) {
context.getSharedPreferences(PREFS_NAME_SETTINGS, Context.MODE_PRIVATE)

fun setPassword(password: String) {
appLockPrefs.edit { putString(KEY_PASSWORD, password) }
appLockPrefs.edit(commit = true) { putString(KEY_PASSWORD, password) }
}

fun getPassword(): String? {
Expand All @@ -30,7 +30,7 @@ class PreferencesRepository(context: Context) {
}

fun setPattern(pattern: String) {
appLockPrefs.edit { putString(KEY_PATTERN, pattern) }
appLockPrefs.edit(commit = true) { putString(KEY_PATTERN, pattern) }
}

fun getPattern(): String? {
Expand All @@ -43,7 +43,7 @@ class PreferencesRepository(context: Context) {
}

fun setLockType(lockType: String) {
settingsPrefs.edit { putString(KEY_LOCK_TYPE, lockType) }
settingsPrefs.edit(commit = true) { putString(KEY_LOCK_TYPE, lockType) }
}

fun getLockType(): String {
Expand Down Expand Up @@ -83,15 +83,47 @@ class PreferencesRepository(context: Context) {
}

fun setAntiUninstallEnabled(enabled: Boolean) {
settingsPrefs.edit { putBoolean(KEY_ANTI_UNINSTALL, enabled) }
settingsPrefs.edit(commit = true) { putBoolean(KEY_ANTI_UNINSTALL, enabled) }
}

fun isAntiUninstallEnabled(): Boolean {
return settingsPrefs.getBoolean(KEY_ANTI_UNINSTALL, false)
}

fun setAntiUninstallAdminSettingsEnabled(enabled: Boolean) {
settingsPrefs.edit(commit = true) { putBoolean(KEY_ANTI_UNINSTALL_ADMIN_SETTINGS, enabled) }
}

fun isAntiUninstallAdminSettingsEnabled(): Boolean {
return settingsPrefs.getBoolean(KEY_ANTI_UNINSTALL_ADMIN_SETTINGS, false)
}

fun setAntiUninstallUsageStatsEnabled(enabled: Boolean) {
settingsPrefs.edit(commit = true) { putBoolean(KEY_ANTI_UNINSTALL_USAGE_STATS, enabled) }
}

fun isAntiUninstallUsageStatsEnabled(): Boolean {
return settingsPrefs.getBoolean(KEY_ANTI_UNINSTALL_USAGE_STATS, false)
}

fun setAntiUninstallAccessibilityEnabled(enabled: Boolean) {
settingsPrefs.edit(commit = true) { putBoolean(KEY_ANTI_UNINSTALL_ACCESSIBILITY, enabled) }
}

fun isAntiUninstallAccessibilityEnabled(): Boolean {
return settingsPrefs.getBoolean(KEY_ANTI_UNINSTALL_ACCESSIBILITY, false)
}

fun setAntiUninstallOverlayEnabled(enabled: Boolean) {
settingsPrefs.edit(commit = true) { putBoolean(KEY_ANTI_UNINSTALL_OVERLAY, enabled) }
}

fun isAntiUninstallOverlayEnabled(): Boolean {
return settingsPrefs.getBoolean(KEY_ANTI_UNINSTALL_OVERLAY, false)
}

fun setProtectEnabled(enabled: Boolean) {
settingsPrefs.edit { putBoolean(KEY_APPLOCK_ENABLED, enabled) }
settingsPrefs.edit(commit = true) { putBoolean(KEY_APPLOCK_ENABLED, enabled) }
}

fun isProtectEnabled(): Boolean {
Expand All @@ -115,7 +147,7 @@ class PreferencesRepository(context: Context) {
}

fun setBackendImplementation(backend: BackendImplementation) {
settingsPrefs.edit { putString(KEY_BACKEND_IMPLEMENTATION, backend.name) }
settingsPrefs.edit(commit = true) { putString(KEY_BACKEND_IMPLEMENTATION, backend.name) }
}

fun getBackendImplementation(): BackendImplementation {
Expand Down Expand Up @@ -164,6 +196,10 @@ class PreferencesRepository(context: Context) {
private const val KEY_DISABLE_HAPTICS = "disable_haptics"
private const val KEY_USE_MAX_BRIGHTNESS = "use_max_brightness"
private const val KEY_ANTI_UNINSTALL = "anti_uninstall"
private const val KEY_ANTI_UNINSTALL_ADMIN_SETTINGS = "anti_uninstall_admin_settings"
private const val KEY_ANTI_UNINSTALL_USAGE_STATS = "anti_uninstall_usage_stats"
private const val KEY_ANTI_UNINSTALL_ACCESSIBILITY = "anti_uninstall_accessibility"
private const val KEY_ANTI_UNINSTALL_OVERLAY = "anti_uninstall_overlay"
private const val KEY_UNLOCK_TIME_DURATION = "unlock_time_duration"
private const val KEY_BACKEND_IMPLEMENTATION = "backend_implementation"
private const val KEY_COMMUNITY_LINK_SHOWN = "community_link_shown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class AdminDisableActivity : ComponentActivity() {
R.string.password_verified_admin,
Toast.LENGTH_SHORT
).show()

devicePolicyManager.removeActiveAdmin(deviceAdminComponentName)
appLockRepository.setAntiUninstallEnabled(false)
finish()
},
Expand Down Expand Up @@ -111,6 +113,8 @@ class AdminDisableActivity : ComponentActivity() {
R.string.password_verified_admin,
Toast.LENGTH_SHORT
).show()

devicePolicyManager.removeActiveAdmin(deviceAdminComponentName)
appLockRepository.setAntiUninstallEnabled(false)
finish()
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ fun AppIntroScreen(navController: NavController) {
NotificationManagerCompat.from(context).areNotificationsEnabled()
}
accessibilityServiceEnabled = context.isAccessibilityServiceEnabled()
usageStatsPermissionGranted = context.hasUsagePermission()
}

val onFinishCallback = {
Expand Down Expand Up @@ -355,55 +356,55 @@ fun AppIntroScreen(navController: NavController) {
onNext = { true }
)

val methodSpecificPages = when (selectedMethod) {
AppUsageMethod.ACCESSIBILITY -> listOf(
IntroPage(
title = stringResource(R.string.accessibility_service_title),
description = stringResource(R.string.app_intro_accessibility_desc),
icon = Accessibility,
backgroundColor = Color(0xFFF1550E),
contentColor = Color.White,
onNext = {
accessibilityServiceEnabled = context.isAccessibilityServiceEnabled()
if (!accessibilityServiceEnabled) {
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
false
} else {
context.appLockRepository()
.setBackendImplementation(BackendImplementation.ACCESSIBILITY)
true
}
val mandatoryPermissionPages = listOf(
IntroPage(
title = stringResource(R.string.accessibility_service_title),
description = stringResource(R.string.app_intro_accessibility_desc),
icon = Accessibility,
backgroundColor = Color(0xFFF1550E),
contentColor = Color.White,
onNext = {
accessibilityServiceEnabled = context.isAccessibilityServiceEnabled()
if (!accessibilityServiceEnabled) {
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
false
} else {
true
}
)
)

AppUsageMethod.USAGE_STATS -> listOf(
IntroPage(
title = stringResource(R.string.app_intro_usage_stats_title),
description = stringResource(R.string.app_intro_usage_stats_desc),
icon = Icons.Default.QueryStats,
backgroundColor = Color(0xFFB453A4),
contentColor = Color.White,
onNext = {
usageStatsPermissionGranted = context.hasUsagePermission()
if (!usageStatsPermissionGranted) {
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
false
} else {
context.appLockRepository()
.setBackendImplementation(BackendImplementation.USAGE_STATS)
context.startService(
Intent(context, ExperimentalAppLockService::class.java)
)
true
}
}
),
IntroPage(
title = stringResource(R.string.app_intro_usage_stats_title),
description = stringResource(R.string.app_intro_usage_stats_desc),
icon = Icons.Default.QueryStats,
backgroundColor = Color(0xFFB453A4),
contentColor = Color.White,
onNext = {
usageStatsPermissionGranted = context.hasUsagePermission()
if (!usageStatsPermissionGranted) {
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
false
} else {
true
}
)
}
)
)

val methodSpecificPages = when (selectedMethod) {
AppUsageMethod.ACCESSIBILITY -> {
context.appLockRepository().setBackendImplementation(BackendImplementation.ACCESSIBILITY)
emptyList()
}

AppUsageMethod.USAGE_STATS -> {
context.appLockRepository().setBackendImplementation(BackendImplementation.USAGE_STATS)
emptyList()
}

AppUsageMethod.SHIZUKU -> listOf(
IntroPage(
Expand Down Expand Up @@ -454,10 +455,12 @@ fun AppIntroScreen(navController: NavController) {
notificationPermissionGranted =
NotificationManagerCompat.from(context).areNotificationsEnabled()
}
accessibilityServiceEnabled = context.isAccessibilityServiceEnabled()
usageStatsPermissionGranted = context.hasUsagePermission()

val methodPermissionGranted = when (selectedMethod) {
AppUsageMethod.ACCESSIBILITY -> context.isAccessibilityServiceEnabled()
AppUsageMethod.USAGE_STATS -> context.hasUsagePermission()
AppUsageMethod.ACCESSIBILITY -> accessibilityServiceEnabled
AppUsageMethod.USAGE_STATS -> usageStatsPermissionGranted
AppUsageMethod.SHIZUKU -> {
if (Shizuku.isPreV11()) {
checkSelfPermission(
Expand All @@ -470,26 +473,30 @@ fun AppIntroScreen(navController: NavController) {
}
}

// Only require all permissions if accessibility is selected
val allPermissionsGranted = if (selectedMethod == AppUsageMethod.ACCESSIBILITY) {
overlayPermissionGranted && notificationPermissionGranted && methodPermissionGranted
} else {
overlayPermissionGranted && notificationPermissionGranted && methodPermissionGranted
}
val allPermissionsGranted = overlayPermissionGranted &&
notificationPermissionGranted &&
accessibilityServiceEnabled &&
usageStatsPermissionGranted &&
methodPermissionGranted

if (!allPermissionsGranted) {
Toast.makeText(
context,
context.getString(R.string.all_permissions_required),
Toast.LENGTH_SHORT
).show()
} else {
// Ensure correct service is started if not Accessibility
if (selectedMethod == AppUsageMethod.USAGE_STATS) {
context.startService(Intent(context, ExperimentalAppLockService::class.java))
}
}
allPermissionsGranted
}
)

val allPages =
basicPages + methodSelectionPage + methodSpecificPages + finalPage
basicPages + methodSelectionPage + mandatoryPermissionPages + methodSpecificPages + finalPage

AppIntro(
pages = allPages,
Expand Down
Loading