use switch instead of button in 'UserRestriction' section

This commit is contained in:
BinTianqi
2024-01-15 22:04:23 +08:00
parent 97dde5a43b
commit 5777c232bb
11 changed files with 271 additions and 73 deletions

3
Readme.md Normal file
View File

@@ -0,0 +1,3 @@
# 简介
使用安卓的DeviceAdmin和DeviceOwner API管理你的设备
即将加入的功能:安装应用、卸载应用、清空应用数据

View File

@@ -61,6 +61,7 @@ dependencies {
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3") implementation("androidx.compose.material3:material3")
implementation("androidx.navigation:navigation-compose:2.7.6") implementation("androidx.navigation:navigation-compose:2.7.6")
implementation("com.google.accompanist:accompanist-systemuicontroller:0.33.2-alpha")
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

View File

@@ -12,7 +12,6 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.AndroidOwner" android:theme="@style/Theme.AndroidOwner"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"
android:testOnly="true"
tools:targetApi="34"> tools:targetApi="34">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@@ -2,6 +2,7 @@ package com.binbin.androidowner
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.os.Build
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -10,8 +11,11 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable 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.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@@ -23,35 +27,63 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
} }
Column { Column {
Text("WiFi MAC: $wifimac") Text("WiFi MAC: $wifimac")
Button(onClick = {myDpm.setCameraDisabled(myComponent, true)}) { var isCameraDisabled by remember{ mutableStateOf(myDpm.getCameraDisabled(null)) }
Button(onClick = {myDpm.setCameraDisabled(myComponent, true);isCameraDisabled = myDpm.getCameraDisabled(null)}) {
Text("禁用相机") Text("禁用相机")
} }
Button(onClick = {myDpm.setCameraDisabled(myComponent, false)}) { Button(onClick = {myDpm.setCameraDisabled(myComponent, false);isCameraDisabled = myDpm.getCameraDisabled(null)}) {
Text("启用相机") Text("启用相机")
} }
Button(onClick = {myDpm.setScreenCaptureDisabled(myComponent,true)}) { Text("AVD上没有相机未测试")
Text("相机被禁用:$isCameraDisabled")
var isScrCapDisabled by remember{ mutableStateOf(myDpm.getScreenCaptureDisabled(null)) }
Button(onClick = {myDpm.setScreenCaptureDisabled(myComponent,true);isScrCapDisabled = myDpm.getScreenCaptureDisabled(null)}) {
Text("禁止截屏") Text("禁止截屏")
} }
Button(onClick = {myDpm.setScreenCaptureDisabled(myComponent,false)}) { Button(onClick = {myDpm.setScreenCaptureDisabled(myComponent,false);isScrCapDisabled = myDpm.getScreenCaptureDisabled(null)}) {
Text("允许截屏") Text("允许截屏")
} }
Text("对AOSP的录屏也起作用")
Text("禁止截屏:$isScrCapDisabled")
Button(onClick = {myDpm.reboot(myComponent)}) { Button(onClick = {myDpm.reboot(myComponent)}) {
Text("重启") Text("重启")
} }
Button(onClick = {myDpm.lockNow()}) { Button(onClick = {myDpm.lockNow()}) {
Text("锁屏") Text("锁屏")
} }
var isMasterMuted by remember{ mutableStateOf(false) }
isMasterMuted = try{ myDpm.isMasterVolumeMuted(myComponent) }catch(e:SecurityException){ false }
Button(onClick = {myDpm.setMasterVolumeMuted(myComponent,true);isMasterMuted=myDpm.isMasterVolumeMuted(myComponent)}) {
Text("全部静音")
}
Button(onClick = {myDpm.setMasterVolumeMuted(myComponent,false);isMasterMuted=myDpm.isMasterVolumeMuted(myComponent)}) {
Text("取消静音")
}
Text("静音:$isMasterMuted")
Text("以下功能需要长按按钮,作者并未测试")
Button( Button(
onClick = {}, onClick = {},
modifier = Modifier modifier = Modifier
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeData(0)}), .combinedClickable(onClick = {}, onLongClick = {myDpm.wipeData(0)}),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
) )
) { ) {
Text( Text("WipeData")
text = "FACTORY_RESET!!!!! (长按)(未测试)", }
color = MaterialTheme.colorScheme.error) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
Button(
modifier = Modifier
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeDevice(0)}),
onClick = {},
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
)
) {
Text("WipeDevice(API34)")
}
} }
} }
} }

View File

