From 499651fc3c1d9c472e799de68ed51b6255e21f58 Mon Sep 17 00:00:00 2001 From: althafvly Date: Mon, 17 Jun 2024 14:18:49 +0530 Subject: [PATCH 1/6] parental: Show restart for debug --- app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt b/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt index 0c56b8a..d8f517c 100644 --- a/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt +++ b/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt @@ -52,7 +52,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) -- GitLab From 1cb3d7056800d02d713513ea71a1e8cf5d505431 Mon Sep 17 00:00:00 2001 From: althafvly Date: Mon, 17 Jun 2024 15:12:23 +0530 Subject: [PATCH 2/6] parental: Remove unused codes and add admin checks parental: Check for other active admins --- .../e/parentalcontrol/DeviceAdmin.kt | 29 +- .../e/parentalcontrol/MainActivity.kt | 318 +++++++++--------- .../data/AuthenticationType.kt | 3 +- .../e/parentalcontrol/ui/view/AskPassword.kt | 24 +- ....kt => AuthenticationTypeSelectionView.kt} | 33 +- .../e/parentalcontrol/ui/view/MainUI.kt | 4 + .../e/parentalcontrol/ui/view/SelectAge.kt | 62 +++- .../e/parentalcontrol/utils/Constants.kt | 3 +- .../e/parentalcontrol/utils/PrefsUtils.kt | 26 +- app/src/main/res/values/strings.xml | 5 + 10 files changed, 295 insertions(+), 212 deletions(-) rename app/src/main/java/foundation/e/parentalcontrol/ui/view/{authenticationTypeSelectionView.kt => AuthenticationTypeSelectionView.kt} (75%) diff --git a/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt b/app/src/main/java/foundation/e/parentalcontrol/DeviceAdmin.kt index d8f517c..1aa6d22 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() { @@ -62,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) { @@ -80,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 b6c73a2..99f847a 100644 --- a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt +++ b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt @@ -8,10 +8,12 @@ package foundation.e.parentalcontrol 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 +66,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 +78,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 +89,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 +141,7 @@ class MainActivity : ComponentActivity() { } private fun onExitApp(withResult: Boolean = false) { - if (withResult && !isSetupFinished) { + if (withResult && !SystemUtils.isSetupFinished(mActivity)) { setResult(RESULT_OK) } finishAfterTransition() @@ -167,7 +156,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 +166,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 +182,6 @@ class MainActivity : ComponentActivity() { ) { fun checkPassword() { if (isPasswordValid) { - enteringConfirmation = true mainScreen(page = Pages.SetupConfirmPinPassword) } } @@ -208,7 +196,7 @@ class MainActivity : ComponentActivity() { value = passText, onValueChange = { passText = it - isPasswordValid = isPinPasswordValid() + isPasswordValid = isPinPasswordValid(it) }, label = { Text( @@ -219,7 +207,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 +229,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 +250,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 +261,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 +272,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 +296,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 +335,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 +358,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 +387,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,23 +411,6 @@ 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") - } - @Composable fun TempActivateAdmin() { BackHandler(onBack = { onExitApp() }) @@ -452,9 +422,71 @@ 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) + ) + } + + val userManager = getSystemService(Context.USER_SERVICE) as UserManager + var showDialog by remember { mutableStateOf(userManager.userCount > 1) } + if (showDialog) { AlertDialog( - onDismissRequest = { showMultiUsersDialog = false }, + onDismissRequest = { showDialog = false }, title = { Row( verticalAlignment = Alignment.CenterVertically, @@ -482,8 +514,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 +525,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,13 +540,13 @@ 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 coroutineScope.launch { @@ -537,16 +569,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 +659,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 +695,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 +719,8 @@ class MainActivity : ComponentActivity() { @Composable fun SelectAgePage() { fun onBackPress() { - if (isSetupFinished) { + selectedAge = null + if (SystemUtils.isSetupFinished(mActivity)) { onStartUp() } else { onExitApp() @@ -734,24 +745,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 +781,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 +813,9 @@ class MainActivity : ComponentActivity() { AskPassword( onPasswordMatch = { PrefsUtils.clearPassword() - removeAdmin() + selectedAge = null + dA.removeAdmin(mActivity) onStartUp() - isAdminActive = isAdminActive() }, onBackPressed = { onStartUp() } ) @@ -839,9 +831,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 76200fe..71eb491 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 bdc76e0..1b7eb64 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 6a07dd8..6cb360f 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 2a5949a..c09a3af 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 8022927..6422ca2 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 f76c7b8..98f3775 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 97917ad..91bd8f8 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/res/values/strings.xml b/app/src/main/res/values/strings.xml index b81cc10..f6f81a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -60,4 +60,9 @@ 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 \ No newline at end of file -- GitLab From d0a3c7fe7d9d074f9cff83c07765ce186429c82b Mon Sep 17 00:00:00 2001 From: althafvly Date: Tue, 18 Jun 2024 10:41:04 +0530 Subject: [PATCH 3/6] parental: Remove unused codes --- app/src/main/AndroidManifest.xml | 5 -- .../e/parentalcontrol/utils/SystemUtils.kt | 54 ------------------- 2 files changed, 59 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c663144..7c7cc41 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/utils/SystemUtils.kt b/app/src/main/java/foundation/e/parentalcontrol/utils/SystemUtils.kt index 686613d..6ee6196 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 = -- GitLab From 1c49b3c6bd77e0dd3042f294796df8cf440caeb1 Mon Sep 17 00:00:00 2001 From: althafvly Date: Tue, 18 Jun 2024 10:53:08 +0530 Subject: [PATCH 4/6] parental: Update version --- app/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2cfc0bb..70c1c61 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 { -- GitLab From 0d5ecf1fccff5aea7dd6f5e47b7cfcebb376aafd Mon Sep 17 00:00:00 2001 From: althafvly Date: Tue, 18 Jun 2024 23:29:45 +0530 Subject: [PATCH 5/6] parental: Reset sharedpref on temp activate --- app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt index 99f847a..2d8bbd7 100644 --- a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt +++ b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt @@ -549,6 +549,7 @@ class MainActivity : ComponentActivity() { isChecked = checkedState, onCheckedChange = { checkedState = it + PrefsUtils.clearAll() coroutineScope.launch { delay(200) moveToNext = true -- GitLab From fb54e1b5bb80b2bfd00e851f29ff06d0624ed455 Mon Sep 17 00:00:00 2001 From: althafvly Date: Tue, 18 Jun 2024 23:29:45 +0530 Subject: [PATCH 6/6] parental: Don't allow to activate with accounts added --- .../e/parentalcontrol/MainActivity.kt | 58 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 2 files changed, 59 insertions(+) diff --git a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt index 2d8bbd7..b4259e5 100644 --- a/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt +++ b/app/src/main/java/foundation/e/parentalcontrol/MainActivity.kt @@ -7,6 +7,7 @@ */ package foundation.e.parentalcontrol +import android.accounts.AccountManager import android.app.admin.DevicePolicyManager import android.content.Context import android.content.Intent @@ -411,6 +412,12 @@ class MainActivity : ComponentActivity() { return dA.isAdminActive(mActivity) } + private fun noAccountsLoggedIn(): Boolean { + val accountManager = AccountManager.get(mActivity) + val accounts = accountManager.accounts + return accounts.isEmpty() + } + @Composable fun TempActivateAdmin() { BackHandler(onBack = { onExitApp() }) @@ -482,6 +489,57 @@ class MainActivity : ComponentActivity() { ) } + if (!noAccountsLoggedIn()) { + 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.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) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f6f81a4..60a149c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -65,4 +65,5 @@ "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 -- GitLab