From 2009baac40dbc9163f1430a0873dfbf83685ca0e Mon Sep 17 00:00:00 2001 From: BinTianqi Date: Sun, 12 May 2024 19:17:13 +0800 Subject: [PATCH] App manager: show a dialog when click suspend, hide, block uninstall or always-on vpn raise pkgName state to save it --- app/build.gradle.kts | 2 +- .../com/bintianqi/owndroid/MainActivity.kt | 16 +- .../com/bintianqi/owndroid/PkgSelector.kt | 10 +- .../owndroid/dpm/ApplicationManage.kt | 235 +++++++++++------- .../java/com/bintianqi/owndroid/dpm/DPM.kt | 2 - .../com/bintianqi/owndroid/ui/Components.kt | 17 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 171 insertions(+), 115 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e97b05c..b31e5e6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,7 +22,7 @@ android { versionCode = 26 versionName = "5.1" multiDexEnabled = false - //signingConfig = signingConfigs.getByName("testkey") + signingConfig = signingConfigs.getByName("testkey") } buildTypes { diff --git a/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt b/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt index 48fdc4e..2451100 100644 --- a/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt +++ b/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt @@ -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){ 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) diff --git a/app/src/main/java/com/bintianqi/owndroid/PkgSelector.kt b/app/src/main/java/com/bintianqi/owndroid/PkgSelector.kt index 2875e3d..1ac002a 100644 --- a/app/src/main/java/com/bintianqi/owndroid/PkgSelector.kt +++ b/app/src/main/java/com/bintianqi/owndroid/PkgSelector.kt @@ -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() @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable -fun PackageSelector(navCtrl:NavHostController){ +fun PackageSelector(navCtrl:NavHostController, pkgName: MutableState){ 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){ 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)) diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt index 5795860..87f25e2 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt @@ -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() private var permittedIme = mutableListOf() private var permittedAccessibility = mutableListOf() +private var dialogConfirmButtonAction = {} +private var dialogDismissButtonAction = {} +private var dialogGetStatus = { false } + @Composable -fun ApplicationManage(navCtrl:NavHostController){ +fun ApplicationManage(navCtrl:NavHostController, pkgName: MutableState, 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 diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt index 01179a6..ad09faa 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt @@ -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 diff --git a/app/src/main/java/com/bintianqi/owndroid/ui/Components.kt b/app/src/main/java/com/bintianqi/owndroid/ui/Components.kt index 075712d..ea8725a 100644 --- a/app/src/main/java/com/bintianqi/owndroid/ui/Components.kt +++ b/app/src/main/java/com/bintianqi/owndroid/ui/Components.kt @@ -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) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f2af943..8fdb8d5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -45,6 +45,7 @@ 复制 文件不存在 IO异常 + 当前状态: 点击以激活 @@ -256,7 +257,6 @@ 应用详情 未安装 防卸载 - 有时候无法正确获取防卸载状态 禁止用户控制 用户将无法清除应用的存储空间和缓存 应用列表: diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 86e0bb8..1a14ea0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,7 @@ Copy File not exist IO Exception + Current status:  Click to activate @@ -269,7 +270,6 @@ App info Not installed Block uninstall - Sometimes it shows a wrong status Disable user control If you set this, you cannot clear storage or cache of the app.