From 587a14d0683d90fa9026610d513516725f8dd405 Mon Sep 17 00:00:00 2001 From: BinTianqi <1220958406@qq.com> Date: Thu, 18 Jan 2024 13:14:59 +0800 Subject: [PATCH] Add security section, backward compatible to API23 --- app/build.gradle.kts | 6 +- app/src/main/AndroidManifest.xml | 2 + .../binbin/androidowner/ApplicationManage.kt | 65 +++++-- .../com/binbin/androidowner/DeviceControl.kt | 38 ++-- .../com/binbin/androidowner/MainActivity.kt | 10 +- .../com/binbin/androidowner/Permissions.kt | 18 +- .../java/com/binbin/androidowner/Security.kt | 182 ++++++++++++++++-- .../java/com/binbin/androidowner/Test.java | 46 +++++ .../com/binbin/androidowner/UserRestrict.kt | 61 +++--- .../ic_launcher.xml | 0 .../ic_launcher_round.xml | 0 app/src/main/res/values/strings.xml | 7 +- 12 files changed, 357 insertions(+), 78 deletions(-) create mode 100644 app/src/main/java/com/binbin/androidowner/Test.java rename app/src/main/res/{mipmap-anydpi => mipmap-anydpi-v26}/ic_launcher.xml (100%) rename app/src/main/res/{mipmap-anydpi => mipmap-anydpi-v26}/ic_launcher_round.xml (100%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5614c0d..70881f1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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 { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 14efb85..9beacf0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + =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) +} diff --git a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt index 9ce6def..2cc428f 100644 --- a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt +++ b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt @@ -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)}), diff --git a/app/src/main/java/com/binbin/androidowner/MainActivity.kt b/app/src/main/java/com/binbin/androidowner/MainActivity.kt index 2af3632..6f4b0da 100644 --- a/app/src/main/java/com/binbin/androidowner/MainActivity.kt +++ b/app/src/main/java/com/binbin/androidowner/MainActivity.kt @@ -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) } } diff --git a/app/src/main/java/com/binbin/androidowner/Permissions.kt b/app/src/main/java/com/binbin/androidowner/Permissions.kt index d55cae8..222aba3 100644 --- a/app/src/main/java/com/binbin/androidowner/Permissions.kt +++ b/app/src/main/java/com/binbin/androidowner/Permissions.kt @@ -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信息") } } - } } diff --git a/app/src/main/java/com/binbin/androidowner/Security.kt b/app/src/main/java/com/binbin/androidowner/Security.kt index d277653..ed74819 100644 --- a/app/src/main/java/com/binbin/androidowner/Security.kt +++ b/app/src/main/java/com/binbin/androidowner/Security.kt @@ -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() } - } diff --git a/app/src/main/java/com/binbin/androidowner/Test.java b/app/src/main/java/com/binbin/androidowner/Test.java new file mode 100644 index 0000000..75df460 --- /dev/null +++ b/app/src/main/java/com/binbin/androidowner/Test.java @@ -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(); + } +} diff --git a/app/src/main/java/com/binbin/androidowner/UserRestrict.kt b/app/src/main/java/com/binbin/androidowner/UserRestrict.kt index 99bb2c0..44da09c 100644 --- a/app/src/main/java/com/binbin/androidowner/UserRestrict.kt +++ b/app/src/main/java/com/binbin/androidowner/UserRestrict.kt @@ -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{ + + } } } diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi/ic_launcher.xml rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi/ic_launcher_round.xml rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae647a7..caade63 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,7 +44,10 @@ 停用 防卸载 如果隐藏,有可能是没安装 - 有时候不能用 + 有时候不能用 禁止用户控制 - 阻止清除应用数据和缓存> + 阻止清除应用数据和缓存 + 安全 + 安装未知来源应用 + 修改或清除锁屏密码> \ No newline at end of file