From 5f95aa81c00d31b992d33923f8b047d7cb90efe2 Mon Sep 17 00:00:00 2001 From: BinTianqi Date: Sun, 21 Dec 2025 21:27:34 +0800 Subject: [PATCH] feat: 'Show a notification to exit' option for lock task mode --- .../com/bintianqi/owndroid/MyViewModel.kt | 17 ++++-- .../java/com/bintianqi/owndroid/dpm/System.kt | 52 +++++++------------ app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values/strings.xml | 3 +- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt index f82b5cc..2b9debb 100644 --- a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt +++ b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt @@ -2,7 +2,6 @@ package com.bintianqi.owndroid import android.accounts.Account import android.annotation.SuppressLint -import android.app.ActivityManager import android.app.ActivityOptions import android.app.Application import android.app.KeyguardManager @@ -874,12 +873,22 @@ class MyViewModel(application: Application): AndroidViewModel(application) { getLockTaskPackages() } @RequiresApi(28) - fun startLockTaskMode(packageName: String, activity: String, clearTask: Boolean): Boolean { + fun startLockTaskMode( + packageName: String, activity: String, clearTask: Boolean, showNotification: Boolean + ): Boolean { if (!DPM.isLockTaskPermitted(packageName)) { val list = lockTaskPackages.value.map { it.name } + packageName DPM.setLockTaskPackages(DAR, list.toTypedArray()) getLockTaskPackages() } + if (showNotification) { + DPM.setLockTaskFeatures( + DAR, + DPM.getLockTaskFeatures(DAR) or + DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS or + DevicePolicyManager.LOCK_TASK_FEATURE_HOME + ) + } val options = ActivityOptions.makeBasic().setLockTaskEnabled(true) val intent = if(activity.isNotEmpty()) { Intent().setComponent(ComponentName(packageName, activity)) @@ -890,7 +899,9 @@ class MyViewModel(application: Application): AndroidViewModel(application) { or (if (clearTask) Intent.FLAG_ACTIVITY_CLEAR_TASK else 0) ) application.startActivity(intent, options.toBundle()) - application.startForegroundService(Intent(application, LockTaskService::class.java)) + if (showNotification) { + application.startForegroundService(Intent(application, LockTaskService::class.java)) + } return true } else { return false diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/System.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/System.kt index 4f361fd..64bcbab 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/System.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/System.kt @@ -31,7 +31,6 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -97,7 +96,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType @@ -110,9 +108,9 @@ import com.bintianqi.owndroid.MyViewModel import com.bintianqi.owndroid.Privilege import com.bintianqi.owndroid.R import com.bintianqi.owndroid.SP +import com.bintianqi.owndroid.adaptiveInsets import com.bintianqi.owndroid.clickableTextField import com.bintianqi.owndroid.formatDate -import com.bintianqi.owndroid.adaptiveInsets import com.bintianqi.owndroid.popToast import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.ui.CheckBoxItem @@ -1151,7 +1149,8 @@ fun NearbyStreamingPolicyScreen( fun LockTaskModeScreen( chosenPackage: Channel, onChoosePackage: () -> Unit, lockTaskPackages: StateFlow>, getLockTaskPackages: () -> Unit, - setLockTaskPackage: (String, Boolean) -> Unit, startLockTaskMode: (String, String, Boolean) -> Boolean, + setLockTaskPackage: (String, Boolean) -> Unit, + startLockTaskMode: (String, String, Boolean, Boolean) -> Boolean, getLockTaskFeatures: () -> Int, setLockTaskFeature: (Int) -> String?, onNavigateUp: () -> Unit ) { val coroutine = rememberCoroutineScope() @@ -1206,7 +1205,7 @@ fun LockTaskModeScreen( @RequiresApi(28) @Composable private fun StartLockTaskMode( - startLockTaskMode: (String, String, Boolean) -> Boolean, + startLockTaskMode: (String, String, Boolean, Boolean) -> Boolean, chosenPackage: Channel, onChoosePackage: () -> Unit ) { val context = LocalContext.current @@ -1216,44 +1215,28 @@ private fun StartLockTaskMode( var activity by rememberSaveable { mutableStateOf("") } var specifyActivity by rememberSaveable { mutableStateOf(false) } var clearTask by rememberSaveable { mutableStateOf(true) } - + var showNotification by rememberSaveable() { mutableStateOf(true) } LaunchedEffect(Unit) { packageName = chosenPackage.receive() } Column( Modifier .fillMaxWidth() - .padding(horizontal = HorizontalPadding) .verticalScroll(rememberScrollState()) ) { - Spacer(Modifier.height(5.dp)) - PackageNameTextField(packageName, onChoosePackage) { packageName = it } + PackageNameTextField( + packageName, onChoosePackage, Modifier.padding(HorizontalPadding, 8.dp) + ) { packageName = it } + FullWidthCheckBoxItem( + R.string.lock_task_mode_start_clear_task, clearTask + ) { clearTask = it } + FullWidthCheckBoxItem( + R.string.lock_taso_mode_show_notification, showNotification + ) { showNotification = it } Row( Modifier .fillMaxWidth() - .padding(top = 8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox( - checked = clearTask, - onCheckedChange = { clearTask = it } - ) - Text( - text = stringResource(R.string.lock_task_mode_start_clear_task), - modifier = Modifier - .padding(start = 8.dp) - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { - clearTask = !clearTask - } - ) - } - Row( - Modifier - .fillMaxWidth() - .padding(bottom = 4.dp), + .padding(start = 4.dp, top = 4.dp, end = HorizontalPadding, bottom = 8.dp), verticalAlignment = Alignment.CenterVertically ) { Checkbox(specifyActivity, { @@ -1273,15 +1256,16 @@ private fun StartLockTaskMode( Button( modifier = Modifier .fillMaxWidth() - .padding(bottom = 5.dp), + .padding(horizontal = HorizontalPadding), onClick = { - val result = startLockTaskMode(packageName, activity, clearTask) + val result = startLockTaskMode(packageName, activity, clearTask, showNotification) if (!result) context.showOperationResultToast(false) }, enabled = packageName.isNotBlank() && (!specifyActivity || activity.isNotBlank()) ) { Text(stringResource(R.string.start)) } + Spacer(Modifier.height(5.dp)) if (!privilege.dhizuku) Notes(R.string.info_start_lock_task_mode) } } diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index b67a883..3b95803 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -173,6 +173,8 @@ 附近通知传输 在足够安全时启用 锁定任务模式 + 清除任务(新实例) + 显示通知以退出 应用未被允许 禁用全部 允许状态栏信息 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 31ff108..9add4f7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -201,6 +201,8 @@ Nearby notification streaming policy Same managed account only Lock task mode + Clear task (start fresh) + Show a notification to exit App is not allowed Disable all @@ -732,5 +734,4 @@ Activate method ADB command This app uses Device owner or Profile owner privileges. These privileges are extremely dangerous, please use them with caution. If used improperly, they may result in severe losses. The developers will not be responsible for this. - Clear task (start fresh)