support profile owner

This commit is contained in:
BinTianqi
2024-01-22 14:13:20 +08:00
parent 01c0a119a6
commit 59cbc1246a
9 changed files with 279 additions and 187 deletions

View File

@@ -4,6 +4,9 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/> <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIPE_DATA"/>
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS"/>
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"

View File

@@ -87,10 +87,10 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
.padding(8.dp), .padding(8.dp),
horizontalArrangement = Arrangement.SpaceAround horizontalArrangement = Arrangement.SpaceAround
) { ) {
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,false)}, enabled = isDeviceOwner(myDpm)) { Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,false)}, enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)) {
Text("取消防卸载") Text("取消防卸载")
} }
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}, enabled = isDeviceOwner(myDpm)) { Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}, enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)) {
Text("防卸载") Text("防卸载")
} }
} }
@@ -113,7 +113,7 @@ private fun AppManageItem(
setMethod:(b:Boolean)->Unit setMethod:(b:Boolean)->Unit
){ ){
var isEnabled by remember{ mutableStateOf(false) } var isEnabled by remember{ mutableStateOf(false) }
if(myDpm.isDeviceOwnerApp("com.binbin.androidowner")){ if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){
isEnabled = getMethod() isEnabled = getMethod()
} }
Row( Row(
@@ -141,7 +141,7 @@ private fun AppManageItem(
setMethod(!isEnabled) setMethod(!isEnabled)
isEnabled = getMethod() isEnabled = getMethod()
}, },
enabled = myDpm.isDeviceOwnerApp("com.binbin.androidowner") enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)
) )
} }
} }

View File