@@ -5,17 +5,18 @@ import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.provider.CalendarContract.Colors
import android.view.View
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -24,25 +25,45 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.binbin.androidowner.ui.theme.AndroidOwnerTheme import com.binbin.androidowner.ui.theme.AndroidOwnerTheme
import com.google.accompanist.systemuicontroller.rememberSystemUiController
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, false)
getWindow().decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
getWindow().decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
//getWindow().setStatusBarColor(Color.White)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val context = applicationContext val context = applicationContext
val dpm = context.getSystemService(DEVICE_POLICY_SERVICE) as DevicePolicyManager val dpm = context.getSystemService(DEVICE_POLICY_SERVICE) as DevicePolicyManager
val adminComponent = ComponentName(context,MyDeviceAdminReceiver::class.java) val adminComponent = ComponentName(context,MyDeviceAdminReceiver::class.java)
setContent { setContent {
val sysUiCtrl = rememberSystemUiController()
val sf = MaterialTheme.colorScheme.surface
val useDarkIcon = !isSystemInDarkTheme()
SideEffect {
sysUiCtrl.run {
setNavigationBarColor(sf,useDarkIcon)
setStatusBarColor(Color.White.copy(alpha = 0F),useDarkIcon)
}
}
AndroidOwnerTheme { AndroidOwnerTheme {
MyScaffold(dpm,adminComponent,context) MyScaffold(dpm,adminComponent,context)
} }
@@ -55,10 +76,25 @@ class MainActivity : ComponentActivity() {
@Composable @Composable
fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainContext:Context){ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainContext:Context){
val navCtrl = rememberNavController() val navCtrl = rememberNavController()
val backStackEntry by navCtrl.currentBackStackEntryAsState()
val topBarNameMap = mapOf(
"HomePage" to R.string.app_name,
"DeviceControl" to R.string.device_ctrl,
"Permissions" to R.string.permission,
"UIControl" to R.string.ui_ctrl,
"ApplicationManage" to R.string.app_manage,
"UserRestriction" to R.string.user_restrict
)
val topBarName = topBarNameMap[backStackEntry?.destination?.route]?: R.string.app_name
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(text = "Android Owner",color = MaterialTheme.colorScheme.onSurface)}, title = {
Text(
text = stringResource(topBarName) ,
color = MaterialTheme.colorScheme.onSurface
)
},
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface containerColor = MaterialTheme.colorScheme.surface
) )
@@ -68,7 +104,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
NavHost( NavHost(
navController = navCtrl, navController = navCtrl,
startDestination = "HomePage", startDestination = "HomePage",
modifier = Modifier.padding(top = 70.dp) modifier = Modifier.padding(top = it.calculateTopPadding())
){ ){
composable(route = "HomePage", content = { HomePage(navCtrl)}) composable(route = "HomePage", content = { HomePage(navCtrl)})
composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)}) composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)})
@@ -83,8 +119,8 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
@Composable @Composable
fun HomePage(navCtrl:NavHostController){ fun HomePage(navCtrl:NavHostController){
Column { Column {
HomePageItem(R.string.permission, R.drawable.info_fill0, R.string.permission_desc, "Permissions", navCtrl) HomePageItem(R.string.permission, R.drawable.security_fill0, R.string.permission_desc, "Permissions", navCtrl)
HomePageItem(R.string.device_ctrl, R.drawable.info_fill0, R.string.device_ctrl_desc, "DeviceControl", navCtrl) HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, R.string.device_ctrl_desc, "DeviceControl", navCtrl)
HomePageItem(R.string.ui_ctrl, R.drawable.info_fill0, R.string.ui_ctrl_desc, "UIControl", navCtrl) HomePageItem(R.string.ui_ctrl, R.drawable.info_fill0, R.string.ui_ctrl_desc, "UIControl", navCtrl)
HomePageItem(R.string.app_manage, R.drawable.info_fill0, R.string.apps_ctrl_description, "ApplicationManage", navCtrl) HomePageItem(R.string.app_manage, R.drawable.info_fill0, R.string.apps_ctrl_description, "ApplicationManage", navCtrl)
HomePageItem(R.string.user_restrict, R.drawable.info_fill0, R.string.user_restrict_desc, "UserRestriction", navCtrl) HomePageItem(R.string.user_restrict, R.drawable.info_fill0, R.string.user_restrict_desc, "UserRestriction", navCtrl)

View File

@@ -3,14 +3,29 @@ package com.binbin.androidowner
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent
import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable 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.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
@Composable @Composable
@@ -18,29 +33,94 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
//da:DeviceAdmin do:DeviceOwner //da:DeviceAdmin do:DeviceOwner
val isda = myDpm.isAdminActive(myComponent) val isda = myDpm.isAdminActive(myComponent)
val isdo = myDpm.isDeviceOwnerApp("com.binbin.androidowner") val isdo = myDpm.isDeviceOwnerApp("com.binbin.androidowner")
val ispo = myDpm.isProfileOwnerApp("com.binbin.androidowner")
Column( Column(
modifier = Modifier.padding(8.dp) modifier = Modifier
.padding(8.dp)
.verticalScroll(rememberScrollState())
) { ) {
Text("Device Admin: $isda") Text("权限:DeviceAdmin < ProfileOwner < DeviceOwner")
Text("Device Owner: $isdo") Column(
SelectionContainer { modifier = Modifier
Column { .clip(RoundedCornerShape(8))
Text("设置DeviceAdmin命令dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver") .background(color = MaterialTheme.colorScheme.primaryContainer)
Text("设置DeviceOwner命令dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver") .padding(10.dp)
) {
Text(text = "Device Admin", style = MaterialTheme.typography.titleLarge)
Text("Device Admin: $isda")
SelectionContainer {
Text("dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver")
}
Button(onClick = {Runtime.getRuntime().exec("su -c \"dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver\"")}) {
Text("获取DeviceAdmin需root未测试")
}
Button(onClick = { ActivateDeviceAdmin(myDpm, myComponent, myContext) }) {
Text("在设置中激活DeviceAdmin")
}
Button(onClick = {myDpm.removeActiveAdmin(myComponent)}) {
Text("不当Device Admin了")
} }
} }
Button(onClick = {Runtime.getRuntime().exec("su -c \"dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver\"")}) { Spacer(modifier = Modifier.padding(6.dp))
Text("获取DeviceAdmin需root未测试") Column(
modifier = Modifier
.clip(RoundedCornerShape(8))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(10.dp)
) {
Text(text = "Device Owner", style = MaterialTheme.typography.titleLarge)
Text("Device Owner: $isdo")
SelectionContainer {
Text("dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver")
}
Button(onClick = {Runtime.getRuntime().exec("su -c \"dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver\"")}) {
Text("获取DeviceOwner需root未测试")
}
Button(onClick = {myDpm.clearDeviceOwnerApp("com.binbin.androidowner")}) {
Text("不当Device Owner了")
}
Text("注意!在这里清除权限不会清除配置。比如:被停用的应用会保持停用状态")
var lockScrInfo by remember { mutableStateOf("") }
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
Text("设置锁屏DeviceOwner信息")
}
} }
Button(onClick = {Runtime.getRuntime().exec("su -c \"dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver\"")}) { Spacer(modifier = Modifier.padding(6.dp))
Text("获取DeviceOwner需root未测试") Column(
} modifier = Modifier
Text("注意!在这里清除权限不会清除配置。比如:被停用的应用会保持停用状态") .clip(RoundedCornerShape(8))
Button(onClick = {myDpm.clearDeviceOwnerApp("com.binbin.androidowner")}) { .background(color = MaterialTheme.colorScheme.primaryContainer)
Text("不当Device Owner了") .padding(10.dp)
} ) {
Button(onClick = {myDpm.removeActiveAdmin(myComponent)}) { Text("Profile Owner是一个过时的功能目前在这个应用里没啥用。")
Text("不当Device Admin了同时会取消DeviceOwner") Text(text = "Profile Owner", style = MaterialTheme.typography.titleLarge)
Text("Profile Owner: $ispo")
SelectionContainer {
Text("dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver")
}
Button(onClick = {Runtime.getRuntime().exec("su -c \"dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver\"")}) {
Text("获取ProfileOwner需root未测试")
}
Button(onClick = {myDpm.clearProfileOwner(myComponent)}) {
Text("不当Profile Owner了")
}
} }
} }
} }
fun ActivateDeviceAdmin(myDpm: DevicePolicyManager,myComponent: ComponentName,myContext: Context){
if (!myDpm.isAdminActive(myComponent)) {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, myComponent)
intent.putExtra(
DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"在这里激活Android Owner"
)
startActivity(myContext,intent,null)
} else {
Toast.makeText(myContext, "已经激活", Toast.LENGTH_SHORT).show()
}
}

