diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2cfc0bb9c82895e091d217017e2e9a5fa7eab745..70c1c612b9017e04cf9d3503626f38cb31be7b51 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -18,8 +18,8 @@ android {
versionProps["VERSION_CHANGE"] = "0"
versionProps["VERSION_MAJOR"] = "1"
versionProps["VERSION_MINOR"] = "0"
- versionProps["VERSION_PATCH"] = "0"
- versionProps["VERSION_CODE"] = "1"
+ versionProps["VERSION_PATCH"] = "1"
+ versionProps["VERSION_CODE"] = "2"
// Attempt to write properties to the file
versionPropsFile.writer().use { writer -> versionProps.store(writer, null) }
@@ -71,7 +71,7 @@ android {
return "${versionMajor}.${versionMinor}.${versionPatch}"
}
- return "1.0"
+ return "1.0.1"
}
defaultConfig {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c6631449afd4c4b08b60e9f8b7465ddcdf82da62..7c7cc4163662f586de5e4af00af54f8e0f0da20e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,13 +3,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="android.uid.system">
-
-
-
diff --git a/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt b/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt
index 0c56b8af676e12439a143a69b688505d6dc8efc2..1aa6d22449f9dfef220fb29140efa1273d7b176f 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt
@@ -16,6 +16,8 @@ import android.util.Log
import android.widget.Toast
import foundation.e.parentalcontrol.ui.view.MainUI
import foundation.e.parentalcontrol.utils.Constants
+import foundation.e.parentalcontrol.utils.PrefsUtils
+import foundation.e.parentalcontrol.utils.SystemUtils
import java.util.Objects
class DeviceAdmin : DeviceAdminReceiver() {
@@ -52,7 +54,9 @@ class DeviceAdmin : DeviceAdminReceiver() {
Intent.ACTION_MY_PACKAGE_REPLACED,
Intent.ACTION_MY_PACKAGE_SUSPENDED,
Constants.RESTART_SERVICE -> {
- showToast(context, R.string.parental_control_restarted)
+ if (BuildConfig.DEBUG) {
+ showToast(context, R.string.parental_control_restarted)
+ }
setSettings(context)
}
else -> super.onReceive(context, intent)
@@ -60,11 +64,8 @@ class DeviceAdmin : DeviceAdminReceiver() {
}
override fun onEnabled(context: Context, intent: Intent) {
- isAdminActive = isAdminActive(context)
- if (isAdminActive) {
- showToast(context, R.string.parental_control_is_activated)
- setSettings(context)
- }
+ showToast(context, R.string.parental_control_is_activated)
+ setSettings(context)
}
private fun setSettings(context: Context) {
@@ -78,7 +79,25 @@ class DeviceAdmin : DeviceAdminReceiver() {
}
override fun onDisabled(context: Context, intent: Intent) {
- isAdminActive = isAdminActive(context)
+ PrefsUtils.init(context)
+ PrefsUtils.clearAll()
+ }
+
+ @Suppress("DEPRECATION")
+ fun removeAdmin(context: Context) {
+ val devicePolicyManager: DevicePolicyManager = getDevicePolicyManager(context)
+ SystemUtils.safeSetProp("persist.sys.mdm_active", "0")
+ val mainUI = MainUI(context)
+ mainUI.clearDefaultRestrictions()
+ if (isDeviceOwnerApp(context)) {
+ devicePolicyManager.clearDeviceOwnerApp(context.packageName)
+ } else if (isProfileOwner(context)) {
+ devicePolicyManager.clearProfileOwner(ComponentName(context, DeviceAdmin::class.java))
+ }
+ }
+
+ fun setAdmin() {
+ SystemUtils.safeSetProp("persist.sys.mdm_active", "1")
}
fun isAdminActive(context: Context): Boolean {
diff --git a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt
index b6c73a2d20c630508bf7a4e9271137e97d2fa29d..b4259e50b8463927e5d57e3764304598638d4c12 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt
@@ -7,11 +7,14 @@
*/
package foundation.e.parentalcontrol
+import android.accounts.AccountManager
import android.app.admin.DevicePolicyManager
-import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.os.Build
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
import android.os.UserManager
import android.provider.Settings
import android.widget.Toast
@@ -64,8 +67,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import androidx.lifecycle.lifecycleScope
-import foundation.e.parentalcontrol.data.Ages
+import foundation.e.elib.BuildConfig
import foundation.e.parentalcontrol.data.AuthenticationType
import foundation.e.parentalcontrol.data.Pages
import foundation.e.parentalcontrol.data.isNotLoggedIn
@@ -77,9 +79,10 @@ import foundation.e.parentalcontrol.ui.text.textFieldColor
import foundation.e.parentalcontrol.ui.text.textFieldColorError
import foundation.e.parentalcontrol.ui.theme.ParentalControlTheme
import foundation.e.parentalcontrol.ui.view.AskPassword
+import foundation.e.parentalcontrol.ui.view.AuthenticationTypeSelectionView
import foundation.e.parentalcontrol.ui.view.MainUI
import foundation.e.parentalcontrol.ui.view.SelectAge
-import foundation.e.parentalcontrol.ui.view.authenticationTypeSelectionView
+import foundation.e.parentalcontrol.ui.view.selectedAge
import foundation.e.parentalcontrol.utils.Constants
import foundation.e.parentalcontrol.utils.CryptUtils
import foundation.e.parentalcontrol.utils.PrefsUtils
@@ -87,53 +90,40 @@ import foundation.e.parentalcontrol.utils.SystemUtils
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
-var isAdminActive by mutableStateOf(false)
-var selectedAuthenticationType by mutableStateOf(null)
-var selectedAge: Ages? by mutableStateOf(null)
-
class MainActivity : ComponentActivity() {
private var mActivity: ComponentActivity = this
- private var passText by mutableStateOf("")
private val dA: DeviceAdmin = DeviceAdmin()
+
+ private var passText by mutableStateOf("")
private var confirmPassText by mutableStateOf("")
- private var enteringConfirmation by mutableStateOf(false)
- private var isSetupFinished = false
- private var passwordConfirmation by mutableStateOf(false)
- private lateinit var currentPage: Pages
- private var showMultiUsersDialog by mutableStateOf(false)
- private var showLoginDialog by mutableStateOf(false)
- private lateinit var mUserManager: UserManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PrefsUtils.init(mActivity)
- isSetupFinished = SystemUtils.isSetupFinished(mActivity)
- selectedAge = PrefsUtils.getAge()
- mUserManager = getSystemService(Context.USER_SERVICE) as UserManager
- showMultiUsersDialog = mUserManager.userCount > 1
onStartUp()
}
private fun onStartUp() {
- isAdminActive = isAdminActive()
- lifecycleScope.launch {
- val appLoungeData = AppLoungeData()
- val loginStatus = appLoungeData.getLoginInfo(mActivity)
- showLoginDialog = isNotLoggedIn(loginStatus)
- }
if (SystemUtils.getUserId() != 0) {
mainScreen(page = Pages.NotMainUser)
- } else if (isAdminActive) {
+ } else if (isAdminSet()) {
mainScreen(page = Pages.ActivateAdmin)
- } else if (!isSetupFinished) {
+ } else if (!SystemUtils.isSetupFinished(mActivity)) {
mainScreen(page = Pages.SelectAge)
} else {
mainScreen(page = Pages.TempActivateAdmin)
}
}
+ private fun isAdminSet(): Boolean {
+ return isAdminActive() &&
+ ((PrefsUtils.getAuthType() == AuthenticationType.PIN ||
+ PrefsUtils.getAuthType() == AuthenticationType.PASSWORD) &&
+ !PrefsUtils.getPassword().isNullOrEmpty())
+ }
+
@Composable
fun SetRestrictionsScreen() {
BackHandler(onBack = { onStartUp() })
@@ -152,7 +142,7 @@ class MainActivity : ComponentActivity() {
}
private fun onExitApp(withResult: Boolean = false) {
- if (withResult && !isSetupFinished) {
+ if (withResult && !SystemUtils.isSetupFinished(mActivity)) {
setResult(RESULT_OK)
}
finishAfterTransition()
@@ -167,7 +157,7 @@ class MainActivity : ComponentActivity() {
fun SetupPinPassword() {
val scope = rememberCoroutineScope()
val keyboardController = LocalSoftwareKeyboardController.current
- var isPasswordValid by remember { mutableStateOf(isPinPasswordValid()) }
+ var isPasswordValid by remember { mutableStateOf(false) }
val focusRequester = FocusRequester()
fun onBackPress() {
@@ -177,7 +167,7 @@ class MainActivity : ComponentActivity() {
@Composable
fun titleText(): String {
- return if (selectedAuthenticationType == AuthenticationType.PIN)
+ return if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
stringResource(R.string.enter_new_pin)
else stringResource(R.string.enter_new_password)
}
@@ -193,7 +183,6 @@ class MainActivity : ComponentActivity() {
) {
fun checkPassword() {
if (isPasswordValid) {
- enteringConfirmation = true
mainScreen(page = Pages.SetupConfirmPinPassword)
}
}
@@ -208,7 +197,7 @@ class MainActivity : ComponentActivity() {
value = passText,
onValueChange = {
passText = it
- isPasswordValid = isPinPasswordValid()
+ isPasswordValid = isPinPasswordValid(it)
},
label = {
Text(
@@ -219,7 +208,7 @@ class MainActivity : ComponentActivity() {
keyboardOptions =
KeyboardOptions.Default.copy(
keyboardType =
- if (selectedAuthenticationType == AuthenticationType.PIN)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
KeyboardType.NumberPassword
else KeyboardType.Password,
imeAction = ImeAction.Done
@@ -241,7 +230,7 @@ class MainActivity : ComponentActivity() {
Text(
text =
- if (selectedAuthenticationType == AuthenticationType.PIN)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
stringResource(R.string.pin_requirements)
else stringResource(R.string.password_requirements),
Modifier.padding(10.dp),
@@ -262,8 +251,8 @@ class MainActivity : ComponentActivity() {
}
}
- private fun isPinPasswordValid(pass: String = passText): Boolean {
- return if (selectedAuthenticationType == AuthenticationType.PIN)
+ private fun isPinPasswordValid(pass: String): Boolean {
+ return if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
pass.length >= 4 && pass.all { it.isDigit() }
else pass.length >= 8
}
@@ -273,7 +262,7 @@ class MainActivity : ComponentActivity() {
val scope = rememberCoroutineScope()
val context = LocalContext.current
val keyboardController = LocalSoftwareKeyboardController.current
- var isPasswordValid by remember { mutableStateOf(isPinPasswordValid()) }
+ var isPasswordValid by remember { mutableStateOf(false) }
val focusRequester = FocusRequester()
var isError by remember { mutableStateOf(false) }
@@ -284,7 +273,7 @@ class MainActivity : ComponentActivity() {
@Composable
fun titleText(): String {
- return if (selectedAuthenticationType == AuthenticationType.PIN)
+ return if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
stringResource(R.string.confirm_pin)
else stringResource(R.string.confirm_password)
}
@@ -308,34 +297,33 @@ class MainActivity : ComponentActivity() {
putString(Constants.PREF_PASSWORD, encryptedPass)
putBoolean(
Constants.PREF_PIN_SET,
- selectedAuthenticationType == AuthenticationType.PIN
+ PrefsUtils.getAuthType() == AuthenticationType.PIN
)
putBoolean(
Constants.PREF_PASSWORD_SET,
- selectedAuthenticationType == AuthenticationType.Password
+ PrefsUtils.getAuthType() == AuthenticationType.PASSWORD
)
- putBoolean(Constants.PREF_FIRST_TIME, false)
apply()
}
isError = false
passText = ""
confirmPassText = ""
- enteringConfirmation = false
onSetAge()
- if (isSetupFinished) {
- mainScreen(page = Pages.ActivateAdmin)
- }
+
if (!isAdminActive()) {
- setAdmin()
+ dA.setAdmin()
}
- if (!isSetupFinished) {
+
+ if (SystemUtils.isSetupFinished(mActivity)) {
+ Handler(Looper.getMainLooper()).postDelayed({ onStartUp() }, 500L)
+ } else {
onExitApp(true)
}
} else {
isError = true
if (
- selectedAuthenticationType == AuthenticationType.PIN &&
+ PrefsUtils.getAuthType() == AuthenticationType.PIN &&
!passText.all { it.isDigit() }
) {
Toast.makeText(
@@ -348,7 +336,7 @@ class MainActivity : ComponentActivity() {
// Passwords do not match, show error message
Toast.makeText(
context,
- if (selectedAuthenticationType == AuthenticationType.PIN)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
getString(R.string.pin_mismatch)
else getString(R.string.password_mismatch),
Toast.LENGTH_SHORT
@@ -371,14 +359,14 @@ class MainActivity : ComponentActivity() {
onValueChange = {
confirmPassText = it
isError = false
- isPasswordValid = isPinPasswordValid(confirmPassText)
+ isPasswordValid = isPinPasswordValid(it)
},
label = { Text(titleText()) },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions =
KeyboardOptions.Default.copy(
keyboardType =
- if (selectedAuthenticationType == AuthenticationType.PIN)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
KeyboardType.NumberPassword
else KeyboardType.Password,
imeAction = ImeAction.Done
@@ -400,7 +388,7 @@ class MainActivity : ComponentActivity() {
Text(
text =
- if (selectedAuthenticationType == AuthenticationType.PIN)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
stringResource(R.string.pin_confirm_text)
else stringResource(R.string.password_confirm_text),
Modifier.padding(10.dp),
@@ -424,21 +412,10 @@ class MainActivity : ComponentActivity() {
return dA.isAdminActive(mActivity)
}
- @Suppress("DEPRECATION")
- private fun removeAdmin() {
- val devicePolicyManager: DevicePolicyManager = dA.getDevicePolicyManager(mActivity)
- SystemUtils.safeSetProp("persist.sys.mdm_active", "0")
- MainUI(mActivity).clearDefaultRestrictions()
- if (dA.isDeviceOwnerApp(mActivity)) {
- devicePolicyManager.clearDeviceOwnerApp(mActivity.packageName)
- } else if (dA.isProfileOwner(mActivity)) {
- devicePolicyManager.clearProfileOwner(ComponentName(mActivity, DeviceAdmin::class.java))
- }
- PrefsUtils.clearAll()
- }
-
- private fun setAdmin() {
- SystemUtils.safeSetProp("persist.sys.mdm_active", "1")
+ private fun noAccountsLoggedIn(): Boolean {
+ val accountManager = AccountManager.get(mActivity)
+ val accounts = accountManager.accounts
+ return accounts.isEmpty()
}
@Composable
@@ -452,9 +429,122 @@ class MainActivity : ComponentActivity() {
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top
) {
- if (showMultiUsersDialog) {
+ val devicePolicyManager: DevicePolicyManager = dA.getDevicePolicyManager(mActivity)
+ val activeAdmins = devicePolicyManager.activeAdmins
+
+ if (
+ !activeAdmins.isNullOrEmpty() && !activeAdmins.contains(dA.getAdminName(mActivity))
+ ) {
+ AlertDialog(
+ onDismissRequest = { onExitApp() },
+ title = {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Icon(
+ imageVector = Icons.Default.Info,
+ contentDescription = "Info icon",
+ tint = Color.Gray
+ )
+ Text(
+ text = stringResource(R.string.parental_control_is_blocked),
+ fontSize = 20.sp,
+ modifier = Modifier.padding(start = 10.dp)
+ )
+ }
+ },
+ text = {
+ Text(
+ text =
+ stringResource(R.string.another_device_admin_app_summary) +
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ stringResource(R.string.settings_device_admin_apps_t)
+ else stringResource(R.string.settings_device_admin_apps_s),
+ color =
+ colorResource(id = foundation.e.elib.R.color.e_secondary_text_color)
+ )
+ },
+ confirmButton = {
+ Text(
+ modifier =
+ Modifier.clickable {
+ val intent = Intent(Settings.ACTION_SECURITY_SETTINGS)
+ startActivity(intent)
+ }
+ .padding(start = 10.dp),
+ color = colorResource(id = foundation.e.elib.R.color.e_accent),
+ text = stringResource(R.string.open_settings).uppercase(),
+ fontSize = 14.sp
+ )
+ },
+ dismissButton = {
+ Text(
+ modifier = Modifier.clickable { onExitApp() },
+ color = colorResource(id = foundation.e.elib.R.color.e_accent),
+ text = stringResource(R.string.discard).uppercase(),
+ fontSize = 14.sp
+ )
+ },
+ shape = RoundedCornerShape(4.dp)
+ )
+ }
+
+ if (!noAccountsLoggedIn()) {
AlertDialog(
- onDismissRequest = { showMultiUsersDialog = false },
+ onDismissRequest = { onExitApp() },
+ title = {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Icon(
+ imageVector = Icons.Default.Info,
+ contentDescription = "Info icon",
+ tint = Color.Gray
+ )
+ Text(
+ text = stringResource(R.string.parental_control_is_blocked),
+ fontSize = 20.sp,
+ modifier = Modifier.padding(start = 10.dp)
+ )
+ }
+ },
+ text = {
+ Text(
+ text = stringResource(R.string.remove_logged_in_accounts),
+ color =
+ colorResource(id = foundation.e.elib.R.color.e_secondary_text_color)
+ )
+ },
+ confirmButton = {
+ Text(
+ modifier =
+ Modifier.clickable {
+ val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+ startActivity(intent)
+ }
+ .padding(start = 10.dp),
+ color = colorResource(id = foundation.e.elib.R.color.e_accent),
+ text = stringResource(R.string.open_settings).uppercase(),
+ fontSize = 14.sp
+ )
+ },
+ dismissButton = {
+ Text(
+ modifier = Modifier.clickable { onExitApp() },
+ color = colorResource(id = foundation.e.elib.R.color.e_accent),
+ text = stringResource(R.string.discard).uppercase(),
+ fontSize = 14.sp
+ )
+ },
+ shape = RoundedCornerShape(4.dp)
+ )
+ }
+
+ val userManager = getSystemService(Context.USER_SERVICE) as UserManager
+ var showDialog by remember { mutableStateOf(userManager.userCount > 1) }
+ if (showDialog) {
+ AlertDialog(
+ onDismissRequest = { showDialog = false },
title = {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -482,8 +572,8 @@ class MainActivity : ComponentActivity() {
Text(
modifier =
Modifier.clickable {
- showMultiUsersDialog = false
startActivity(Intent(Settings.ACTION_USER_SETTINGS))
+ showDialog = false
}
.padding(start = 10.dp),
color = colorResource(id = foundation.e.elib.R.color.e_accent),
@@ -493,7 +583,7 @@ class MainActivity : ComponentActivity() {
},
dismissButton = {
Text(
- modifier = Modifier.clickable { showMultiUsersDialog = false },
+ modifier = Modifier.clickable { showDialog = false },
color = colorResource(id = foundation.e.elib.R.color.e_accent),
text = stringResource(R.string.discard).uppercase(),
fontSize = 14.sp
@@ -508,15 +598,16 @@ class MainActivity : ComponentActivity() {
color = colorResource(foundation.e.elib.R.color.e_primary_text_color),
)
- var checkedState by remember { mutableStateOf(isAdminActive) }
+ var checkedState by remember { mutableStateOf(false) }
var moveToNext by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
ToggleWithText(
text = stringResource(R.string.activate_parental_control),
- isChecked = (isAdminActive || isAdminActive()) || checkedState,
+ isChecked = checkedState,
onCheckedChange = {
checkedState = it
+ PrefsUtils.clearAll()
coroutineScope.launch {
delay(200)
moveToNext = true
@@ -537,16 +628,20 @@ class MainActivity : ComponentActivity() {
CustomTopAppBar(title = stringResource(R.string.app_name), onClick = { onExitApp() })
+ var showLoginDialog by remember { mutableStateOf(false) }
+
+ LaunchedEffect(Unit) {
+ val appLoungeData = AppLoungeData()
+ val loginStatus = appLoungeData.getLoginInfo(mActivity)
+ showLoginDialog = isNotLoggedIn(loginStatus)
+ }
+
Column(
modifier = Modifier.fillMaxSize().padding(start = 24.dp, end = 24.dp),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top
) {
- if (
- showLoginDialog &&
- PrefsUtils.getBlockedApps() == null &&
- (isAdminActive || isAdminActive())
- ) {
+ if (showLoginDialog && PrefsUtils.getBlockedApps() == null) {
val mainUI = MainUI(mActivity)
AlertDialog(
onDismissRequest = {
@@ -623,48 +718,34 @@ class MainActivity : ComponentActivity() {
ToggleWithText(
text = stringResource(R.string.activate_parental_control),
- isChecked = isAdminActive,
+ isChecked = isAdminActive(),
onCheckedChange = {
if (it) {
- setAdmin()
- } else if (PrefsUtils.isPinSet() || PrefsUtils.isPasswordSet()) {
- mainScreen(page = Pages.AskPasswordForAdminRemoval)
+ dA.setAdmin()
} else {
- removeAdmin()
+ mainScreen(page = Pages.AskPasswordForAdminRemoval)
}
}
)
- if (isAdminActive && PrefsUtils.isPinSet() || PrefsUtils.isPasswordSet()) {
- val mainUI = MainUI(mActivity)
- SelectAge(
- onRadioClick = {
- selectedAge = it
- mainScreen(page = Pages.AskPasswordForAgeReset)
- }
- )
-
- if (currentPage == Pages.ActivateAdmin && passwordConfirmation) {
- onSetAge()
- passwordConfirmation = false
- onStartUp()
- mainUI.blockBlackListedApps()
- }
+ SelectAge(
+ onRadioClick = { mainScreen(page = Pages.AskPasswordForAgeReset) },
+ onNextClick = {}
+ )
- Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
- Text(
- text = stringResource(R.string.change_my_security_code).uppercase(),
- color = colorResource(foundation.e.elib.R.color.e_accent),
- fontWeight = FontWeight.Bold,
- modifier =
- Modifier.clickable(
- onClick = { mainScreen(page = Pages.AskPasswordForPasswordReset) }
- ),
- style = MaterialTheme.typography.bodyLarge,
- )
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+ Text(
+ text = stringResource(R.string.change_my_security_code).uppercase(),
+ color = colorResource(foundation.e.elib.R.color.e_accent),
+ fontWeight = FontWeight.Bold,
+ modifier =
+ Modifier.clickable(
+ onClick = { mainScreen(page = Pages.AskPasswordForPasswordReset) }
+ ),
+ style = MaterialTheme.typography.bodyLarge,
+ )
- OnDebugBuild()
- }
+ OnDebugBuild()
}
}
}
@@ -673,32 +754,20 @@ class MainActivity : ComponentActivity() {
if (selectedAge == null) return
with(PrefsUtils.getEdit()) {
putInt(Constants.PREF_AGE, selectedAge!!.ordinal)
- putBoolean(Constants.PREF_AGE_SET, true)
apply()
}
}
@Composable
private fun OnDebugBuild() {
- if (
- (BuildConfig.DEBUG || !isSetupFinished) &&
- (isAdminActive || isAdminActive()) &&
- (PrefsUtils.isPinSet() || PrefsUtils.isPasswordSet())
- ) {
+ if (BuildConfig.DEBUG) {
Box(
modifier = Modifier.fillMaxSize().padding(bottom = 16.dp),
contentAlignment = Alignment.BottomEnd,
) {
Button(
- onClick = {
- if (BuildConfig.DEBUG && isSetupFinished) {
- mainScreen(page = Pages.AskPasswordForDebugMenu)
- } else {
- onExitApp(true)
- }
- },
+ onClick = { mainScreen(page = Pages.AskPasswordForDebugMenu) },
colors = buttonColor(),
- enabled = isAdminActive || isAdminActive(),
) {
Text(stringResource(R.string.next))
}
@@ -709,7 +778,8 @@ class MainActivity : ComponentActivity() {
@Composable
fun SelectAgePage() {
fun onBackPress() {
- if (isSetupFinished) {
+ selectedAge = null
+ if (SystemUtils.isSetupFinished(mActivity)) {
onStartUp()
} else {
onExitApp()
@@ -734,24 +804,9 @@ class MainActivity : ComponentActivity() {
)
SelectAge(
- onRadioClick = {
- selectedAge = it
- mainScreen(page = Pages.SelectAge)
- }
+ onRadioClick = {},
+ onNextClick = { mainScreen(page = Pages.AuthenticationTypeSelectionView) }
)
-
- Box(
- modifier = Modifier.fillMaxSize().padding(top = 16.dp),
- contentAlignment = Alignment.TopCenter,
- ) {
- Button(
- onClick = { mainScreen(page = Pages.AuthenticationTypeSelectionView) },
- colors = buttonColor(),
- enabled = selectedAge != null
- ) {
- Text(stringResource(R.string.next))
- }
- }
}
}
@@ -785,22 +840,18 @@ class MainActivity : ComponentActivity() {
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top
) {
- currentPage = page
when (page) {
Pages.AuthenticationTypeSelectionView -> {
- selectedAuthenticationType =
- authenticationTypeSelectionView(
- onBackPressed = {
- if (isAdminActive()) {
- onStartUp()
- } else {
- mainScreen(page = Pages.SelectAge)
- }
+ AuthenticationTypeSelectionView(
+ onBackPressed = {
+ if (isAdminActive()) {
+ mainScreen(page = Pages.ActivateAdmin)
+ } else {
+ mainScreen(page = Pages.SelectAge)
}
- )
- if (selectedAuthenticationType != null) {
- mainScreen(page = Pages.SetupPinPassword)
- }
+ },
+ onSelection = { mainScreen(page = Pages.SetupPinPassword) }
+ )
}
Pages.SetupPinPassword -> {
SetupPinPassword()
@@ -821,9 +872,9 @@ class MainActivity : ComponentActivity() {
AskPassword(
onPasswordMatch = {
PrefsUtils.clearPassword()
- removeAdmin()
+ selectedAge = null
+ dA.removeAdmin(mActivity)
onStartUp()
- isAdminActive = isAdminActive()
},
onBackPressed = { onStartUp() }
)
@@ -839,9 +890,11 @@ class MainActivity : ComponentActivity() {
Pages.AskPasswordForAgeReset -> {
AskPassword(
onPasswordMatch = {
- passwordConfirmation = true
+ onSetAge()
+ MainUI(mActivity).blockBlackListedApps()
onStartUp()
},
+ onPasswordMisMatch = { selectedAge = PrefsUtils.getAge() },
onBackPressed = { onStartUp() }
)
}
diff --git a/app/src/main/java/foundation/e/parentalcontrol/data/AuthenticationType.kt b/app/src/main/java/foundation/e/parentalcontrol/data/AuthenticationType.kt
index 76200fe25ed2a49d601911c46d8cbe49ad57b23a..71eb491527c72ad4810a82f56a36afbb3c5357f6 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/data/AuthenticationType.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/data/AuthenticationType.kt
@@ -8,6 +8,7 @@
package foundation.e.parentalcontrol.data
enum class AuthenticationType {
+ NONE,
PIN,
- Password
+ PASSWORD
}
diff --git a/app/src/main/java/foundation/e/parentalcontrol/ui/view/AskPassword.kt b/app/src/main/java/foundation/e/parentalcontrol/ui/view/AskPassword.kt
index bdc76e064661511f5ab599d89996238ab0de12b7..1b7eb64909a9e45a4c806e91d0b5ca90ee7bcce1 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/ui/view/AskPassword.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/ui/view/AskPassword.kt
@@ -42,6 +42,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import foundation.e.parentalcontrol.R
+import foundation.e.parentalcontrol.data.AuthenticationType
import foundation.e.parentalcontrol.ui.buttons.buttonColor
import foundation.e.parentalcontrol.ui.text.CustomTopAppBar
import foundation.e.parentalcontrol.ui.text.textFieldColor
@@ -53,7 +54,11 @@ import kotlinx.coroutines.launch
private var passText by mutableStateOf("")
@Composable
-fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
+fun AskPassword(
+ onPasswordMatch: () -> Unit,
+ onBackPressed: () -> Unit,
+ onPasswordMisMatch: () -> Unit = {}
+) {
val scope = rememberCoroutineScope()
val context = LocalContext.current
val keyboardController = LocalSoftwareKeyboardController.current
@@ -63,16 +68,19 @@ fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
onBack = {
passText = ""
onBackPressed()
+ onPasswordMisMatch()
}
)
CustomTopAppBar(
title =
- if (PrefsUtils.isPinSet()) stringResource(R.string.enter_pin)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
+ stringResource(R.string.enter_pin)
else stringResource(R.string.enter_password),
onClick = {
passText = ""
onBackPressed()
+ onPasswordMisMatch()
}
)
@@ -87,9 +95,11 @@ fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
isError = false
} else {
// Passwords do not match, show error message
+ onPasswordMisMatch()
Toast.makeText(
context,
- if (PrefsUtils.isPinSet()) context.getString(R.string.pin_mismatch)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
+ context.getString(R.string.pin_mismatch)
else context.getString(R.string.password_mismatch),
Toast.LENGTH_SHORT
)
@@ -119,7 +129,7 @@ fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
},
label = {
Text(
- if (PrefsUtils.isPinSet())
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
stringResource(R.string.enter_your_parental_control_pin)
else stringResource(R.string.enter_your_parental_control_password)
)
@@ -128,7 +138,8 @@ fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
keyboardOptions =
KeyboardOptions.Default.copy(
keyboardType =
- if (PrefsUtils.isPinSet()) KeyboardType.NumberPassword
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
+ KeyboardType.NumberPassword
else KeyboardType.Password,
imeAction = ImeAction.Done
),
@@ -149,7 +160,8 @@ fun AskPassword(onPasswordMatch: () -> Unit, onBackPressed: () -> Unit) {
Text(
text =
- if (PrefsUtils.isPinSet()) stringResource(R.string.enter_your_parental_control_pin)
+ if (PrefsUtils.getAuthType() == AuthenticationType.PIN)
+ stringResource(R.string.enter_your_parental_control_pin)
else stringResource(R.string.enter_your_parental_control_password),
Modifier.padding(10.dp),
fontWeight = FontWeight.ExtraLight
diff --git a/app/src/main/java/foundation/e/parentalcontrol/ui/view/authenticationTypeSelectionView.kt b/app/src/main/java/foundation/e/parentalcontrol/ui/view/AuthenticationTypeSelectionView.kt
similarity index 75%
rename from app/src/main/java/foundation/e/parentalcontrol/ui/view/authenticationTypeSelectionView.kt
rename to app/src/main/java/foundation/e/parentalcontrol/ui/view/AuthenticationTypeSelectionView.kt
index 6a07dd87111fbf27fb62908389b2b6822ca46234..6cb360ffa83c0e74cf849ef8295578e1c1d187f8 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/ui/view/authenticationTypeSelectionView.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/ui/view/AuthenticationTypeSelectionView.kt
@@ -23,20 +23,24 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import foundation.e.parentalcontrol.R
import foundation.e.parentalcontrol.data.AuthenticationType
-import foundation.e.parentalcontrol.selectedAuthenticationType
import foundation.e.parentalcontrol.ui.buttons.ImageButtonWithText
import foundation.e.parentalcontrol.ui.buttons.buttonColor
import foundation.e.parentalcontrol.ui.text.CustomTopAppBar
+import foundation.e.parentalcontrol.utils.Constants
+import foundation.e.parentalcontrol.utils.PrefsUtils
@Composable
-fun authenticationTypeSelectionView(onBackPressed: () -> Unit): AuthenticationType? {
- var selectedType by remember { mutableStateOf(selectedAuthenticationType) }
- var buttonIsOkay by remember { mutableStateOf(false) }
+fun AuthenticationTypeSelectionView(onBackPressed: () -> Unit, onSelection: () -> Unit) {
+ val context = LocalContext.current
+ PrefsUtils.init(context)
+
+ var selectedType by remember { mutableStateOf(PrefsUtils.getAuthType()) }
BackHandler(onBack = { onBackPressed() })
@@ -55,8 +59,8 @@ fun authenticationTypeSelectionView(onBackPressed: () -> Unit): AuthenticationTy
// Radio buttons for selecting authentication type
ImageButtonWithText(
text = stringResource(R.string.setup_password),
- selected = selectedType == AuthenticationType.Password,
- onClick = { selectedType = AuthenticationType.Password },
+ selected = selectedType == AuthenticationType.PASSWORD,
+ onClick = { selectedType = AuthenticationType.PASSWORD },
image = ImageVector.vectorResource(R.drawable.baseline_password_24),
)
@@ -69,19 +73,20 @@ fun authenticationTypeSelectionView(onBackPressed: () -> Unit): AuthenticationTy
Box(modifier = Modifier.fillMaxSize()) {
Button(
- onClick = { buttonIsOkay = true },
+ onClick = {
+ PrefsUtils.getEdit().apply {
+ putInt(Constants.PREF_AUTH_TYPE, selectedType.ordinal)
+ apply()
+ }
+ onSelection()
+ },
modifier = Modifier.align(Alignment.TopCenter).padding(top = 16.dp),
- enabled = selectedType != null, // Enable only if an option is selected
+ enabled =
+ selectedType != AuthenticationType.NONE, // Enable only if an option is selected
colors = buttonColor()
) {
Text(stringResource(R.string.next))
}
}
}
-
- if (selectedType != null && buttonIsOkay) {
- return selectedType
- }
-
- return null
}
diff --git a/app/src/main/java/foundation/e/parentalcontrol/ui/view/MainUI.kt b/app/src/main/java/foundation/e/parentalcontrol/ui/view/MainUI.kt
index 2a5949a2f652185d5fddf30faa452e502297a607..c09a3af6545782347d8108b66aa817413e0ed223 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/ui/view/MainUI.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/ui/view/MainUI.kt
@@ -77,6 +77,8 @@ class MainUI(context: Context) {
}
fun setDefaultRestrictions() {
+ if (!dA.isAdminActive(mContext)) return
+
setRestriction(appSettingsRestriction)
setRestriction(developerSettingsRestriction)
setRestriction(appUnknownSourceRestriction)
@@ -110,6 +112,8 @@ class MainUI(context: Context) {
}
fun clearDefaultRestrictions() {
+ if (!dA.isAdminActive(mContext)) return
+
clearRestriction(appSettingsRestriction)
clearRestriction(developerSettingsRestriction)
clearRestriction(appUnknownSourceRestriction)
diff --git a/app/src/main/java/foundation/e/parentalcontrol/ui/view/SelectAge.kt b/app/src/main/java/foundation/e/parentalcontrol/ui/view/SelectAge.kt
index 8022927cf139949496b950eedea5f7866f698c49..6422ca2a6ec6397e3805e2445fb415a9858fb5f0 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/ui/view/SelectAge.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/ui/view/SelectAge.kt
@@ -7,22 +7,40 @@
*/
package foundation.e.parentalcontrol.ui.view
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import foundation.e.parentalcontrol.DeviceAdmin
import foundation.e.parentalcontrol.R
import foundation.e.parentalcontrol.data.Ages
-import foundation.e.parentalcontrol.selectedAge
import foundation.e.parentalcontrol.ui.buttons.RadioButtonWithText
+import foundation.e.parentalcontrol.ui.buttons.buttonColor
+import foundation.e.parentalcontrol.utils.PrefsUtils
+
+var selectedAge: Ages? by mutableStateOf(null)
@Composable
-fun SelectAge(onRadioClick: (age: Ages) -> Unit) {
+fun SelectAge(onRadioClick: () -> Unit, onNextClick: () -> Unit) {
+ val context = LocalContext.current
+
+ if (DeviceAdmin().isAdminActive(context)) {
+ selectedAge = PrefsUtils.getAge()
+ }
+
Text(
text = stringResource(R.string.age_group_of_the_child),
color = colorResource(foundation.e.elib.R.color.e_primary_text_color),
@@ -36,36 +54,66 @@ fun SelectAge(onRadioClick: (age: Ages) -> Unit) {
RadioButtonWithText(
text = stringResource(R.string.three_years_old),
selected = Ages.THREE == selectedAge,
- onClick = { onRadioClick(Ages.THREE) },
+ onClick = {
+ selectedAge = Ages.THREE
+ onRadioClick()
+ },
radioButtonOnRight = true
)
RadioButtonWithText(
text = stringResource(R.string.six_years_old),
selected = Ages.SIX == selectedAge,
- onClick = { onRadioClick(Ages.SIX) },
+ onClick = {
+ selectedAge = Ages.SIX
+ onRadioClick()
+ },
radioButtonOnRight = true
)
RadioButtonWithText(
text = stringResource(R.string.eleven_years_old),
selected = Ages.ELEVEN == selectedAge,
- onClick = { onRadioClick(Ages.ELEVEN) },
+ onClick = {
+ selectedAge = Ages.ELEVEN
+ onRadioClick()
+ },
radioButtonOnRight = true
)
RadioButtonWithText(
text = stringResource(R.string.fifteen_years_old),
selected = Ages.FIFTEEN == selectedAge,
- onClick = { onRadioClick(Ages.FIFTEEN) },
+ onClick = {
+ selectedAge = Ages.FIFTEEN
+ onRadioClick()
+ },
radioButtonOnRight = true
)
RadioButtonWithText(
text = stringResource(R.string.seventeen_years_old),
selected = Ages.SEVENTEEN == selectedAge,
- onClick = { onRadioClick(Ages.SEVENTEEN) },
+ onClick = {
+ selectedAge = Ages.SEVENTEEN
+ onRadioClick()
+ },
radioButtonOnRight = true
)
}
+
+ if (!DeviceAdmin().isAdminActive(context)) {
+ Box(
+ modifier = Modifier.fillMaxSize().padding(top = 16.dp),
+ contentAlignment = Alignment.TopCenter,
+ ) {
+ Button(
+ onClick = { onNextClick() },
+ colors = buttonColor(),
+ enabled = selectedAge != null
+ ) {
+ Text(stringResource(R.string.next))
+ }
+ }
+ }
}
diff --git a/app/src/main/java/foundation/e/parentalcontrol/utils/Constants.kt b/app/src/main/java/foundation/e/parentalcontrol/utils/Constants.kt
index f76c7b800b33322ec7498e5f7cc6e8e278004d07..98f37750fc6cead4095b0178ab1a9cd541a7e0d7 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/utils/Constants.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/utils/Constants.kt
@@ -8,12 +8,11 @@
package foundation.e.parentalcontrol.utils
object Constants {
+ const val PREF_AUTH_TYPE = "auth_type"
const val PREF_PIN_SET = "pin_set"
- const val PREF_AGE_SET = "age_set"
const val PREF_PASSWORD_SET = "password_set"
const val PREF_PASSWORD = "password"
const val PREF_AGE = "age"
- const val PREF_FIRST_TIME = "first_time"
const val RESTART_SERVICE = "foundation.e.parental_control.RESTART_SERVICE"
diff --git a/app/src/main/java/foundation/e/parentalcontrol/utils/PrefsUtils.kt b/app/src/main/java/foundation/e/parentalcontrol/utils/PrefsUtils.kt
index 97917adc9b24343afc5e2867ea44877e51ae0855..91bd8f83dd9fdf827d84419de6ecd9de3709a632 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/utils/PrefsUtils.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/utils/PrefsUtils.kt
@@ -12,6 +12,7 @@ import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import foundation.e.parentalcontrol.data.Ages
+import foundation.e.parentalcontrol.data.AuthenticationType
object PrefsUtils {
private lateinit var sharedPreferences: SharedPreferences
@@ -23,22 +24,23 @@ object PrefsUtils {
}
}
- fun isPinSet(): Boolean {
- return sharedPreferences.getBoolean(Constants.PREF_PIN_SET, false)
- }
-
- fun isPasswordSet(): Boolean {
- return sharedPreferences.getBoolean(Constants.PREF_PASSWORD_SET, false)
+ fun getAuthType(): AuthenticationType {
+ val default =
+ if (sharedPreferences.getBoolean(Constants.PREF_PIN_SET, false)) {
+ AuthenticationType.PIN.ordinal
+ } else if (sharedPreferences.getBoolean(Constants.PREF_PASSWORD_SET, false)) {
+ AuthenticationType.PASSWORD.ordinal
+ } else {
+ AuthenticationType.NONE.ordinal
+ }
+ val type = sharedPreferences.getInt(Constants.PREF_AUTH_TYPE, default)
+ return AuthenticationType.entries[type]
}
fun getPassword(): String? {
return sharedPreferences.getString(Constants.PREF_PASSWORD, "")
}
- fun isAgeSet(): Boolean {
- return sharedPreferences.getBoolean(Constants.PREF_AGE_SET, false)
- }
-
fun getEdit(): SharedPreferences.Editor {
return sharedPreferences.edit()
}
@@ -49,10 +51,6 @@ object PrefsUtils {
return Ages.entries[ordinal]
}
- fun getFirstTime(): Boolean {
- return sharedPreferences.getBoolean(Constants.PREF_FIRST_TIME, true)
- }
-
fun clearAll() {
sharedPreferences.edit().clear().apply()
}
diff --git a/app/src/main/java/foundation/e/parentalcontrol/utils/SystemUtils.kt b/app/src/main/java/foundation/e/parentalcontrol/utils/SystemUtils.kt
index 686613d0e8097e97dcf4252864f3bde06ece28a9..6ee6196360711a6810c5b448becd73e2d051dfa6 100644
--- a/app/src/main/java/foundation/e/parentalcontrol/utils/SystemUtils.kt
+++ b/app/src/main/java/foundation/e/parentalcontrol/utils/SystemUtils.kt
@@ -8,7 +8,6 @@
package foundation.e.parentalcontrol.utils
import android.annotation.SuppressLint
-import android.app.AppOpsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
@@ -55,59 +54,6 @@ object SystemUtils {
return UserHandle.myUserId()
}
- fun getAppsAllowedToInstallPackages(context: Context): List {
- val packageManager = context.packageManager
- val appsWithInstallPermission = mutableListOf()
-
- val packages = packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS)
- val appOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
-
- for (packageInfo in packages) {
- val requestedPermissions = packageInfo.requestedPermissions
- if (
- requestedPermissions != null &&
- requestedPermissions.contains("android.permission.REQUEST_INSTALL_PACKAGES")
- ) {
- val mode =
- appOpsManager.unsafeCheckOpNoThrow(
- AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES,
- packageInfo.applicationInfo.uid,
- packageInfo.packageName
- )
- if (mode == AppOpsManager.MODE_ALLOWED) {
- appsWithInstallPermission.add(packageInfo.packageName)
- }
- }
- }
-
- return appsWithInstallPermission
- }
-
- fun allowAppToInstallPackages(context: Context, packageName: String, enable: Boolean): Boolean {
- try {
- val packageManager = context.packageManager
- val appOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
-
- val packageInfo =
- packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
- val uid = packageInfo.applicationInfo.uid
-
- appOpsManager.setMode(
- AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES,
- uid,
- packageName,
- if (enable) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_DEFAULT
- )
- } catch (e: PackageManager.NameNotFoundException) {
- e.printStackTrace()
- return false
- } catch (e: SecurityException) {
- e.printStackTrace()
- return false
- }
- return true
- }
-
fun getInstalledUserApps(context: Context): List {
val packageManager: PackageManager = context.packageManager
val allApps: List =
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b81cc105d824a7473d6fd6231c054b1777f94983..60a149c9a99b8c88c16a10b06f1337c66015dd8d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -60,4 +60,10 @@
This setting is blocked
Enter your parental control pin
Enter your parental control password
+ Parental control is blocked
+ Another device admin app was detected. Please disable or remove it before activating parental control. To remove it, please go to the settings below.\n\n
+ "Security > More security settings > Device admin apps"
+ "Security > Device admin apps"
+ Open settings
+ "Please remove all logged-in accounts to activate parental control.\n\nSettings > Accounts"
\ No newline at end of file