@@ -4,9 +4,9 @@ import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.UserManager
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement 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
@@ -21,7 +21,6 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch 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
@@ -46,27 +45,36 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName,myConte
.padding(bottom = 20.dp) .padding(bottom = 20.dp)
.navigationBarsPadding() .navigationBarsPadding()
) { ) {
if(isDeviceOwner(myDpm)){
DeviceCtrlItem(R.string.disable_cam,R.string.place_holder, R.drawable.photo_camera_fill0,myDpm,{myDpm.getCameraDisabled(null)},{b -> myDpm.setCameraDisabled(myComponent,b)}) DeviceCtrlItem(R.string.disable_cam,R.string.place_holder, R.drawable.photo_camera_fill0,myDpm,{myDpm.getCameraDisabled(null)},{b -> myDpm.setCameraDisabled(myComponent,b)})
}
if(isDeviceOwner(myDpm)){
DeviceCtrlItem(R.string.disable_scrcap,R.string.aosp_scrrec_also_work,R.drawable.screenshot_fill0,myDpm,{myDpm.getScreenCaptureDisabled(null)},{b -> myDpm.setScreenCaptureDisabled(myComponent,b) }) DeviceCtrlItem(R.string.disable_scrcap,R.string.aosp_scrrec_also_work,R.drawable.screenshot_fill0,myDpm,{myDpm.getScreenCaptureDisabled(null)},{b -> myDpm.setScreenCaptureDisabled(myComponent,b) })
if(VERSION.SDK_INT>=34){ }
if(VERSION.SDK_INT>=34&&(isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser))){
DeviceCtrlItem(R.string.hide_status_bar,R.string.may_hide_notifi_icon_only,R.drawable.notifications_fill0,myDpm,{myDpm.isStatusBarDisabled},{b -> myDpm.setStatusBarDisabled(myComponent,b) }) DeviceCtrlItem(R.string.hide_status_bar,R.string.may_hide_notifi_icon_only,R.drawable.notifications_fill0,myDpm,{myDpm.isStatusBarDisabled},{b -> myDpm.setStatusBarDisabled(myComponent,b) })
} }
if(VERSION.SDK_INT>=30){ if(VERSION.SDK_INT>=30&&isDeviceOwner(myDpm)){
DeviceCtrlItem(R.string.auto_time,R.string.place_holder,R.drawable.schedule_fill0,myDpm,{myDpm.getAutoTimeEnabled(myComponent)},{b -> myDpm.setAutoTimeEnabled(myComponent,b) }) DeviceCtrlItem(R.string.auto_time,R.string.place_holder,R.drawable.schedule_fill0,myDpm,{myDpm.getAutoTimeEnabled(myComponent)},{b -> myDpm.setAutoTimeEnabled(myComponent,b) })
DeviceCtrlItem(R.string.auto_timezone,R.string.place_holder,R.drawable.globe_fill0,myDpm,{myDpm.getAutoTimeZoneEnabled(myComponent)},{b -> myDpm.setAutoTimeZoneEnabled(myComponent,b) }) DeviceCtrlItem(R.string.auto_timezone,R.string.place_holder,R.drawable.globe_fill0,myDpm,{myDpm.getAutoTimeZoneEnabled(myComponent)},{b -> myDpm.setAutoTimeZoneEnabled(myComponent,b) })
} }
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){
DeviceCtrlItem(R.string.master_mute,R.string.place_holder,R.drawable.volume_up_fill0,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) }) DeviceCtrlItem(R.string.master_mute,R.string.place_holder,R.drawable.volume_up_fill0,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) })
if(VERSION.SDK_INT>=26){ }
if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)|| isProfileOwner(myDpm))){
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,R.drawable.backup_fill0,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) }) DeviceCtrlItem(R.string.backup_service,R.string.place_holder,R.drawable.backup_fill0,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
} }
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){
DeviceCtrlItem(R.string.disable_bt_contact_share,R.string.place_holder,R.drawable.account_circle_fill0,myDpm,{myDpm.getBluetoothContactSharingDisabled(myComponent)},{b -> myDpm.setBluetoothContactSharingDisabled(myComponent,b)}) DeviceCtrlItem(R.string.disable_bt_contact_share,R.string.place_holder,R.drawable.account_circle_fill0,myDpm,{myDpm.getBluetoothContactSharingDisabled(myComponent)},{b -> myDpm.setBluetoothContactSharingDisabled(myComponent,b)})
if(VERSION.SDK_INT>=31){ }
if(VERSION.SDK_INT>=31&&isDeviceOwner(myDpm)){
if(myDpm.canUsbDataSignalingBeDisabled()){ if(myDpm.canUsbDataSignalingBeDisabled()){
DeviceCtrlItem(R.string.usb_signal,R.string.place_holder,R.drawable.usb_fill0,myDpm,{myDpm.isUsbDataSignalingEnabled},{b -> myDpm.isUsbDataSignalingEnabled = b }) DeviceCtrlItem(R.string.usb_signal,R.string.place_holder,R.drawable.usb_fill0,myDpm,{myDpm.isUsbDataSignalingEnabled},{b -> myDpm.isUsbDataSignalingEnabled = b })
}else{ }else{
Text("你的设备不支持关闭USB信号") Text("你的设备不支持关闭USB信号")
} }
} }
if(VERSION.SDK_INT>=28){
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -84,7 +92,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName,myConte
Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show()
} }
}, },
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser)
) { ) {
Text("禁用锁屏(需无密码)") Text("禁用锁屏(需无密码)")
} }
@@ -97,11 +105,13 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName,myConte
Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show()
} }
}, },
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser)
) { ) {
Text("启用锁屏") Text("启用锁屏")
} }
} }
}
Row( Row(
horizontalArrangement = Arrangement.SpaceAround, horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier modifier = Modifier
@@ -141,10 +151,16 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName,myConte
if(VERSION.SDK_INT<34){ if(VERSION.SDK_INT<34){
Text("隐藏状态栏需要API34") Text("隐藏状态栏需要API34")
} }
Button(onClick = {myDpm.uninstallAllUserCaCerts(myComponent)},modifier = Modifier.align(Alignment.CenterHorizontally), enabled = isDeviceOwner(myDpm)) { Button(
onClick = {myDpm.uninstallAllUserCaCerts(myComponent)},
modifier = Modifier.align(Alignment.CenterHorizontally),
enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)
) {
Text(text = "清除用户Ca证书") Text(text = "清除用户Ca证书")
} }
if(isDeviceOwner(myDpm)){
SysUpdatePolicy(myDpm,myComponent,myContext) SysUpdatePolicy(myDpm,myComponent,myContext)
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -168,7 +184,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName,myConte
containerColor = if(confirmed){MaterialTheme.colorScheme.primary}else{MaterialTheme.colorScheme.error}, containerColor = if(confirmed){MaterialTheme.colorScheme.primary}else{MaterialTheme.colorScheme.error},
contentColor = if(confirmed){MaterialTheme.colorScheme.onPrimary}else{MaterialTheme.colorScheme.onError} contentColor = if(confirmed){MaterialTheme.colorScheme.onPrimary}else{MaterialTheme.colorScheme.onError}
), ),
enabled = isDeviceOwner(myDpm) enabled = myDpm.isAdminActive(myComponent)
) { ) {
Text(text = if(confirmed){"取消"}else{"确定"}) Text(text = if(confirmed){"取消"}else{"确定"})
} }
@@ -241,16 +257,13 @@ private fun DeviceCtrlItem(
} }
} }
} }
if(isDeviceOwner(myDpm)){
isEnabled = getMethod() isEnabled = getMethod()
}
Switch( Switch(
checked = isEnabled, checked = isEnabled,
onCheckedChange = { onCheckedChange = {
setMethod(!isEnabled) setMethod(!isEnabled)
isEnabled=getMethod() isEnabled=getMethod()
}, }
enabled = isDeviceOwner(myDpm)
) )
} }
} }

View File