View File

@@ -21,5 +21,6 @@ fun UIControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
Button(onClick = {myDpm.setStatusBarDisabled(myComponent,false)}) { Button(onClick = {myDpm.setStatusBarDisabled(myComponent,false)}) {
Text("显示状态栏") Text("显示状态栏")
} }
Text("也许只能控制状态栏上的通知图标")
} }
} }

View File

@@ -2,8 +2,10 @@ package com.binbin.androidowner
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.os.Build
import android.os.UserManager import android.os.UserManager
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@@ -11,15 +13,18 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button import androidx.compose.material.icons.Icons
import androidx.compose.material3.ButtonDefaults import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@@ -32,58 +37,78 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",myComponent, myDpm) 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_CONFIG_WIFI,R.string.config_wifi,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",myComponent, myDpm) if(Build.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)
}
UserRestrictionItem(UserManager.DISALLOW_DEBUGGING_FEATURES,R.string.debug_features,"",myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_DEBUGGING_FEATURES,R.string.debug_features,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),myComponent, myDpm) 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_ADJUST_VOLUME,R.string.adjust_volume,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",myComponent, myDpm)
if(Build.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_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_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){
Text("以下功能需要安卓9或以上飞行模式、位置信息、调整亮度")
}
if(Build.VERSION.SDK_INT<31){
Text("以下功能需要安卓12或以上相机切换")
}
} }
} }
@Composable @Composable
private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDescription:String, myComponent: ComponentName, myDpm: DevicePolicyManager){ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDescription:String, myComponent: ComponentName, myDpm: DevicePolicyManager){
var strictState by remember{ mutableStateOf(myDpm.getUserRestrictions(myComponent).getBoolean(restriction)) } val isdo = myDpm.isDeviceOwnerApp("com.binbin.androidowner")
Column( var strictState by remember{ mutableStateOf(false) }
Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 5.dp, horizontal = 8.dp) .padding(vertical = 5.dp, horizontal = 8.dp)
.clip(RoundedCornerShape(10)) .clip(RoundedCornerShape(10))
.background(color = MaterialTheme.colorScheme.secondaryContainer) .background(color = MaterialTheme.colorScheme.secondaryContainer)
.padding(5.dp) .padding(5.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
){ ){
Text( Row(
text = stringResource(itemName), verticalAlignment = Alignment.CenterVertically
style = MaterialTheme.typography.titleLarge ) {
) Icon(
if(restrictionDescription!=""){Text(restrictionDescription)} imageVector = Icons.Outlined.Info,
Text(text = "禁止:$strictState") contentDescription = null,
Row { modifier = Modifier.padding(horizontal = 8.dp)
Button( )
onClick = { Column(
myDpm.clearUserRestriction(myComponent,restriction) modifier = Modifier.align(Alignment.CenterVertically)
) {
Text(
text = stringResource(itemName),
style = MaterialTheme.typography.titleLarge
)
if(restrictionDescription!=""){Text(restrictionDescription)}
}
}
if(isdo){
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) strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
}, },
modifier = Modifier.padding(3.dp) enabled = isdo
) { )
Text(stringResource(R.string.allow))
}
Button(
onClick = {
myDpm.addUserRestriction(myComponent,restriction)
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
},
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
) ,
modifier = Modifier.padding(2.dp)
) {
Text(text = stringResource(R.string.disallow))
}
} }
} }
} }

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M15.5,1h-8C6.12,1 5,2.12 5,3.5v17C5,21.88 6.12,23 7.5,23h8c1.38,0 2.5,-1.12 2.5,-2.5v-17C18,2.12 16.88,1 15.5,1zM11.5,22c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM16,18L7,18L7,4h9v14z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM12,11.99h7c-0.53,4.12 -3.28,7.79 -7,8.94L12,12L5,12L5,6.3l7,-3.11v8.8z"/>
</vector>

