Add security section, backward compatible to API23

This commit is contained in:
BinTianqi
2024-01-18 13:14:59 +08:00
parent 0a60affff9
commit 587a14d068
12 changed files with 357 additions and 78 deletions

View File

@@ -9,10 +9,10 @@ android {
defaultConfig {
applicationId = "com.binbin.androidowner"
minSdk = 26
minSdk = 23
targetSdk = 34
versionCode = 2
versionName = "1.1"
versionCode = 3
versionName = "1.2"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"

View File

@@ -3,8 +3,11 @@ package com.binbin.androidowner
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager.NameNotFoundException
import android.net.Uri
import android.os.Build.VERSION
import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -28,6 +31,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
@Composable
@@ -47,32 +51,46 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
},
label = { Text("包名") }
)
val isSuspended = {
try{
myDpm.isPackageSuspended(myComponent,pkgName)
}catch(e:NameNotFoundException){
false
if(VERSION.SDK_INT>=24){
val isSuspended = {
try{
myDpm.isPackageSuspended(myComponent,pkgName)
}catch(e:NameNotFoundException){
false
}
}
AppManageItem(R.string.suspend,R.string.place_holder,myDpm, isSuspended,
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
}
AppManageItem(R.string.hide,R.string.isapphidden_desc,myDpm, {myDpm.isApplicationHidden(myComponent,pkgName)},
{b -> myDpm.setApplicationHidden(myComponent,pkgName,b)})
AppManageItem(R.string.suspend,R.string.place_holder,myDpm, isSuspended,
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
/*AppManageItem(R.string.block_unins,R.string.sometimes_not_avaliable,myDpm, {myDpm.isUninstallBlocked(myComponent,pkgName)},
if(VERSION.SDK_INT>=30){
AppManageItem(R.string.user_ctrl_disabled,R.string.user_ctrl_disabled_desc,myDpm, {pkgName in myDpm.getUserControlDisabledPackages(myComponent)},
{b->myDpm.setUserControlDisabledPackages(myComponent, mutableListOf(if(b){pkgName}else{null}))})
}
/*AppManageItem(R.string.block_unins,R.string.sometimes_not_available,myDpm, {myDpm.isUninstallBlocked(myComponent,pkgName)},
{b -> myDpm.setUninstallBlocked(myComponent,pkgName,b)})*/
Text("因为无法获取某个应用是否防卸载,无法使用开关控制防卸载")
Row {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(5.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceAround
) {
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,false)}) {
Text("取消防卸载")
}
Spacer(Modifier.padding(horizontal = 2.dp))
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}) {
Text("防卸载")
}
}
if(VERSION.SDK_INT>=30){
AppManageItem(R.string.user_ctrl_disabled,R.string.user_ctrl_disabled_desc,myDpm, {pkgName in myDpm.getUserControlDisabledPackages(myComponent)},
{b->myDpm.setUserControlDisabledPackages(myComponent, mutableListOf(if(b){pkgName}else{null}))})
Button(
onClick = {
uninstallApp(myContext,pkgName)
}) {
Text("卸载")
}
Spacer(Modifier.padding(5.dp))
}
@@ -119,3 +137,22 @@ private fun AppManageItem(
)
}
}
fun uninstallPkg(pkgName:String,myContext:Context){
val packageManager = myContext.packageManager
try {
val packageInfo = packageManager.getPackageInfo(pkgName, 0)
val intent = Intent(Intent.ACTION_DELETE)
intent.setData(Uri.parse("package:" + packageInfo.packageName))
startActivity(myContext,intent,null)
} catch (e: NameNotFoundException) {
Toast.makeText(myContext, "应用未安装", Toast.LENGTH_SHORT).show()
}
}
private fun uninstallApp(context: Context, packageName: String) {
val packageUri = Uri.parse("package:$packageName")
val uninstallIntent = Intent(Intent.ACTION_DELETE, packageUri)
uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(uninstallIntent)
}

View File