@@ -128,7 +128,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent,mainContext)}) composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent,mainContext)})
composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)}) composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)})
composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)}) composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)})
composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent)}) composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent,mainContext)})
composable(route = "UserManage", content = { UserManage(mainDpm,mainComponent,mainContext)}) composable(route = "UserManage", content = { UserManage(mainDpm,mainComponent,mainContext)})
composable(route = "Password", content = { Password(mainDpm,mainComponent,mainContext)}) composable(route = "Password", content = { Password(mainDpm,mainComponent,mainContext)})
} }
@@ -139,7 +139,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
fun HomePage(navCtrl:NavHostController,myDpm:DevicePolicyManager,myComponent:ComponentName){ fun HomePage(navCtrl:NavHostController,myDpm:DevicePolicyManager,myComponent:ComponentName){
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 activateType = if(isdo){"Device Owner"}else if(isda){"Device Admin"}else{""} val activateType = if(isDeviceOwner(myDpm)){"Device Owner"}else if(isProfileOwner(myDpm)){"Profile Owner"}else if(isda){"Device Admin"}else{""}
val isActivated = if(isdo||isda){"已激活"}else{"未激活"} val isActivated = if(isdo||isda){"已激活"}else{"未激活"}
Column { Column {
Row( Row(
@@ -235,3 +235,7 @@ fun RadioButtonItem(
fun isDeviceOwner(dpm:DevicePolicyManager): Boolean { fun isDeviceOwner(dpm:DevicePolicyManager): Boolean {
return dpm.isDeviceOwnerApp("com.binbin.androidowner") return dpm.isDeviceOwnerApp("com.binbin.androidowner")
} }
fun isProfileOwner(dpm:DevicePolicyManager): Boolean {
return dpm.isProfileOwnerApp("com.binbin.androidowner")
}

View File

@@ -145,19 +145,26 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp) .padding(horizontal = 8.dp, vertical = 4.dp)
.clip(RoundedCornerShape(10)) .clip(RoundedCornerShape(16.dp))
.background(color = MaterialTheme.colorScheme.primaryContainer) .background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(10.dp) .padding(10.dp)
) { ) {
TextField( TextField(
value = newPwd, value = newPwd,
onValueChange = {newPwd=it}, onValueChange = {newPwd=it},
enabled = !confirmed&& isDeviceOwner(myDpm), enabled = !confirmed&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm)),
label = { Text("密码")}, label = { Text("密码")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
) )
Text(text = stringResource(R.string.reset_pwd_desc), modifier = Modifier.padding(vertical = 5.dp)) Text(text = stringResource(R.string.reset_pwd_desc), modifier = Modifier.padding(vertical = 5.dp))
var resetPwdFlag by remember{ mutableStateOf(0) }
RadioButtonItem("RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT",
{resetPwdFlag==DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT},
{resetPwdFlag=DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT})
RadioButtonItem("RESET_PASSWORD_REQUIRE_ENTRY",{resetPwdFlag==DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY},
{resetPwdFlag=DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY})
RadioButtonItem("",{resetPwdFlag==0},{resetPwdFlag=0})
Row { Row {
Button( Button(
onClick = { onClick = {
@@ -165,14 +172,14 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
}else{ Toast.makeText(myContext, "需要4位数字或字母", Toast.LENGTH_SHORT).show() } }else{ Toast.makeText(myContext, "需要4位数字或字母", Toast.LENGTH_SHORT).show() }
}, },
modifier = Modifier.padding(end = 10.dp), modifier = Modifier.padding(end = 10.dp),
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)
) { ) {
Text("确认密码") Text("确认密码")
} }
if(VERSION.SDK_INT>=26){ if(VERSION.SDK_INT>=26){
Button( Button(
onClick = { onClick = {
val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,0) val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,resetPwdFlag)
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show() if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() } }else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false confirmed=false
@@ -185,7 +192,7 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
}else{ }else{
Button( Button(
onClick = { onClick = {
val resetSuccess = myDpm.resetPassword(newPwd,0) val resetSuccess = myDpm.resetPassword(newPwd,resetPwdFlag)
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show() if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() } }else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false confirmed=false

View File

@@ -102,6 +102,58 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
Text("或者进入设置 -> 安全 -> 更多安全设置 -> 设备管理应用 -> Android Owner") Text("或者进入设置 -> 安全 -> 更多安全设置 -> 设备管理应用 -> Android Owner")
} }
} }
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(10.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(text = "Profile Owner", style = MaterialTheme.typography.titleLarge)
Text(if(isProfileOwner(myDpm)){"已激活"}else{"未激活"})
}
if(isProfileOwner(myDpm)&&VERSION.SDK_INT>=24){
Button(
onClick = {
myDpm.clearProfileOwner(myComponent)
navCtrl.navigate("HomePage") {
popUpTo(
navCtrl.graph.findStartDestination().id
) { saveState = true }
}
}
) {
Text("撤销")
}
}
}
if(!isProfileOwner(myDpm)){
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp)
.clip(RoundedCornerShape(15.dp))
.background(color = MaterialTheme.colorScheme.tertiaryContainer)
.padding(10.dp),
horizontalAlignment = Alignment.Start
) {
if(!isDeviceOwner(myDpm)){
Text("你可以在adb shell中使用以下命令激活Profile Owner")
SelectionContainer {
Text("dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver",
color = MaterialTheme.colorScheme.onTertiaryContainer)
}
Text("一个设备只能有一个Device owner强烈建议激活Device owner")
}
if(isDeviceOwner(myDpm)){
Text("Device owner创建其他用户后这个应用会成为新用户的Profile owner")
}
}
}
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -131,7 +183,7 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
} }
} }
} }
if(isdo||isda){ if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)||myDpm.isAdminActive(myComponent)){
Text( Text(
text = "注意!在这里撤销权限不会清除配置。比如:被停用的应用会保持停用状态", text = "注意!在这里撤销权限不会清除配置。比如:被停用的应用会保持停用状态",
color = MaterialTheme.colorScheme.onErrorContainer, color = MaterialTheme.colorScheme.onErrorContainer,
@@ -143,27 +195,7 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
.padding(6.dp) .padding(6.dp)
) )
} }
if(isdo){ if(!isdo&&!isProfileOwner(myDpm)){
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(8.dp)
) {
Text(text = "设备信息", style = MaterialTheme.typography.titleLarge)
if(VERSION.SDK_INT>=30){
val orgDevice = myDpm.isOrganizationOwnedDeviceWithManagedProfile
Text("由组织拥有的工作资料设备:$orgDevice")
}
if(VERSION.SDK_INT>=34&&(myDpm.isProfileOwnerApp("com.binbin.androidowner")||myDpm.isManagedProfile(myComponent))){
val financed = myDpm.isDeviceFinanced
Text("Financed Device : $financed")
}
}
}
if(!isdo){
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -183,6 +215,25 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
} }
} }
} }
if(VERSION.SDK_INT>=30){
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(8.dp)
) {
Text(text = "设备信息", style = MaterialTheme.typography.titleLarge)
val orgDevice = myDpm.isOrganizationOwnedDeviceWithManagedProfile
Text("由组织拥有的受管理资料设备:$orgDevice")
Text("Managed profile: ${myDpm.isManagedProfile(myComponent)}")
if(VERSION.SDK_INT>=34&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){
val financed = myDpm.isDeviceFinanced
Text("企业资产 : $financed")
}
}
}
if(isdo&&VERSION.SDK_INT>=24){ if(isdo&&VERSION.SDK_INT>=24){
DeviceOwnerInfo(R.string.owner_lockscr_info,R.string.place_holder,R.string.owner_lockscr_info,focusManager,myContext, DeviceOwnerInfo(R.string.owner_lockscr_info,R.string.place_holder,R.string.owner_lockscr_info,focusManager,myContext,

View File

@@ -1,5 +1,6 @@
package com.binbin.androidowner package com.binbin.androidowner
import android.app.ActivityManager
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
@@ -43,7 +44,6 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
//val myUM = myContext.getSystemService(Context.USER_SERVICE) //val myUM = myContext.getSystemService(Context.USER_SERVICE)
val currentUser = android.os.Process.myUserHandle() val currentUser = android.os.Process.myUserHandle()
val userList = Test.returnUsers(myContext) val userList = Test.returnUsers(myContext)
Text("因为我的模拟器的多用户无法使用,部分功能并未测试")
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -60,16 +60,16 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
Text("支持多用户:${UserManager.supportsMultipleUsers()}") Text("支持多用户:${UserManager.supportsMultipleUsers()}")
} }
if(VERSION.SDK_INT>=31){ if(VERSION.SDK_INT>=31){
Text("Headless system user: ${UserManager.isHeadlessSystemUserMode()}") Text("系统用户: ${UserManager.isHeadlessSystemUserMode()}")
} }
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
if (VERSION.SDK_INT >= 28&& isDeviceOwner(myDpm)) { if (VERSION.SDK_INT >= 28) {
val logoutable = myDpm.isLogoutEnabled val logoutable = myDpm.isLogoutEnabled
Text(text = "用户可以退出 : $logoutable") Text(text = "用户可以退出 : $logoutable")
val ephemeralUser = myDpm.isEphemeralUser(myComponent) val ephemeralUser = myDpm.isEphemeralUser(myComponent)
Text(text = "临时用户: $ephemeralUser") Text(text = "临时用户: $ephemeralUser")
val affiliatedUser = myDpm.isAffiliatedUser val affiliatedUser = myDpm.isAffiliatedUser
Text(text = "Affiliated User: $affiliatedUser") Text(text = "次级用户: $affiliatedUser")
} }
Spacer(Modifier.padding(5.dp)) Spacer(Modifier.padding(5.dp))
Text("切换用户后或设备重启后会删除临时用户") Text("切换用户后或设备重启后会删除临时用户")
@@ -88,7 +88,7 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
var resultForLogout by remember{ mutableIntStateOf(-1) } var resultForLogout by remember{ mutableIntStateOf(-1) }
var resultForStop by remember{ mutableIntStateOf(-1) } var resultForStop by remember{ mutableIntStateOf(-1) }
Text("登出用户需要成为次级用户的Profile Owner") Text("登出用户需要成为次级用户的Profile Owner")
Button(onClick = {resultForLogout = myDpm.logoutUser(myComponent)}, enabled = isDeviceOwner(myDpm)) { Button(onClick = {resultForLogout = myDpm.logoutUser(myComponent)}, enabled = isProfileOwner(myDpm)) {
Text("登出用户") Text("登出用户")
} }
if(resultForLogout!=-1){ if(resultForLogout!=-1){
@@ -100,6 +100,11 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
if(resultForStop!=-1){ if(resultForStop!=-1){
Text(userOperationResultCode(resultForStop)) Text(userOperationResultCode(resultForStop))
} }
if(isProfileOwner(myDpm)){
Button(onClick = {myDpm.setProfileEnabled(myComponent)}) {
Text(text = "启用资料")
}
}
} }
Button( Button(
onClick = { onClick = {
@@ -169,10 +174,10 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
}else{ }else{
Text("创建用户需安卓7") Text("创建用户需安卓7")
} }
UserSessionMessage("用户名","用户名",myDpm,myContext,{null},{msg -> myDpm.setProfileName(myComponent, msg.toString())}) UserSessionMessage("用户名","用户名",true,myDpm,myContext,{null},{msg -> myDpm.setProfileName(myComponent, msg.toString())})
if(VERSION.SDK_INT>=28){ if(VERSION.SDK_INT>=28){
UserSessionMessage("用户会话开始消息","消息",myDpm,myContext,{myDpm.getStartUserSessionMessage(myComponent)},{msg -> myDpm.setStartUserSessionMessage(myComponent,msg)}) UserSessionMessage("用户会话开始消息","消息",false,myDpm,myContext,{myDpm.getStartUserSessionMessage(myComponent)},{msg -> myDpm.setStartUserSessionMessage(myComponent,msg)})
UserSessionMessage("用户会话结束消息","消息",myDpm,myContext,{myDpm.getEndUserSessionMessage(myComponent)},{msg -> myDpm.setEndUserSessionMessage(myComponent,msg)}) UserSessionMessage("用户会话结束消息","消息",false,myDpm,myContext,{myDpm.getEndUserSessionMessage(myComponent)},{msg -> myDpm.setEndUserSessionMessage(myComponent,msg)})
} }
Spacer(Modifier.padding(vertical = 30.dp)) Spacer(Modifier.padding(vertical = 30.dp))
} }
@@ -182,6 +187,7 @@ fun UserManage(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext: Co
fun UserSessionMessage( fun UserSessionMessage(
text:String, text:String,
textField:String, textField:String,
profileOwner:Boolean,
myDpm:DevicePolicyManager, myDpm:DevicePolicyManager,
myContext: Context, myContext: Context,
get:()->CharSequence?, get:()->CharSequence?,
@@ -196,29 +202,26 @@ fun UserSessionMessage(
.padding(10.dp) .padding(10.dp)
) { ) {
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
var msg:CharSequence? by remember{ mutableStateOf(null) } var msg by remember{ mutableStateOf(if(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&profileOwner)){ if(get()==null){""}else{get().toString()} }else{""}) }
if(isDeviceOwner(myDpm)){
msg = if(get()==null){""}else{get()}
}
Text(text = text, style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onPrimaryContainer) Text(text = text, style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onPrimaryContainer)
TextField( TextField(
value = msg.toString(), value = msg,
onValueChange = {msg=it}, onValueChange = {msg=it},
label = {Text(textField)}, label = {Text(textField)},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.padding(vertical = 6.dp), modifier = Modifier.padding(vertical = 6.dp),
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&profileOwner)
) )
Row { Row {
Button( Button(
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
setMsg(msg) setMsg(msg)
msg = if(get()==null){""}else{get()} msg = if(get()==null){""}else{get().toString()}
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
}, },
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&profileOwner)
) { ) {
Text("应用") Text("应用")
} }
@@ -227,10 +230,10 @@ fun UserSessionMessage(
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
setMsg(null) setMsg(null)
msg = if(get()==null){""}else{get()} msg = if(get()==null){""}else{get().toString()}
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
}, },
enabled = isDeviceOwner(myDpm) enabled = isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&profileOwner)
) { ) {
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.content.Context
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@@ -35,7 +37,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@Composable @Composable
fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName,myContext: Context){
val verticalScrolling = rememberScrollState() val verticalScrolling = rememberScrollState()
var currentSection by remember{ mutableIntStateOf(0) } var currentSection by remember{ mutableIntStateOf(0) }
Column( Column(
@@ -46,110 +48,113 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
.navigationBarsPadding() .navigationBarsPadding()
) { ) {
Text("打开开关后会禁用对应的功能") Text("打开开关后会禁用对应的功能")
if(isProfileOwner(myDpm)){
Text("Profile owner无法更改部分功能")
}
SectionTab("网络和互联网",{currentSection==1}) { currentSection = if(currentSection==1){ 0 }else{ 1 } } SectionTab("网络和互联网",{currentSection==1}) { currentSection = if(currentSection==1){ 0 }else{ 1 } }
if(currentSection==1){ if(currentSection==1){
UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",R.drawable.signal_cellular_alt_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",R.drawable.signal_cellular_alt_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_DATA_ROAMING,R.string.data_roaming,"",R.drawable.network_cell_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_DATA_ROAMING,R.string.data_roaming,"",R.drawable.network_cell_fill0, myContext, myComponent, myDpm)}
if(VERSION.SDK_INT>=34){ if(VERSION.SDK_INT>=34){
UserRestrictionItem(UserManager.DISALLOW_CELLULAR_2G,R.string.cellular_2g,"",R.drawable.network_cell_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CELLULAR_2G,R.string.cellular_2g,"",R.drawable.network_cell_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,R.string.ultra_wideband_radio,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,R.string.ultra_wideband_radio,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
} }
UserRestrictionItem(UserManager.DISALLOW_CONFIG_WIFI,R.string.config_wifi,"",R.drawable.wifi_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_WIFI,R.string.config_wifi,"",R.drawable.wifi_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=33){ if(VERSION.SDK_INT>=33){
UserRestrictionItem(UserManager.DISALLOW_ADD_WIFI_CONFIG,R.string.add_wifi_conf,"",R.drawable.wifi_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_ADD_WIFI_CONFIG,R.string.add_wifi_conf,"",R.drawable.wifi_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CHANGE_WIFI_STATE,R.string.change_wifi_state,"",R.drawable.wifi_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CHANGE_WIFI_STATE,R.string.change_wifi_state,"",R.drawable.wifi_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_WIFI_DIRECT,R.string.wifi_direct,"",R.drawable.wifi_tethering_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_WIFI_DIRECT,R.string.wifi_direct,"",R.drawable.wifi_tethering_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_WIFI_TETHERING,R.string.wifi_tethering,"",R.drawable.wifi_tethering_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_WIFI_TETHERING,R.string.wifi_tethering,"",R.drawable.wifi_tethering_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI,R.string.share_admin_wifi,"",R.drawable.share_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI,R.string.share_admin_wifi,"",R.drawable.share_fill0, myContext, myComponent, myDpm)
} }
UserRestrictionItem(UserManager.DISALLOW_NETWORK_RESET,R.string.network_reset,"",R.drawable.reset_wrench_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_NETWORK_RESET,R.string.network_reset,"",R.drawable.reset_wrench_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_TETHERING,R.string.config_tethering,"",R.drawable.wifi_tethering_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_TETHERING,R.string.config_tethering,"",R.drawable.wifi_tethering_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_VPN,R.string.config_vpn,"",R.drawable.vpn_key_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_VPN,R.string.config_vpn,"",R.drawable.vpn_key_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=29){UserRestrictionItem(UserManager.DISALLOW_CONFIG_PRIVATE_DNS,R.string.config_private_dns,"",R.drawable.dns_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=29){UserRestrictionItem(UserManager.DISALLOW_CONFIG_PRIVATE_DNS,R.string.config_private_dns,"",R.drawable.dns_fill0, myContext, myComponent, myDpm)}
if(VERSION.SDK_INT>=28){ UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",R.drawable.airplanemode_active_fill0,myComponent, myDpm) } if(VERSION.SDK_INT>=28){ UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",R.drawable.airplanemode_active_fill0, myContext, myComponent, myDpm) }
UserRestrictionItem(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,R.string.config_cell_broadcasts,"",R.drawable.cell_tower_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,R.string.config_cell_broadcasts,"",R.drawable.cell_tower_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_SMS,R.string.sms,"",R.drawable.sms_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_SMS,R.string.sms,"",R.drawable.sms_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_OUTGOING_CALLS,R.string.outgoing_calls,"",R.drawable.phone_forwarded_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_OUTGOING_CALLS,R.string.outgoing_calls,"",R.drawable.phone_forwarded_fill0, myContext, myComponent, myDpm)
} }
SectionTab("其他连接",{currentSection==6}) { currentSection = if(currentSection==6){ 0 }else{ 6 } } SectionTab("其他连接",{currentSection==6}) { currentSection = if(currentSection==6){ 0 }else{ 6 } }
if(currentSection==6){ if(currentSection==6){
if(VERSION.SDK_INT>=26){ if(VERSION.SDK_INT>=26){
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",R.drawable.bluetooth_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",R.drawable.bluetooth_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",R.drawable.bluetooth_searching_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",R.drawable.bluetooth_searching_fill0, myContext, myComponent, myDpm)
} }
UserRestrictionItem(UserManager.DISALLOW_SHARE_LOCATION,R.string.share_location,"",R.drawable.location_on_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_SHARE_LOCATION,R.string.share_location,"",R.drawable.location_on_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",R.drawable.location_on_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",R.drawable.location_on_fill0, myContext, myComponent, myDpm)}
UserRestrictionItem(UserManager.DISALLOW_OUTGOING_BEAM,R.string.outgoing_beam,"",R.drawable.nfc_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_OUTGOING_BEAM,R.string.outgoing_beam,"",R.drawable.nfc_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_USB_FILE_TRANSFER,R.string.usb_file_transfer,"",R.drawable.usb_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_USB_FILE_TRANSFER,R.string.usb_file_transfer,"",R.drawable.usb_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,R.string.mount_physical_media, stringResource(R.string.mount_phisical_media_desc),R.drawable.sd_card_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,R.string.mount_physical_media, stringResource(R.string.mount_phisical_media_desc),R.drawable.sd_card_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_PRINTING,R.string.printing,"",R.drawable.print_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_PRINTING,R.string.printing,"",R.drawable.print_fill0, myContext, myComponent, myDpm)}
} }
SectionTab("应用",{currentSection==2}) { currentSection = if(currentSection==2){ 0 }else{ 2 } } SectionTab("应用",{currentSection==2}) { currentSection = if(currentSection==2){ 0 }else{ 2 } }
if(currentSection==2){ if(currentSection==2){
UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=29){UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,R.string.install_unknown_src_globally,"",R.drawable.android_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=29){UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,R.string.install_unknown_src_globally,"",R.drawable.android_fill0, myContext, myComponent, myDpm)}
UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,R.string.inst_unknown_src,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,R.string.inst_unknown_src,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_UNINSTALL_APPS,R.string.uninstall_apps,"",R.drawable.delete_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_UNINSTALL_APPS,R.string.uninstall_apps,"",R.drawable.delete_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_APPS_CONTROL,R.string.apps_ctrl, stringResource(R.string.apps_ctrl_description),R.drawable.apps_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_APPS_CONTROL,R.string.apps_ctrl, stringResource(R.string.apps_ctrl_description),R.drawable.apps_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=34){ UserRestrictionItem(UserManager.DISALLOW_CONFIG_DEFAULT_APPS,R.string.config_default_apps,"",R.drawable.apps_fill0,myComponent, myDpm) } if(VERSION.SDK_INT>=34){ UserRestrictionItem(UserManager.DISALLOW_CONFIG_DEFAULT_APPS,R.string.config_default_apps,"",R.drawable.apps_fill0, myContext, myComponent, myDpm) }
} }
SectionTab("显示与音量",{currentSection==3}) { currentSection = if(currentSection==3){ 0 }else{ 3 } } SectionTab("显示与音量",{currentSection==3}) { currentSection = if(currentSection==3){ 0 }else{ 3 } }
if(currentSection==3){ if(currentSection==3){
if(VERSION.SDK_INT>=28){ if(VERSION.SDK_INT>=28){
UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",R.drawable.brightness_5_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",R.drawable.brightness_5_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,R.string.config_scr_timeout,"",R.drawable.screen_lock_portrait_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,R.string.config_scr_timeout,"",R.drawable.screen_lock_portrait_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_AMBIENT_DISPLAY,R.string.ambient_display,"",R.drawable.brightness_5_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_AMBIENT_DISPLAY,R.string.ambient_display,"",R.drawable.brightness_5_fill0, myContext, myComponent, myDpm)
} }
UserRestrictionItem(UserManager.DISALLOW_ADJUST_VOLUME,R.string.adjust_volume,"",R.drawable.volume_up_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_ADJUST_VOLUME,R.string.adjust_volume,"",R.drawable.volume_up_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_UNMUTE_MICROPHONE,R.string.unmute_microphone,"",R.drawable.mic_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_UNMUTE_MICROPHONE,R.string.unmute_microphone,"",R.drawable.mic_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=31){ if(VERSION.SDK_INT>=31){
UserRestrictionItem(UserManager.DISALLOW_CAMERA_TOGGLE,R.string.camera_toggle,"",R.drawable.cameraswitch_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CAMERA_TOGGLE,R.string.camera_toggle,"",R.drawable.cameraswitch_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_MICROPHONE_TOGGLE,R.string.microphone_toggle,"",R.drawable.mic_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_MICROPHONE_TOGGLE,R.string.microphone_toggle,"",R.drawable.mic_fill0, myContext, myComponent, myDpm)
} }
} }
SectionTab("用户与工作资料",{currentSection==4}) { currentSection = if(currentSection==4){ 0 }else{ 4 } } SectionTab("用户与工作资料",{currentSection==4}) { currentSection = if(currentSection==4){ 0 }else{ 4 } }
if(currentSection==4){ if(currentSection==4){
UserRestrictionItem(UserManager.DISALLOW_ADD_USER,R.string.add_user,"",R.drawable.account_circle_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_ADD_USER,R.string.add_user,"",R.drawable.account_circle_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_REMOVE_USER,R.string.remove_user,"",R.drawable.account_circle_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_REMOVE_USER,R.string.remove_user,"",R.drawable.account_circle_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_USER_SWITCH,R.string.switch_user,"",R.drawable.account_circle_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_USER_SWITCH,R.string.switch_user,"",R.drawable.account_circle_fill0, myContext, myComponent, myDpm)}
if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_SET_USER_ICON,R.string.set_user_icon,"",R.drawable.account_circle_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_SET_USER_ICON,R.string.set_user_icon,"",R.drawable.account_circle_fill0, myContext, myComponent, myDpm)}
UserRestrictionItem(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,R.string.cross_profile_copy, stringResource(R.string.cross_profile_copy_desc),R.drawable.content_paste_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,R.string.cross_profile_copy, stringResource(R.string.cross_profile_copy_desc),R.drawable.content_paste_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=26){ if(VERSION.SDK_INT>=26){
UserRestrictionItem(UserManager.DISALLOW_ADD_MANAGED_PROFILE,R.string.add_managed_profile,"",R.drawable.work_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_ADD_MANAGED_PROFILE,R.string.add_managed_profile,"",R.drawable.work_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,R.string.remove_managed_profile,"",R.drawable.work_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,R.string.remove_managed_profile,"",R.drawable.work_fill0, myContext, myComponent, myDpm)
} }
if(VERSION.SDK_INT>=28){ if(VERSION.SDK_INT>=28){
UserRestrictionItem(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,R.string.share_into_managed_profile,"",R.drawable.share_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,R.string.share_into_managed_profile,"",R.drawable.share_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_UNIFIED_PASSWORD,R.string.unifiied_pwd,"",R.drawable.work_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_UNIFIED_PASSWORD,R.string.unifiied_pwd,"",R.drawable.work_fill0, myContext, myComponent, myDpm)
} }
} }
SectionTab("杂项",{currentSection==5}) { currentSection = if(currentSection==5){ 0 }else{ 5 } } SectionTab("杂项",{currentSection==5}) { currentSection = if(currentSection==5){ 0 }else{ 5 } }
if(currentSection==5){ if(currentSection==5){
if(VERSION.SDK_INT>=26){ UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",R.drawable.password_fill0,myComponent, myDpm) } if(VERSION.SDK_INT>=26){ UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",R.drawable.password_fill0, myContext, myComponent, myDpm) }
UserRestrictionItem(UserManager.DISALLOW_CONFIG_CREDENTIALS,R.string.config_credentials,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_CREDENTIALS,R.string.config_credentials,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=29){ if(VERSION.SDK_INT>=29){
UserRestrictionItem(UserManager.DISALLOW_CONTENT_CAPTURE,R.string.content_capture,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONTENT_CAPTURE,R.string.content_capture,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONTENT_SUGGESTIONS,R.string.content_suggestions,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONTENT_SUGGESTIONS,R.string.content_suggestions,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
} }
UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),R.drawable.web_asset,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),R.drawable.web_asset, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_SET_WALLPAPER,R.string.set_wallpaper,"",R.drawable.wallpaper_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=24){UserRestrictionItem(UserManager.DISALLOW_SET_WALLPAPER,R.string.set_wallpaper,"",R.drawable.wallpaper_fill0, myContext, myComponent, myDpm)}
if(VERSION.SDK_INT>=34){ UserRestrictionItem(UserManager.DISALLOW_GRANT_ADMIN,R.string.grant_admin,"",R.drawable.android_fill0,myComponent, myDpm) } if(VERSION.SDK_INT>=34){ UserRestrictionItem(UserManager.DISALLOW_GRANT_ADMIN,R.string.grant_admin,"",R.drawable.android_fill0, myContext, myComponent, myDpm) }
UserRestrictionItem(UserManager.DISALLOW_FUN,R.string.`fun`,"可能会影响谷歌商店的游戏",R.drawable.stadia_controller_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_FUN,R.string.`fun`,"可能会影响谷歌商店的游戏",R.drawable.stadia_controller_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_MODIFY_ACCOUNTS,R.string.modify_accounts,"",R.drawable.manage_accounts_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_MODIFY_ACCOUNTS,R.string.modify_accounts,"",R.drawable.manage_accounts_fill0, myContext, myComponent, myDpm)
if(VERSION.SDK_INT>=28){ if(VERSION.SDK_INT>=28){
UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCALE,R.string.config_locale,"",R.drawable.language_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCALE,R.string.config_locale,"",R.drawable.language_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_CONFIG_DATE_TIME,R.string.config_date_time,"",R.drawable.schedule_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_CONFIG_DATE_TIME,R.string.config_date_time,"",R.drawable.schedule_fill0, myContext, myComponent, myDpm)
} }
if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,R.string.sys_err_dialog,"",R.drawable.android_fill0,myComponent, myDpm)} if(VERSION.SDK_INT>=28){UserRestrictionItem(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,R.string.sys_err_dialog,"",R.drawable.android_fill0, myContext, myComponent, myDpm)}
UserRestrictionItem(UserManager.DISALLOW_FACTORY_RESET,R.string.factory_reset,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_FACTORY_RESET,R.string.factory_reset,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_SAFE_BOOT,R.string.safe_boot,"",R.drawable.android_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_SAFE_BOOT,R.string.safe_boot,"",R.drawable.android_fill0, myContext, myComponent, myDpm)
UserRestrictionItem(UserManager.DISALLOW_DEBUGGING_FEATURES,R.string.debug_features,"",R.drawable.adb_fill0,myComponent, myDpm) UserRestrictionItem(UserManager.DISALLOW_DEBUGGING_FEATURES,R.string.debug_features,"",R.drawable.adb_fill0, myContext, myComponent, myDpm)
} }
if(VERSION.SDK_INT<24){ if(VERSION.SDK_INT<24){
@@ -195,8 +200,14 @@ fun SectionTab(txt:String,getSection:()->Boolean,setSection:()->Unit){
} }
@Composable @Composable
private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDescription:String, leadIcon:Int,myComponent: ComponentName, myDpm: DevicePolicyManager){ private fun UserRestrictionItem(
val isdo = myDpm.isDeviceOwnerApp("com.binbin.androidowner") restriction:String, itemName:Int,
restrictionDescription:String,
leadIcon:Int,
myContext: Context,
myComponent: ComponentName,
myDpm: DevicePolicyManager
){
var strictState by remember{ mutableStateOf(false) } var strictState by remember{ mutableStateOf(false) }
Row( Row(
modifier = Modifier modifier = Modifier
@@ -228,7 +239,7 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
if(restrictionDescription!=""){Text(text = restrictionDescription, color = MaterialTheme.colorScheme.onSecondaryContainer)} if(restrictionDescription!=""){Text(text = restrictionDescription, color = MaterialTheme.colorScheme.onSecondaryContainer)}
} }
} }
if(isdo&&VERSION.SDK_INT>=24){ if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)|| isProfileOwner(myDpm))){
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction) strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
} }
if(VERSION.SDK_INT>=24){ if(VERSION.SDK_INT>=24){
@@ -236,14 +247,20 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
checked = strictState, checked = strictState,
onCheckedChange = { onCheckedChange = {
strictState=it strictState=it
try{
if(strictState){ if(strictState){
myDpm.addUserRestriction(myComponent,restriction) myDpm.addUserRestriction(myComponent,restriction)
}else{ }else{
myDpm.clearUserRestriction(myComponent,restriction) myDpm.clearUserRestriction(myComponent,restriction)
} }
}catch(e:SecurityException){
if(isProfileOwner(myDpm)){
Toast.makeText(myContext, "Profile owner 无法更改", Toast.LENGTH_SHORT).show()
}
}
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction) strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
}, },
enabled = isdo enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm)
) )
} }
} }

View File

@@ -1,23 +1,17 @@
# Project-wide Gradle settings. ## For more details on how to configure your build environment visit
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html # http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the #Sun Jan 21 20:24:56 CST 2024
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.useAndroidX=true
kotlin.code.style=official
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M" -Dfile.encoding\=UTF-8