feat: 'Show a notification to exit' option for lock task mode

This commit is contained in:
BinTianqi
2025-12-21 21:27:34 +08:00
parent 88da62e65d
commit 5f95aa81c0
4 changed files with 36 additions and 38 deletions

View File

@@ -2,7 +2,6 @@ package com.bintianqi.owndroid
import android.accounts.Account import android.accounts.Account
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.ActivityOptions import android.app.ActivityOptions
import android.app.Application import android.app.Application
import android.app.KeyguardManager import android.app.KeyguardManager
@@ -874,12 +873,22 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
getLockTaskPackages() getLockTaskPackages()
} }
@RequiresApi(28) @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)) { if (!DPM.isLockTaskPermitted(packageName)) {
val list = lockTaskPackages.value.map { it.name } + packageName val list = lockTaskPackages.value.map { it.name } + packageName
DPM.setLockTaskPackages(DAR, list.toTypedArray()) DPM.setLockTaskPackages(DAR, list.toTypedArray())
getLockTaskPackages() 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 options = ActivityOptions.makeBasic().setLockTaskEnabled(true)
val intent = if(activity.isNotEmpty()) { val intent = if(activity.isNotEmpty()) {
Intent().setComponent(ComponentName(packageName, activity)) 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) or (if (clearTask) Intent.FLAG_ACTIVITY_CLEAR_TASK else 0)
) )
application.startActivity(intent, options.toBundle()) application.startActivity(intent, options.toBundle())
if (showNotification) {
application.startForegroundService(Intent(application, LockTaskService::class.java)) application.startForegroundService(Intent(application, LockTaskService::class.java))
}
return true return true
} else { } else {
return false return false

View File

@@ -31,7 +31,6 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row 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.draw.clip
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType 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.Privilege
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.SP import com.bintianqi.owndroid.SP
import com.bintianqi.owndroid.adaptiveInsets
import com.bintianqi.owndroid.clickableTextField import com.bintianqi.owndroid.clickableTextField
import com.bintianqi.owndroid.formatDate import com.bintianqi.owndroid.formatDate
import com.bintianqi.owndroid.adaptiveInsets
import com.bintianqi.owndroid.popToast import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
@@ -1151,7 +1149,8 @@ fun NearbyStreamingPolicyScreen(
fun LockTaskModeScreen( fun LockTaskModeScreen(
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
lockTaskPackages: StateFlow<List<AppInfo>>, getLockTaskPackages: () -> Unit, lockTaskPackages: StateFlow<List<AppInfo>>, 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 getLockTaskFeatures: () -> Int, setLockTaskFeature: (Int) -> String?, onNavigateUp: () -> Unit
) { ) {
val coroutine = rememberCoroutineScope() val coroutine = rememberCoroutineScope()
@@ -1206,7 +1205,7 @@ fun LockTaskModeScreen(
@RequiresApi(28) @RequiresApi(28)
@Composable @Composable
private fun StartLockTaskMode( private fun StartLockTaskMode(
startLockTaskMode: (String, String, Boolean) -> Boolean, startLockTaskMode: (String, String, Boolean, Boolean) -> Boolean,
chosenPackage: Channel<String>, onChoosePackage: () -> Unit chosenPackage: Channel<String>, onChoosePackage: () -> Unit
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -1216,44 +1215,28 @@ private fun StartLockTaskMode(
var activity by rememberSaveable { mutableStateOf("") } var activity by rememberSaveable { mutableStateOf("") }
var specifyActivity by rememberSaveable { mutableStateOf(false) } var specifyActivity by rememberSaveable { mutableStateOf(false) }
var clearTask by rememberSaveable { mutableStateOf(true) } var clearTask by rememberSaveable { mutableStateOf(true) }
var showNotification by rememberSaveable() { mutableStateOf(true) }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
packageName = chosenPackage.receive() packageName = chosenPackage.receive()
} }
Column( Column(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = HorizontalPadding)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
Spacer(Modifier.height(5.dp)) PackageNameTextField(
PackageNameTextField(packageName, onChoosePackage) { packageName = it } 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( Row(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 8.dp), .padding(start = 4.dp, top = 4.dp, end = HorizontalPadding, bottom = 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),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Checkbox(specifyActivity, { Checkbox(specifyActivity, {
@@ -1273,15 +1256,16 @@ private fun StartLockTaskMode(
Button( Button(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 5.dp), .padding(horizontal = HorizontalPadding),
onClick = { onClick = {
val result = startLockTaskMode(packageName, activity, clearTask) val result = startLockTaskMode(packageName, activity, clearTask, showNotification)
if (!result) context.showOperationResultToast(false) if (!result) context.showOperationResultToast(false)
}, },
enabled = packageName.isNotBlank() && (!specifyActivity || activity.isNotBlank()) enabled = packageName.isNotBlank() && (!specifyActivity || activity.isNotBlank())
) { ) {
Text(stringResource(R.string.start)) Text(stringResource(R.string.start))
} }
Spacer(Modifier.height(5.dp))
if (!privilege.dhizuku) Notes(R.string.info_start_lock_task_mode) if (!privilege.dhizuku) Notes(R.string.info_start_lock_task_mode)
} }
} }

View File

@@ -173,6 +173,8 @@
<string name="nearby_notification_streaming">附近通知传输</string> <string name="nearby_notification_streaming">附近通知传输</string>
<string name="enable_if_secure_enough">在足够安全时启用</string> <string name="enable_if_secure_enough">在足够安全时启用</string>
<string name="lock_task_mode">锁定任务模式</string> <string name="lock_task_mode">锁定任务模式</string>
<string name="lock_task_mode_start_clear_task">清除任务(新实例)</string>
<string name="lock_taso_mode_show_notification">显示通知以退出</string>
<string name="app_not_allowed">应用未被允许</string> <string name="app_not_allowed">应用未被允许</string>
<string name="disable_all">禁用全部</string> <string name="disable_all">禁用全部</string>
<string name="ltf_sys_info">允许状态栏信息</string> <string name="ltf_sys_info">允许状态栏信息</string>

View File

@@ -201,6 +201,8 @@
<string name="nearby_notification_streaming">Nearby notification streaming policy</string> <string name="nearby_notification_streaming">Nearby notification streaming policy</string>
<string name="enable_if_secure_enough">Same managed account only</string> <string name="enable_if_secure_enough">Same managed account only</string>
<string name="lock_task_mode">Lock task mode</string> <string name="lock_task_mode">Lock task mode</string>
<string name="lock_task_mode_start_clear_task">Clear task (start fresh)</string>
<string name="lock_taso_mode_show_notification">Show a notification to exit</string>
<string name="app_not_allowed">App is not allowed</string> <string name="app_not_allowed">App is not allowed</string>
<string name="disable_all">Disable all</string> <string name="disable_all">Disable all</string>
<!--ltf: lock task feature--> <!--ltf: lock task feature-->
@@ -732,5 +734,4 @@
<string name="activate_method">Activate method</string> <string name="activate_method">Activate method</string>
<string name="adb_command">ADB command</string> <string name="adb_command">ADB command</string>
<string name="owndroid_warning">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.</string> <string name="owndroid_warning">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.</string>
<string name="lock_task_mode_start_clear_task">Clear task (start fresh)</string>
</resources> </resources>