@@ -34,11 +34,6 @@ import androidx.compose.ui.unit.dp
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
val wifimac = try {
myDpm.getWifiMacAddress(myComponent).toString()
}catch(e:SecurityException){
"没有权限"
}
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
@@ -54,16 +49,35 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
DeviceCtrlItem(R.string.auto_timezone,R.string.place_holder,myDpm,{myDpm.getAutoTimeZoneEnabled(myComponent)},{b -> myDpm.setAutoTimeZoneEnabled(myComponent,b) })
}
DeviceCtrlItem(R.string.master_mute,R.string.place_holder,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) })
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
Text("隐藏状态栏需要API34")
Text("自动设置时间和自动设置时区需要API30")
Button(onClick = {myDpm.reboot(myComponent)}) {
Text("重启")
if(VERSION.SDK_INT>=26){
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
}
if(VERSION.SDK_INT>=24){
Button(onClick = {myDpm.reboot(myComponent)}) {
Text("重启")
}
val wifimac = try {
myDpm.getWifiMacAddress(myComponent).toString()
}catch(e:SecurityException){
"没有权限"
}
Text("WiFi MAC: $wifimac")
}
if(VERSION.SDK_INT<24){
Text("重启和WiFi Mac需要API24")
}
if(VERSION.SDK_INT<26){
Text("备份服务需要API26")
}
if(VERSION.SDK_INT<30){
Text("自动设置时间和自动设置时区需要API30")
}
if(VERSION.SDK_INT<34){
Text("隐藏状态栏需要API34")
}
Button(onClick = {myDpm.lockNow()}) {
Text("锁屏")
}
Text("WiFi MAC: $wifimac")
Text("以下功能需要长按按钮,作者并未测试")
Button(
onClick = {},
@@ -76,7 +90,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
) {
Text("WipeData")
}
if (VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
if (VERSION.SDK_INT >= 34) {
Button(
modifier = Modifier
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeDevice(0)}),

View File

@@ -85,7 +85,8 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
"Permissions" to R.string.permission,
"UIControl" to R.string.ui_ctrl,
"ApplicationManage" to R.string.app_manage,
"UserRestriction" to R.string.user_restrict
"UserRestriction" to R.string.user_restrict,
"Security" to R.string.security
)
val topBarName = topBarNameMap[backStackEntry?.destination?.route]?: R.string.app_name
Scaffold(
@@ -125,13 +126,16 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
NavHost(
navController = navCtrl,
startDestination = "HomePage",
modifier = Modifier.padding(top = it.calculateTopPadding()).navigationBarsPadding()
modifier = Modifier
.padding(top = it.calculateTopPadding())
.navigationBarsPadding()
){
composable(route = "HomePage", content = { HomePage(navCtrl,mainDpm,mainComponent)})
composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)})
composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)})
composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)})
composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent)})
composable(route = "Security", content = { Security(mainDpm,mainComponent,mainContext)})
}
}
}
@@ -174,10 +178,10 @@ fun HomePage(navCtrl:NavHostController,myDpm:DevicePolicyManager,myComponent:Com
)
}
}
//HomePageItem(R.string.permission, R.drawable.security_fill0, R.string.permission_desc, "Permissions", navCtrl)
HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, R.string.device_ctrl_desc, "DeviceControl", navCtrl)
HomePageItem(R.string.app_manage, R.drawable.apps_fill0, R.string.apps_ctrl_description, "ApplicationManage", navCtrl)
HomePageItem(R.string.user_restrict, R.drawable.manage_accounts_fill0, R.string.user_restrict_desc, "UserRestriction", navCtrl)
HomePageItem(R.string.security, R.drawable.security_fill0,R.string.security_desc, "Security",navCtrl)
}
}

View File