View File

@@ -1,17 +1,17 @@
<resources> <resources>
<string name="app_name">Android Owner</string> <string name="app_name">Android Owner</string>
<string name="bluetooth">蓝牙</string> <string name="bluetooth">蓝牙</string>
<string name="airplane_mode">飞行模式需安卓9</string> <string name="airplane_mode">飞行模式</string>
<string name="config_wifi">配置Wi-Fi</string> <string name="config_wifi">配置Wi-Fi</string>
<string name="debug_features">调试功能</string> <string name="debug_features">调试功能</string>
<string name="config_location">配置位置信息需安卓9</string> <string name="config_location">配置位置信息</string>
<string name="config_mobile_network">配置移动数据</string> <string name="config_mobile_network">配置移动数据</string>
<string name="create_windows">创建窗口</string> <string name="create_windows">创建窗口</string>
<string name="allow">允许</string> <string name="allow">允许</string>
<string name="disallow">禁止</string> <string name="disallow">禁止</string>
<string name="is_disallow">是否禁止:</string> <string name="is_disallow">是否禁止:</string>
<string name="adjust_volume">调整音量</string> <string name="adjust_volume">调整音量</string>
<string name="config_brightness">调整亮度需安卓9</string> <string name="config_brightness">调整亮度</string>
<string name="install_apps">安装应用</string> <string name="install_apps">安装应用</string>
<string name="sms">短信</string> <string name="sms">短信</string>
<string name="apps_ctrl">控制应用</string> <string name="apps_ctrl">控制应用</string>
@@ -28,4 +28,7 @@
<string name="ui_ctrl_desc">目前没啥功能</string> <string name="ui_ctrl_desc">目前没啥功能</string>
<string name="app_manage_desc">非DeviceOwner勿入</string> <string name="app_manage_desc">非DeviceOwner勿入</string>
<string name="user_restrict_desc">限制一些功能</string> <string name="user_restrict_desc">限制一些功能</string>
<string name="autofill">自动填充服务</string>
<string name="camera_toggle">切换相机</string>
<string name="bt_share">蓝牙分享</string>
</resources> </resources>