Optimize start/stop lock task mode flow

Optimize Package selector
This commit is contained in:
BinTianqi
2024-12-21 20:07:32 +08:00
parent 873896ec10
commit 84c1dff9e6
16 changed files with 216 additions and 285 deletions

View File

@@ -50,7 +50,6 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableIntState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@@ -74,37 +73,37 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.bintianqi.owndroid.InstallAppActivity
import com.bintianqi.owndroid.MyViewModel
import com.bintianqi.owndroid.PackageInstallerReceiver
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.fileUriFlow
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.InfoCard
import com.bintianqi.owndroid.ui.Information
import com.bintianqi.owndroid.ui.ListItem
import com.bintianqi.owndroid.ui.NavIcon
import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.SwitchItem
import java.util.concurrent.Executors
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ApplicationManage(navCtrl:NavHostController, dialogStatus: MutableIntState) {
fun ApplicationManage(navCtrl:NavHostController, vm: MyViewModel) {
val focusMgr = LocalFocusManager.current
val localNavCtrl = rememberNavController()
var pkgName by rememberSaveable { mutableStateOf("") }
val updatePackage by selectedPackage.collectAsState()
val updatePackage by vm.selectedPackage.collectAsStateWithLifecycle()
LaunchedEffect(updatePackage) {
if(updatePackage != "") {
pkgName = updatePackage
selectedPackage.value = ""
vm.selectedPackage.value = ""
}
}
Scaffold(
@@ -145,9 +144,7 @@ fun ApplicationManage(navCtrl:NavHostController, dialogStatus: MutableIntState)
popEnterTransition = Animations.navHostPopEnterTransition,
popExitTransition = Animations.navHostPopExitTransition
) {
composable(route = "Home") {
Home(localNavCtrl, pkgName, dialogStatus)
}
composable(route = "Home") { Home(localNavCtrl, pkgName) }
composable(route = "UserControlDisabled") { UserCtrlDisabledPkg(pkgName) }
composable(route = "PermissionManage") { PermissionManage(pkgName) }
composable(route = "CrossProfilePackage") { CrossProfilePkg(pkgName) }
@@ -160,23 +157,11 @@ fun ApplicationManage(navCtrl:NavHostController, dialogStatus: MutableIntState)
composable(route = "UninstallApp") { UninstallApp(pkgName) }
}
}
when(dialogStatus.intValue) {
0 -> {}
1 -> EnableSystemAppDialog(dialogStatus, pkgName)
2 -> ClearAppDataDialog(dialogStatus, pkgName)
3 -> DefaultDialerAppDialog(dialogStatus, pkgName)
}
LaunchedEffect(dialogStatus.intValue) {
focusMgr.clearFocus()
}
}
@Composable
private fun Home(
navCtrl:NavHostController,
pkgName: String,
dialogStatus: MutableIntState
) {
private fun Home(navCtrl:NavHostController, pkgName: String) {
var dialogStatus by remember { mutableIntStateOf(0) }
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
@@ -190,7 +175,6 @@ private fun Home(
hide = dpm.isApplicationHidden(receiver, pkgName)
var blockUninstall by remember { mutableStateOf(false) }
blockUninstall = dpm.isUninstallBlocked(receiver,pkgName)
var appControlDialog by remember { mutableStateOf(false) }
var appControlAction by remember { mutableIntStateOf(0) }
val focusMgr = LocalFocusManager.current
val appControl: (Boolean) -> Unit = {
@@ -226,20 +210,20 @@ private fun Home(
title = R.string.suspend, desc = "", icon = R.drawable.block_fill0,
state = suspend,
onCheckedChange = { appControlAction = 1; appControl(it) },
onClickBlank = { appControlAction = 1; appControlDialog = true }
onClickBlank = { appControlAction = 1; dialogStatus = 4 }
)
}
SwitchItem(
title = R.string.hide, desc = stringResource(R.string.isapphidden_desc), icon = R.drawable.visibility_off_fill0,
state = hide,
onCheckedChange = { appControlAction = 2; appControl(it) },
onClickBlank = { appControlAction = 2; appControlDialog = true }
onClickBlank = { appControlAction = 2; dialogStatus = 4 }
)
SwitchItem(
title = R.string.block_uninstall, desc = "", icon = R.drawable.delete_forever_fill0,
state = blockUninstall,
onCheckedChange = { appControlAction = 3; appControl(it) },
onClickBlank = { appControlAction = 3; appControlDialog = true }
onClickBlank = { appControlAction = 3; dialogStatus = 4 }
)
if((VERSION.SDK_INT >= 33 && profileOwner) || (VERSION.SDK_INT >= 30 && deviceOwner)) {
FunctionItem(R.string.ucd, "", R.drawable.do_not_touch_fill0) { navCtrl.navigate("UserControlDisabled") }
@@ -259,32 +243,124 @@ private fun Home(
FunctionItem(R.string.permitted_accessibility_services, "", R.drawable.settings_accessibility_fill0) { navCtrl.navigate("Accessibility") }
FunctionItem(R.string.permitted_ime, "", R.drawable.keyboard_fill0) { navCtrl.navigate("IME") }
FunctionItem(R.string.enable_system_app, "", R.drawable.enable_fill0) {
if(pkgName != "") dialogStatus.intValue = 1
if(pkgName != "") dialogStatus = 1
}
if(VERSION.SDK_INT >= 28 && deviceOwner) {
FunctionItem(R.string.keep_uninstalled_packages, "", R.drawable.delete_fill0) { navCtrl.navigate("KeepUninstalled") }
}
if(VERSION.SDK_INT >= 28) {
FunctionItem(R.string.clear_app_storage, "", R.drawable.mop_fill0) {
if(pkgName != "") dialogStatus.intValue = 2
if(pkgName != "") dialogStatus = 2
}
}
FunctionItem(R.string.install_app, "", R.drawable.install_mobile_fill0) { navCtrl.navigate("InstallApp") }
FunctionItem(R.string.uninstall_app, "", R.drawable.delete_fill0) { navCtrl.navigate("UninstallApp") }
if(VERSION.SDK_INT >= 34 && (deviceOwner || dpm.isOrgProfile(receiver))) {
FunctionItem(R.string.set_default_dialer, "", R.drawable.call_fill0) {
if(pkgName != "") dialogStatus.intValue = 3
if(pkgName != "") dialogStatus = 3
}
}
Spacer(Modifier.padding(vertical = 30.dp))
LaunchedEffect(Unit) { fileUriFlow.value = Uri.parse("") }
}
if(appControlDialog) {
if(dialogStatus == 1) AlertDialog(
title = { Text(stringResource(R.string.enable_system_app)) },
text = {
Text(stringResource(R.string.enable_system_app_desc) + "\n" + pkgName)
},
onDismissRequest = { dialogStatus = 0 },
dismissButton = {
TextButton(onClick = { dialogStatus = 0 }) {
Text(stringResource(R.string.cancel))
}
},
confirmButton = {
TextButton(
onClick = {
try {
dpm.enableSystemApp(receiver, pkgName)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
} catch(_: IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
dialogStatus = 0
}
) {
Text(stringResource(R.string.confirm))
}
},
modifier = Modifier.fillMaxWidth()
)
if(dialogStatus == 2 && VERSION.SDK_INT >= 28) AlertDialog(
title = { Text(text = stringResource(R.string.clear_app_storage)) },
text = {
Text(stringResource(R.string.app_storage_will_be_cleared) + "\n" + pkgName)
},
confirmButton = {
TextButton(
onClick = {
val executor = Executors.newCachedThreadPool()
val onClear = DevicePolicyManager.OnClearApplicationUserDataListener { pkg: String, succeed: Boolean ->
Looper.prepare()
val toastText =
if(pkg!="") { "$pkg\n" }else{ "" } +
context.getString(R.string.clear_data) +
context.getString(if(succeed) R.string.success else R.string.failed )
Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()
Looper.loop()
}
dpm.clearApplicationUserData(receiver, pkgName, executor, onClear)
dialogStatus = 0
},
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
) {
Text(text = stringResource(R.string.clear))
}
},
dismissButton = {
TextButton(
onClick = { dialogStatus = 0 }
) {
Text(text = stringResource(R.string.cancel))
}
},
onDismissRequest = { dialogStatus = 0 },
modifier = Modifier.fillMaxWidth()
)
if(dialogStatus == 3 && VERSION.SDK_INT >= 34) AlertDialog(
title = { Text(stringResource(R.string.set_default_dialer)) },
text = {
Text(stringResource(R.string.app_will_be_default_dialer) + "\n" + pkgName)
},
onDismissRequest = { dialogStatus = 0 },
dismissButton = {
TextButton(onClick = { dialogStatus = 0 }) {
Text(stringResource(R.string.cancel))
}
},
confirmButton = {
TextButton(
onClick = {
try{
dpm.setDefaultDialerApplication(pkgName)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
} catch(_: IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
dialogStatus = 0
}
) {
Text(stringResource(R.string.confirm))
}
},
modifier = Modifier.fillMaxWidth()
)
if(dialogStatus == 4) {
LaunchedEffect(Unit) {
focusMgr.clearFocus()
}
AlertDialog(
onDismissRequest = { appControlDialog = false },
onDismissRequest = { dialogStatus = 0 },
title = {
Text(
text = stringResource(
@@ -316,7 +392,7 @@ private fun Home(
TextButton(
onClick = {
appControl(true)
appControlDialog = false
dialogStatus = 0
}
) {
Text(text = stringResource(R.string.enable))
@@ -326,7 +402,7 @@ private fun Home(
TextButton(
onClick = {
appControl(false)
appControlDialog = false
dialogStatus = 0
}
) {
Text(text = stringResource(R.string.disable))
@@ -334,6 +410,7 @@ private fun Home(
}
)
}
LaunchedEffect(dialogStatus) { focusMgr.clearFocus() }
}
@@ -697,9 +774,7 @@ private fun PermittedAccessibility(pkgName: String) {
}
}
}
Information {
Text(stringResource(R.string.system_accessibility_always_allowed))
}
InfoCard(R.string.system_accessibility_always_allowed)
Spacer(Modifier.padding(vertical = 30.dp))
}
}
@@ -755,9 +830,7 @@ private fun PermittedIME(pkgName: String) {
}
}
}
Information {
Text(stringResource(R.string.system_ime_always_allowed))
}
InfoCard(R.string.system_ime_always_allowed)
Spacer(Modifier.padding(vertical = 30.dp))
}
}
@@ -892,117 +965,3 @@ private fun InstallApp() {
}
}
}
@SuppressLint("NewApi")
@Composable
private fun ClearAppDataDialog(status: MutableIntState, pkgName: String) {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
AlertDialog(
title = { Text(text = stringResource(R.string.clear_app_storage)) },
text = {
Text(stringResource(R.string.app_storage_will_be_cleared) + "\n" + pkgName)
},
confirmButton = {
TextButton(
onClick = {
val executor = Executors.newCachedThreadPool()
val onClear = DevicePolicyManager.OnClearApplicationUserDataListener { pkg: String, succeed: Boolean ->
Looper.prepare()
val toastText =
if(pkg!="") { "$pkg\n" }else{ "" } +
context.getString(R.string.clear_data) +
context.getString(if(succeed) R.string.success else R.string.failed )
Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()
Looper.loop()
}
dpm.clearApplicationUserData(receiver, pkgName, executor, onClear)
status.intValue = 0
},
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
) {
Text(text = stringResource(R.string.clear))
}
},
dismissButton = {
TextButton(
onClick = { status.intValue = 0 }
) {
Text(text = stringResource(R.string.cancel))
}
},
onDismissRequest = { status.intValue = 0 },
modifier = Modifier.fillMaxWidth()
)
}
@SuppressLint("NewApi")
@Composable
private fun DefaultDialerAppDialog(status: MutableIntState, pkgName: String) {
val context = LocalContext.current
val dpm = context.getDPM()
AlertDialog(
title = { Text(stringResource(R.string.set_default_dialer)) },
text = {
Text(stringResource(R.string.app_will_be_default_dialer) + "\n" + pkgName)
},
onDismissRequest = { status.intValue = 0 },
dismissButton = {
TextButton(onClick = { status.intValue = 0 }) {
Text(stringResource(R.string.cancel))
}
},
confirmButton = {
TextButton(
onClick = {
try{
dpm.setDefaultDialerApplication(pkgName)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}catch(_: IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
status.intValue = 0
}
) {
Text(stringResource(R.string.confirm))
}
},
modifier = Modifier.fillMaxWidth()
)
}
@Composable
private fun EnableSystemAppDialog(status: MutableIntState, pkgName: String) {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
AlertDialog(
title = { Text(stringResource(R.string.enable_system_app)) },
text = {
Text(stringResource(R.string.enable_system_app_desc) + "\n" + pkgName)
},
onDismissRequest = { status.intValue = 0 },
dismissButton = {
TextButton(onClick = { status.intValue = 0 }) {
Text(stringResource(R.string.cancel))
}
},
confirmButton = {
TextButton(
onClick = {
try {
dpm.enableSystemApp(receiver, pkgName)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
} catch(_: IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
status.intValue = 0
}
) {
Text(stringResource(R.string.confirm))
}
},
modifier = Modifier.fillMaxWidth()
)
}

View File

@@ -92,12 +92,12 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.navigation.NavHostController
import com.bintianqi.owndroid.MyViewModel
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.exportFile
import com.bintianqi.owndroid.exportFilePath
import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.isExportingSecurityOrNetworkLogs
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.InfoCard
@@ -400,7 +400,7 @@ fun PrivateDNS(navCtrl: NavHostController) {
@SuppressLint("NewApi")
@Composable
fun AlwaysOnVPNPackage(navCtrl: NavHostController) {
fun AlwaysOnVPNPackage(navCtrl: NavHostController, vm: MyViewModel) {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
@@ -409,11 +409,11 @@ fun AlwaysOnVPNPackage(navCtrl: NavHostController) {
val focusMgr = LocalFocusManager.current
val refresh = { pkgName = dpm.getAlwaysOnVpnPackage(receiver) ?: "" }
LaunchedEffect(Unit) { refresh() }
val updatePackage by selectedPackage.collectAsState()
val updatePackage by vm.selectedPackage.collectAsState()
LaunchedEffect(updatePackage) {
if(selectedPackage.value != "") {
pkgName = selectedPackage.value
selectedPackage.value = ""
if(updatePackage != "") {
pkgName = updatePackage
vm.selectedPackage.value = ""
}
}
val setAlwaysOnVpn: (String?, Boolean)->Boolean = { vpnPkg: String?, lockdownEnabled: Boolean ->

View File

@@ -75,7 +75,6 @@ import com.bintianqi.owndroid.ui.CardItem
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.InfoCard
import com.bintianqi.owndroid.ui.Information
import com.bintianqi.owndroid.ui.MyScaffold
import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.yesOrNo
@@ -303,7 +302,7 @@ fun ResetPasswordToken(navCtrl: NavHostController) {
}
}
Spacer(Modifier.padding(vertical = 5.dp))
Information{ Text(stringResource(R.string.activate_token_not_required_when_no_password)) }
InfoCard(R.string.activate_token_not_required_when_no_password)
}
}

View File

@@ -3,9 +3,6 @@ package com.bintianqi.owndroid.dpm
import android.annotation.SuppressLint
import android.app.ActivityOptions
import android.app.AlertDialog
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.admin.DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY
import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK
@@ -107,10 +104,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.core.app.NotificationCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import com.bintianqi.owndroid.MyViewModel
import com.bintianqi.owndroid.NotificationUtils
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.StopLockTaskModeReceiver
import com.bintianqi.owndroid.exportFile
import com.bintianqi.owndroid.exportFilePath
import com.bintianqi.owndroid.fileUriFlow
@@ -118,13 +116,10 @@ import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.isExportingSecurityOrNetworkLogs
import com.bintianqi.owndroid.prepareForNotification
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.toggle
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.InfoCard
import com.bintianqi.owndroid.ui.Information
import com.bintianqi.owndroid.ui.ListItem
import com.bintianqi.owndroid.ui.MyScaffold
import com.bintianqi.owndroid.ui.RadioButtonItem
@@ -522,9 +517,7 @@ fun ChangeTimeZone(navCtrl: NavHostController) {
Text(stringResource(R.string.apply))
}
Spacer(Modifier.padding(vertical = 10.dp))
Information {
Text(stringResource(R.string.disable_auto_time_zone_before_set))
}
InfoCard(R.string.disable_auto_time_zone_before_set)
}
if(dialog) AlertDialog(
text = {
@@ -700,12 +693,11 @@ fun NearbyStreamingPolicy(navCtrl: NavHostController) {
@SuppressLint("NewApi")
@Composable
fun LockTaskMode(navCtrl: NavHostController) {
fun LockTaskMode(navCtrl: NavHostController, vm: MyViewModel) {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current
val coroutine = rememberCoroutineScope()
var appSelectorRequest by rememberSaveable { mutableIntStateOf(0) }
MyScaffold(R.string.lock_task_mode, 8.dp, navCtrl, false) {
val lockTaskFeatures = remember { mutableStateListOf<Int>() }
@@ -784,11 +776,11 @@ fun LockTaskMode(navCtrl: NavHostController) {
lockTaskFeatures.forEach { result += it }
}
try {
dpm.setLockTaskFeatures(receiver,result)
dpm.setLockTaskFeatures(receiver, result)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
} catch (e: IllegalArgumentException) {
AlertDialog.Builder(context)
.setTitle("Error")
.setTitle(R.string.error)
.setMessage(e.message)
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
.show()
@@ -863,11 +855,11 @@ fun LockTaskMode(navCtrl: NavHostController) {
var startLockTaskApp by rememberSaveable { mutableStateOf("") }
var startLockTaskActivity by rememberSaveable { mutableStateOf("") }
var specifyActivity by rememberSaveable { mutableStateOf(false) }
val updatePackage by selectedPackage.collectAsState()
val updatePackage by vm.selectedPackage.collectAsStateWithLifecycle()
LaunchedEffect(updatePackage) {
if(updatePackage != "") {
if(appSelectorRequest == 1) inputLockTaskPkg = updatePackage else startLockTaskApp = updatePackage
selectedPackage.value = ""
vm.selectedPackage.value = ""
}
}
Spacer(Modifier.padding(vertical = 10.dp))
@@ -906,7 +898,8 @@ fun LockTaskMode(navCtrl: NavHostController) {
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
if(!dpm.getLockTaskPackages(receiver).contains(startLockTaskApp)) {
if(!NotificationUtils.checkPermission(context)) return@Button
if(!dpm.isLockTaskPermitted(startLockTaskApp)) {
Toast.makeText(context, R.string.app_not_allowed, Toast.LENGTH_SHORT).show()
return@Button
}
@@ -915,13 +908,7 @@ fun LockTaskMode(navCtrl: NavHostController) {
val launchIntent = if(specifyActivity) Intent().setComponent(ComponentName(startLockTaskApp, startLockTaskActivity))
else packageManager.getLaunchIntentForPackage(startLockTaskApp)
if (launchIntent != null) {
coroutine.launch {
prepareForNotification(context) {
sendStopLockTaskNotification(context)
context.startActivity(launchIntent, options.toBundle())
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}
}
context.startActivity(launchIntent, options.toBundle())
} else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
@@ -1497,23 +1484,3 @@ fun InstallSystemUpdate(navCtrl: NavHostController) {
InfoCard(R.string.auto_reboot_after_install_succeed)
}
}
@SuppressLint("NewApi")
private fun sendStopLockTaskNotification(context: Context) {
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (VERSION.SDK_INT >= 26) {
val channel = NotificationChannel("LockTaskMode", context.getString(R.string.lock_task_mode), NotificationManager.IMPORTANCE_HIGH).apply {
description = "Notification channel for stop lock task mode"
setShowBadge(false)
}
nm.createNotificationChannel(channel)
}
val intent = Intent(context, StopLockTaskModeReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val builder = NotificationCompat.Builder(context, "LockTaskMode")
.setContentTitle(context.getText(R.string.lock_task_mode))
.setSmallIcon(R.drawable.lock_fill0)
.addAction(NotificationCompat.Action.Builder(R.drawable.lock_fill0, context.getText(R.string.stop), pendingIntent).build())
.setPriority(NotificationCompat.PRIORITY_HIGH)
nm.notify(1, builder.build())
}