@@ -5,7 +5,7 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.provider.Settings.Global
import android.os.Build.VERSION
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -30,7 +30,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.core.app.ActivityCompat.startActivityForResult
import androidx.core.content.ContextCompat.startActivity
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
@@ -130,16 +129,15 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
Text("使用此命令也会激活Device Admin")
}
}
if(isdo){
var lockScrInfo by remember { mutableStateOf("") }
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
Spacer(Modifier.padding(5.dp))
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
Text("设置锁屏DeviceOwner信息")
}
}
if(isdo&&VERSION.SDK_INT>=24){
var lockScrInfo by remember { mutableStateOf("") }
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
Spacer(Modifier.padding(5.dp))
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
Text("设置锁屏DeviceOwner信息")
}
}
}
}

View File

@@ -1,25 +1,185 @@
package com.binbin.androidowner
import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
@Composable
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName){
Column {
Button(onClick = {myDpm.clearResetPasswordToken(myComponent)}) {
Text("清除重置密码令牌")
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Context){
var newPwd by remember{ mutableStateOf("") }
var confirmed by remember{ mutableStateOf(false) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
val myByteArray by remember{ mutableStateOf(byteArrayOf(1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0)) }
if(VERSION.SDK_INT>=26){
Column(
horizontalAlignment = Alignment.Start,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clip(RoundedCornerShape(10))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(8.dp)
) {
Text(
text = "密码重置令牌",
style = MaterialTheme.typography.titleLarge
)
Row {
Button(
onClick = {
if(myDpm.clearResetPasswordToken(myComponent)){
Toast.makeText(myContext, "清除成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "清除失败", Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.padding(end = 8.dp)
) {
Text("清除")
}
Button(
onClick = {
if(myDpm.setResetPasswordToken(myComponent, myByteArray)){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.padding(end = 8.dp)
) {
Text("设置")
}
Button(
onClick = {
if(!myDpm.isResetPasswordTokenActive(myComponent)){
try{
activateToken(myContext)
}catch(e:NullPointerException){
Toast.makeText(myContext, "请先设置令牌", Toast.LENGTH_SHORT).show()
}
}else{
Toast.makeText(myContext, "已经激活", Toast.LENGTH_SHORT).show()
}
}
) {
Text("激活")
}
}
Text("没有密码时会自动激活令牌")
}
}
Button(onClick = {myDpm.setResetPasswordToken(myComponent, byteArrayOf(32))}) {
Text("设置重置密码令牌")
}
Text("不知道上面两个东西干啥用的")
Button(onClick = {myDpm.resetPassword(null,0)}) {
Text("清除密码")
TextField(
value = newPwd,
onValueChange = {newPwd=it},
enabled = !confirmed,
label = { Text("密码")}
)
Text(
text = "(留空可以清除密码)",
modifier = Modifier.padding(vertical = 5.dp)
)
Row {
Button(
onClick = {
if(newPwd.length>=4||newPwd.isEmpty()){
confirmed=!confirmed
}else{
Toast.makeText(myContext, "需要4位数字或字母", Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.padding(end = 10.dp)
) {
Text("确认密码")
}
if(VERSION.SDK_INT>=26){
Button(
onClick = {
val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,0)
if(resetSuccess){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
confirmed=false
},
enabled = confirmed,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError
)
) {
Text("设置密码")
}
}else{
Button(
onClick = {
val resetSuccess = myDpm.resetPassword(newPwd,0)
if(resetSuccess){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
confirmed=false
},
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError
)
) {
Text("设置密码")
}
}
}
Text(
text = "该操作可能会造成不可挽回的损失,请先备份好数据。设置密码的时候一定要谨慎!!!",
color = MaterialTheme.colorScheme.onErrorContainer,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.errorContainer)
.padding(8.dp)
)
}
}
fun activateToken(myContext: Context){
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
val keyguardManager = myContext.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)
confirmIntent.setFlags(FLAG_ACTIVITY_NEW_TASK)
if (confirmIntent != null) {
startActivity(myContext,confirmIntent, null)
} else {
Toast.makeText(myContext, "激活失败", Toast.LENGTH_SHORT).show()
}
}

View File

@@ -0,0 +1,46 @@
package com.binbin.androidowner;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageInstaller;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Test {
public static void installPackage(Context context, InputStream inputStream)
throws IOException {
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
int sessionId = packageInstaller.createSession(new PackageInstaller
.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
long sizeBytes = 0;
OutputStream out;
out = session.openWrite("my_app_session", 0, sizeBytes);
int total = 0;
byte[] buffer = new byte[65536];
int c;
while ((c = inputStream.read(buffer)) != -1) {
total += c;
out.write(buffer, 0, c);
}
session.fsync(out);
inputStream.close();
out.close();
// fake intent
IntentSender statusReceiver = null;
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
session.close();
}
}

View File

@@ -2,7 +2,7 @@ package com.binbin.androidowner
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.os.Build
import android.os.Build.VERSION
import android.os.UserManager
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
@@ -34,15 +34,19 @@ import androidx.compose.ui.unit.dp
fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
val verticalScrolling = rememberScrollState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.verticalScroll(verticalScrolling)
.padding(bottom = 20.dp)
) {
Text("打开开关后会禁用对应的功能")
UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_WIFI,R.string.config_wifi,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
if(Build.VERSION.SDK_INT>=28){
if(VERSION.SDK_INT>=26){
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
}
if(VERSION.SDK_INT>=28){
UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",myComponent, myDpm)
@@ -51,17 +55,23 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_ADJUST_VOLUME,R.string.adjust_volume,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",myComponent, myDpm)
if(Build.VERSION.SDK_INT>=31){
if(VERSION.SDK_INT>=31){
UserRestrictionItem(UserManager.DISALLOW_CAMERA_TOGGLE,R.string.camera_toggle,"",myComponent, myDpm)
}
UserRestrictionItem(UserManager.DISALLOW_SMS,R.string.sms,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_APPS_CONTROL,R.string.apps_ctrl, stringResource(R.string.apps_ctrl_description),myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
if(Build.VERSION.SDK_INT<28){
if(VERSION.SDK_INT>=26){
UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
}
UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,R.string.inst_unknown_src,"",myComponent, myDpm)
if(VERSION.SDK_INT<26){
Text("以下功能需要安卓8或以上蓝牙、自动填充服务")
}
if(VERSION.SDK_INT<28){
Text("以下功能需要安卓9或以上飞行模式、位置信息、调整亮度")
}
if(Build.VERSION.SDK_INT<31){
Text("以下功能需要安卓12或以上相机切换")
if(VERSION.SDK_INT<31){
Text("以下功能需要安卓12或以上切换相机")
}
}
}
@@ -98,21 +108,26 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
if(restrictionDescription!=""){Text(restrictionDescription)}
}
}
if(isdo){
if(isdo&&VERSION.SDK_INT>=24){
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
}
Switch(
checked = strictState,
onCheckedChange = {
strictState=it
if(strictState){
myDpm.addUserRestriction(myComponent,restriction)
}else{
myDpm.clearUserRestriction(myComponent,restriction)
}
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
},
enabled = isdo
)
if(VERSION.SDK_INT>=24){
Switch(
checked = strictState,
onCheckedChange = {
strictState=it
if(strictState){
myDpm.addUserRestriction(myComponent,restriction)
}else{
myDpm.clearUserRestriction(myComponent,restriction)
}
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
},
enabled = isdo
)
}else{
}
}
}

View File

@@ -44,7 +44,10 @@
<string name="suspend">停用</string>
<string name="block_unins">防卸载</string>
<string name="isapphidden_desc">如果隐藏,有可能是没安装</string>
<string name="sometimes_not_avaliable">有时候不能用</string>
<string name="sometimes_not_available">有时候不能用</string>
<string name="user_ctrl_disabled">禁止用户控制</string>
<string name="user_ctrl_disabled_desc">阻止清除应用数据和缓存</string>>
<string name="user_ctrl_disabled_desc">阻止清除应用数据和缓存</string>
<string name="security">安全</string>
<string name="inst_unknown_src">安装未知来源应用</string>
<string name="security_desc">修改或清除锁屏密码</string>>
</resources>