mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
App manager: show a dialog when click suspend, hide, block uninstall or always-on vpn
raise pkgName state to save it
This commit is contained in:
@@ -22,7 +22,7 @@ android {
|
||||
versionCode = 26
|
||||
versionName = "5.1"
|
||||
multiDexEnabled = false
|
||||
//signingConfig = signingConfigs.getByName("testkey")
|
||||
signingConfig = signingConfigs.getByName("testkey")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@@ -21,8 +22,7 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@@ -60,6 +60,7 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UnrememberedMutableState")
|
||||
@ExperimentalMaterial3Api
|
||||
@Composable
|
||||
fun MyScaffold(){
|
||||
@@ -69,6 +70,8 @@ fun MyScaffold(){
|
||||
val myComponent = ComponentName(myContext,Receiver::class.java)
|
||||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
val focusMgr = LocalFocusManager.current
|
||||
val pkgName = mutableStateOf("")
|
||||
val dialogStatus = mutableIntStateOf(0)
|
||||
SetDarkTheme()
|
||||
LaunchedEffect(Unit){
|
||||
while(true){
|
||||
@@ -89,17 +92,17 @@ fun MyScaffold(){
|
||||
popEnterTransition = Animations.navHostPopEnterTransition,
|
||||
popExitTransition = Animations.navHostPopExitTransition
|
||||
){
|
||||
composable(route = "HomePage", content = { HomePage(navCtrl)})
|
||||
composable(route = "HomePage", content = { HomePage(navCtrl, pkgName)})
|
||||
composable(route = "SystemManage", content = { SystemManage(navCtrl) })
|
||||
composable(route = "ManagedProfile", content = {ManagedProfile(navCtrl)})
|
||||
composable(route = "Permissions", content = { DpmPermissions(navCtrl)})
|
||||
composable(route = "ApplicationManage", content = { ApplicationManage(navCtrl)})
|
||||
composable(route = "ApplicationManage", content = { ApplicationManage(navCtrl, pkgName, dialogStatus)})
|
||||
composable(route = "UserRestriction", content = { UserRestriction(navCtrl)})
|
||||
composable(route = "UserManage", content = { UserManage(navCtrl)})
|
||||
composable(route = "Password", content = { Password(navCtrl)})
|
||||
composable(route = "AppSetting", content = { AppSetting(navCtrl)})
|
||||
composable(route = "Network", content = {Network(navCtrl)})
|
||||
composable(route = "PackageSelector"){PackageSelector(navCtrl)}
|
||||
composable(route = "PackageSelector"){PackageSelector(navCtrl, pkgName)}
|
||||
composable(route = "PermissionPicker"){PermissionPicker(navCtrl)}
|
||||
}
|
||||
LaunchedEffect(Unit){
|
||||
@@ -114,7 +117,7 @@ fun MyScaffold(){
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HomePage(navCtrl:NavHostController){
|
||||
private fun HomePage(navCtrl:NavHostController, pkgName: MutableState<String>){
|
||||
val myContext = LocalContext.current
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,Receiver::class.java)
|
||||
@@ -125,6 +128,7 @@ private fun HomePage(navCtrl:NavHostController){
|
||||
}
|
||||
else if(myDpm.isAdminActive(myComponent)){R.string.device_admin}else{R.string.click_to_activate}
|
||||
)
|
||||
LaunchedEffect(Unit){ pkgName.value = "" }
|
||||
Column(modifier = Modifier.statusBarsPadding().verticalScroll(rememberScrollState())) {
|
||||
Spacer(Modifier.padding(vertical = 25.dp))
|
||||
Text(text = stringResource(R.string.app_name), style = typography.headlineLarge, modifier = Modifier.padding(start = 10.dp), color = colorScheme.onBackground)
|
||||
|
||||
@@ -21,8 +21,6 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import com.bintianqi.owndroid.dpm.applySelectedPackage
|
||||
import com.bintianqi.owndroid.dpm.selectedPackage
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.theme.bgColor
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
@@ -40,7 +38,7 @@ private val pkgs = mutableListOf<PkgInfo>()
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun PackageSelector(navCtrl:NavHostController){
|
||||
fun PackageSelector(navCtrl:NavHostController, pkgName: MutableState<String>){
|
||||
val context = LocalContext.current
|
||||
val pm = context.packageManager
|
||||
val apps = pm.getInstalledApplications(0)
|
||||
@@ -144,7 +142,7 @@ fun PackageSelector(navCtrl:NavHostController){
|
||||
if(show) {
|
||||
items(pkgs) {
|
||||
if(filter==it.type){
|
||||
PackageItem(it, navCtrl)
|
||||
PackageItem(it, navCtrl, pkgName)
|
||||
}
|
||||
}
|
||||
items(1){Spacer(Modifier.padding(vertical = 30.dp))}
|
||||
@@ -163,12 +161,12 @@ fun PackageSelector(navCtrl:NavHostController){
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PackageItem(pkg: PkgInfo, navCtrl: NavHostController){
|
||||
private fun PackageItem(pkg: PkgInfo, navCtrl: NavHostController, pkgName: MutableState<String>){
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable{selectedPackage =pkg.pkgName;applySelectedPackage =true;navCtrl.navigateUp()}
|
||||
.clickable{ pkgName.value = pkg.pkgName; navCtrl.navigateUp()}
|
||||
.padding(vertical = 3.dp)
|
||||
){
|
||||
Spacer(Modifier.padding(start = 15.dp))
|
||||
|
||||
@@ -32,7 +32,6 @@ import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -43,6 +42,7 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
@@ -64,10 +64,13 @@ private var keepUninstallPkg = mutableListOf<String>()
|
||||
private var permittedIme = mutableListOf<String>()
|
||||
private var permittedAccessibility = mutableListOf<String>()
|
||||
|
||||
private var dialogConfirmButtonAction = {}
|
||||
private var dialogDismissButtonAction = {}
|
||||
private var dialogGetStatus = { false }
|
||||
|
||||
@Composable
|
||||
fun ApplicationManage(navCtrl:NavHostController){
|
||||
fun ApplicationManage(navCtrl:NavHostController, pkgName: MutableState<String>, dialogStatus: MutableIntState){
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var pkgName by rememberSaveable{ mutableStateOf("") }
|
||||
val localNavCtrl = rememberNavController()
|
||||
val backStackEntry by localNavCtrl.currentBackStackEntryAsState()
|
||||
val titleMap = mapOf(
|
||||
@@ -96,16 +99,10 @@ fun ApplicationManage(navCtrl:NavHostController){
|
||||
}
|
||||
){ paddingValues->
|
||||
Column(modifier = Modifier.fillMaxSize().padding(top = paddingValues.calculateTopPadding())){
|
||||
LaunchedEffect(Unit) {
|
||||
while(true){
|
||||
if(applySelectedPackage){ pkgName = selectedPackage; applySelectedPackage = false; applySelectedPermission = true}
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
if(backStackEntry?.destination?.route!="InstallApp"){
|
||||
TextField(
|
||||
value = pkgName,
|
||||
onValueChange = { pkgName = it },
|
||||
value = pkgName.value,
|
||||
onValueChange = { pkgName.value = it },
|
||||
label = { Text(stringResource(R.string.package_name)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
|
||||
@@ -128,27 +125,30 @@ fun ApplicationManage(navCtrl:NavHostController){
|
||||
popExitTransition = Animations.navHostPopExitTransition,
|
||||
modifier = Modifier.background(bgColor)
|
||||
){
|
||||
composable(route = "Home"){Home(localNavCtrl,pkgName)}
|
||||
composable(route = "BlockUninstall"){BlockUninstall(pkgName)}
|
||||
composable(route = "UserControlDisabled"){UserCtrlDisabledPkg(pkgName)}
|
||||
composable(route = "PermissionManage"){PermissionManage(pkgName,navCtrl)}
|
||||
composable(route = "CrossProfilePackage"){CrossProfilePkg(pkgName)}
|
||||
composable(route = "CrossProfileWidget"){CrossProfileWidget(pkgName)}
|
||||
composable(route = "CredentialManagePolicy"){CredentialManagePolicy(pkgName)}
|
||||
composable(route = "Accessibility"){PermittedAccessibility(pkgName)}
|
||||
composable(route = "IME"){PermittedIME(pkgName)}
|
||||
composable(route = "KeepUninstalled"){KeepUninstalledApp(pkgName)}
|
||||
composable(route = "Home"){Home(localNavCtrl, pkgName.value, dialogStatus)}
|
||||
composable(route = "UserControlDisabled"){UserCtrlDisabledPkg(pkgName.value)}
|
||||
composable(route = "PermissionManage"){PermissionManage(pkgName.value, navCtrl)}
|
||||
composable(route = "CrossProfilePackage"){CrossProfilePkg(pkgName.value)}
|
||||
composable(route = "CrossProfileWidget"){CrossProfileWidget(pkgName.value)}
|
||||
composable(route = "CredentialManagePolicy"){CredentialManagePolicy(pkgName.value)}
|
||||
composable(route = "Accessibility"){PermittedAccessibility(pkgName.value)}
|
||||
composable(route = "IME"){PermittedIME(pkgName.value)}
|
||||
composable(route = "KeepUninstalled"){KeepUninstalledApp(pkgName.value)}
|
||||
composable(route = "InstallApp"){InstallApp()}
|
||||
composable(route = "UninstallApp"){UninstallApp(pkgName)}
|
||||
composable(route = "ClearAppData"){ClearAppData(pkgName)}
|
||||
composable(route = "DefaultDialer"){DefaultDialerApp(pkgName)}
|
||||
composable(route = "UninstallApp"){UninstallApp(pkgName.value)}
|
||||
composable(route = "ClearAppData"){ClearAppData(pkgName.value)}
|
||||
composable(route = "DefaultDialer"){DefaultDialerApp(pkgName.value)}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(dialogStatus.intValue!=0){
|
||||
LocalFocusManager.current.clearFocus()
|
||||
AppControlDialog(dialogStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Home(navCtrl:NavHostController, pkgName: String){
|
||||
private fun Home(navCtrl:NavHostController, pkgName: String, dialogStatus: MutableIntState){
|
||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())){
|
||||
val myContext = LocalContext.current
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
@@ -163,38 +163,70 @@ private fun Home(navCtrl:NavHostController, pkgName: String){
|
||||
startActivity(myContext,intent,null)
|
||||
}
|
||||
if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
||||
val getSuspendStatus = {
|
||||
try{ myDpm.isPackageSuspended(myComponent, pkgName) }
|
||||
catch(e:NameNotFoundException){ false }
|
||||
catch(e:IllegalArgumentException){ false }
|
||||
}
|
||||
SwitchItem(
|
||||
R.string.suspend,"",R.drawable.block_fill0,
|
||||
{
|
||||
try{ myDpm.isPackageSuspended(myComponent,pkgName) }
|
||||
catch(e:NameNotFoundException){ false }
|
||||
catch(e:IllegalArgumentException){ false }
|
||||
},
|
||||
{myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName), it)}
|
||||
)
|
||||
}
|
||||
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
||||
SwitchItem(
|
||||
R.string.hide, stringResource(R.string.isapphidden_desc),R.drawable.visibility_off_fill0,
|
||||
{myDpm.isApplicationHidden(myComponent,pkgName)},{myDpm.setApplicationHidden(myComponent, pkgName, it)}
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
||||
SwitchItem(
|
||||
R.string.always_on_vpn,"",R.drawable.vpn_key_fill0,{pkgName == myDpm.getAlwaysOnVpnPackage(myComponent)},
|
||||
{
|
||||
try {
|
||||
myDpm.setAlwaysOnVpnPackage(myComponent, pkgName, it)
|
||||
} catch(e: UnsupportedOperationException) {
|
||||
Toast.makeText(myContext, R.string.unsupported, Toast.LENGTH_SHORT).show()
|
||||
} catch(e: NameNotFoundException) {
|
||||
Toast.makeText(myContext, R.string.not_installed, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
title = R.string.suspend, desc = "", icon = R.drawable.block_fill0,
|
||||
getState = getSuspendStatus,
|
||||
onCheckedChange = { myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName), it) },
|
||||
onClickBlank = {
|
||||
dialogGetStatus = getSuspendStatus
|
||||
dialogConfirmButtonAction = { myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName), true) }
|
||||
dialogDismissButtonAction = { myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName), false) }
|
||||
dialogStatus.intValue = 1
|
||||
}
|
||||
)
|
||||
}
|
||||
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
||||
SubPageItem(R.string.block_uninstall,"",R.drawable.delete_forever_fill0){navCtrl.navigate("BlockUninstall")}
|
||||
SwitchItem(
|
||||
title = R.string.hide, desc = stringResource(R.string.isapphidden_desc), icon = R.drawable.visibility_off_fill0,
|
||||
getState = { myDpm.isApplicationHidden(myComponent,pkgName) },
|
||||
onCheckedChange = { myDpm.setApplicationHidden(myComponent, pkgName, it) },
|
||||
onClickBlank = {
|
||||
dialogGetStatus = { myDpm.isApplicationHidden(myComponent,pkgName) }
|
||||
dialogConfirmButtonAction = { myDpm.setApplicationHidden(myComponent, pkgName, true) }
|
||||
dialogDismissButtonAction = { myDpm.setApplicationHidden(myComponent, pkgName, false) }
|
||||
dialogStatus.intValue = 2
|
||||
}
|
||||
)
|
||||
}
|
||||
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
||||
SwitchItem(
|
||||
title = R.string.block_uninstall, desc = "", icon = R.drawable.delete_forever_fill0,
|
||||
getState = { myDpm.isUninstallBlocked(myComponent,pkgName) },
|
||||
onCheckedChange = { myDpm.setUninstallBlocked(myComponent,pkgName,it) },
|
||||
onClickBlank = {
|
||||
dialogGetStatus = { myDpm.isUninstallBlocked(myComponent,pkgName) }
|
||||
dialogConfirmButtonAction = { myDpm.setUninstallBlocked(myComponent,pkgName,true) }
|
||||
dialogDismissButtonAction = { myDpm.setUninstallBlocked(myComponent,pkgName,false) }
|
||||
dialogStatus.intValue = 3
|
||||
}
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
||||
val setAlwaysOnVpn: (Boolean)->Unit = {
|
||||
try {
|
||||
myDpm.setAlwaysOnVpnPackage(myComponent, pkgName, it)
|
||||
} catch(e: UnsupportedOperationException) {
|
||||
Toast.makeText(myContext, R.string.unsupported, Toast.LENGTH_SHORT).show()
|
||||
} catch(e: NameNotFoundException) {
|
||||
Toast.makeText(myContext, R.string.not_installed, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
SwitchItem(
|
||||
title = R.string.always_on_vpn, desc = "", icon = R.drawable.vpn_key_fill0,
|
||||
getState = {pkgName == myDpm.getAlwaysOnVpnPackage(myComponent)},
|
||||
onCheckedChange = setAlwaysOnVpn,
|
||||
onClickBlank = {
|
||||
dialogGetStatus = { pkgName == myDpm.getAlwaysOnVpnPackage(myComponent) }
|
||||
dialogConfirmButtonAction = { setAlwaysOnVpn(true) }
|
||||
dialogDismissButtonAction = { setAlwaysOnVpn(false) }
|
||||
dialogStatus.intValue = 4
|
||||
}
|
||||
)
|
||||
}
|
||||
if((VERSION.SDK_INT>=33&&isProfileOwner(myDpm))||(VERSION.SDK_INT>=30&&isDeviceOwner(myDpm))){
|
||||
SubPageItem(R.string.ucd,"",R.drawable.do_not_touch_fill0){navCtrl.navigate("UserControlDisabled")}
|
||||
@@ -300,49 +332,6 @@ private fun UserCtrlDisabledPkg(pkgName:String){
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BlockUninstall(pkgName: String){
|
||||
val myContext = LocalContext.current
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,Receiver::class.java)
|
||||
val focusMgr = LocalFocusManager.current
|
||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
||||
var state by remember{mutableStateOf(myDpm.isUninstallBlocked(myComponent,pkgName))}
|
||||
Spacer(Modifier.padding(vertical = 10.dp))
|
||||
Text(text = stringResource(R.string.block_uninstall), style = typography.headlineLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Text(stringResource(R.string.current_state, stringResource(if(state){R.string.enabled}else{R.string.disabled})))
|
||||
Spacer(Modifier.padding(vertical = 3.dp))
|
||||
Text(text = stringResource(R.string.sometimes_get_wrong_block_uninstall_state))
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Button(
|
||||
onClick = {
|
||||
focusMgr.clearFocus()
|
||||
myDpm.setUninstallBlocked(myComponent,pkgName,true)
|
||||
Toast.makeText(myContext, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
state = myDpm.isUninstallBlocked(myComponent,pkgName)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.49F)
|
||||
) {
|
||||
Text(stringResource(R.string.enable))
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
focusMgr.clearFocus()
|
||||
myDpm.setUninstallBlocked(myComponent,pkgName,false)
|
||||
Toast.makeText(myContext, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
state = myDpm.isUninstallBlocked(myComponent,pkgName)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.96F)
|
||||
){
|
||||
Text(stringResource(R.string.disable))
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
private fun PermissionManage(pkgName: String, navCtrl: NavHostController){
|
||||
@@ -899,6 +888,62 @@ private fun DefaultDialerApp(pkgName: String){
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppControlDialog(status: MutableIntState){
|
||||
val enabled = dialogGetStatus()
|
||||
Dialog(
|
||||
onDismissRequest = { status.intValue = 0 }
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
){
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(15.dp)
|
||||
){
|
||||
Text(
|
||||
text = stringResource(
|
||||
when(status.intValue){
|
||||
1 -> R.string.suspend
|
||||
2 -> R.string.hide
|
||||
3 -> R.string.block_uninstall
|
||||
4 -> R.string.always_on_vpn
|
||||
else -> R.string.unknown
|
||||
}
|
||||
),
|
||||
style = typography.headlineMedium,
|
||||
modifier = Modifier.padding(start = 5.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.current_status_is) + stringResource(if(enabled){R.string.enabled}else{R.string.disabled}),
|
||||
modifier = Modifier.padding(start = 5.dp, top = 5.dp, bottom = 5.dp)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
){
|
||||
TextButton(
|
||||
onClick = { status.intValue = 0 }
|
||||
){
|
||||
Text(text = stringResource(R.string.cancel))
|
||||
}
|
||||
Row{
|
||||
TextButton(
|
||||
onClick = { dialogDismissButtonAction(); status.intValue = 0 }
|
||||
){
|
||||
Text(text = stringResource(R.string.disable))
|
||||
}
|
||||
TextButton(
|
||||
onClick = { dialogConfirmButtonAction(); status.intValue = 0 }
|
||||
){
|
||||
Text(text = stringResource(R.string.enable))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun installPackage(context: Context, inputStream: InputStream){
|
||||
val packageInstaller = context.packageManager.packageInstaller
|
||||
|
||||
@@ -5,8 +5,6 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
|
||||
var selectedPackage = ""
|
||||
var applySelectedPackage = false
|
||||
var selectedPermission = ""
|
||||
var applySelectedPermission = false
|
||||
lateinit var createManagedProfile: ActivityResultLauncher<Intent>
|
||||
|
||||
@@ -5,7 +5,9 @@ import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.LocalIndication
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
@@ -128,12 +130,21 @@ fun SwitchItem(
|
||||
@DrawableRes icon: Int?,
|
||||
getState: ()->Boolean,
|
||||
onCheckedChange: (Boolean)->Unit,
|
||||
enable:Boolean=true
|
||||
enable:Boolean = true,
|
||||
onClickBlank: (() -> Unit)? = null
|
||||
){
|
||||
var checked by remember{mutableStateOf(false)}
|
||||
checked = getState()
|
||||
Box(modifier = Modifier.fillMaxWidth().padding(vertical = 5.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.align(Alignment.CenterStart)){
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(enabled = onClickBlank!=null, onClick = onClickBlank?:{})
|
||||
.padding(vertical = 5.dp)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.align(Alignment.CenterStart)
|
||||
){
|
||||
Spacer(Modifier.padding(start = 30.dp))
|
||||
if(icon!=null){
|
||||
Icon(painter = painterResource(icon),contentDescription = null)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<string name="copy">复制</string>
|
||||
<string name="file_not_exist">文件不存在</string>
|
||||
<string name="io_exception">IO异常</string>
|
||||
<string name="current_status_is">当前状态:</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">点击以激活</string>
|
||||
@@ -256,7 +257,6 @@
|
||||
<string name="app_info">应用详情</string>
|
||||
<string name="not_installed">未安装</string>
|
||||
<string name="block_uninstall">防卸载</string>
|
||||
<string name="sometimes_get_wrong_block_uninstall_state">有时候无法正确获取防卸载状态</string>
|
||||
<string name="ucd">禁止用户控制</string>
|
||||
<string name="ucd_desc">用户将无法清除应用的存储空间和缓存</string>
|
||||
<string name="app_list_is">应用列表:</string>
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<string name="copy">Copy</string>
|
||||
<string name="file_not_exist">File not exist</string>
|
||||
<string name="io_exception">IO Exception</string>
|
||||
<string name="current_status_is">Current status: </string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="click_to_activate">Click to activate</string>
|
||||
@@ -269,7 +270,6 @@
|
||||
<string name="app_info">App info</string>
|
||||
<string name="not_installed">Not installed</string>
|
||||
<string name="block_uninstall">Block uninstall</string>
|
||||
<string name="sometimes_get_wrong_block_uninstall_state">Sometimes it shows a wrong status</string>
|
||||
<!--ucd: user control disabled-->
|
||||
<string name="ucd">Disable user control</string>
|
||||
<string name="ucd_desc">If you set this, you cannot clear storage or cache of the app. </string>
|
||||
|
||||
Reference in New Issue
Block a user