massive work profile features

This commit is contained in:
BinTianqi
2024-02-09 17:05:45 +08:00
parent 0437ff11fa
commit d3e36e445b
8 changed files with 284 additions and 52 deletions

View File

@@ -58,7 +58,6 @@
### 即将加入的功能
- Managed Profile工作资料和多用户相关
- ~~应用管理:安装/卸载应用~~(暂不考虑)
- 应用管理:包选择器(目前只能手动输入包名)
- 应用管理:应用权限选择器

View File

@@ -3,7 +3,6 @@
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_KEYGUARD"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<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"/>
@@ -16,6 +15,7 @@
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIFI"/>
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS"/>
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY"/>
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION"/>
<application
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@@ -24,7 +24,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.AndroidOwner"
android:enableOnBackInvokedCallback="true"
android:allowNativeHeapPointerTagging="true"
tools:targetApi="34">
<activity
android:name=".MainActivity"
@@ -37,6 +36,7 @@
<action android:name="android.app.action.PROVISION_MANAGED_PROFILE"/>
<action android:name="android.app.action.MANAGED_PROFILE_PROVISIONED"/>
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
<action android:name="com.binbin.androidowner.MAIN_ACTION"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

View File

@@ -36,11 +36,13 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import java.util.concurrent.Executors
private var credentialList = mutableSetOf<String>()
private var crossProfilePkg = mutableSetOf<String>()
@Composable
fun ApplicationManage(){
val myContext = LocalContext.current
@@ -75,6 +77,9 @@ fun ApplicationManage(){
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
)
}
if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
Text(text = "作用域: 工作资料", style = bodyTextStyle, textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp))
}
if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
AppManageItem(
R.string.suspend,R.string.place_holder,
@@ -242,6 +247,82 @@ fun ApplicationManage(){
}
}
if(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
Column(modifier = sections()){
Text(text = "跨资料应用", style = typography.titleLarge)
var list by remember{mutableStateOf("")}
val refresh = {
crossProfilePkg = myDpm.getCrossProfilePackages(myComponent)
list = ""
var count = crossProfilePkg.size
for(each in crossProfilePkg){ count-=1; list+=each; if(count>0){list+="\n"} }
}
var inited by remember{mutableStateOf(false)}
if(!inited){refresh();inited=true}
Text(text = if(list!=""){list}else{""}, style = bodyTextStyle)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
Button(
onClick = {
if(pkgName!=""){crossProfilePkg.add(pkgName)}
myDpm.setCrossProfilePackages(myComponent, crossProfilePkg)
refresh()
},
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text("添加")
}
Button(
onClick = {
if(pkgName!=""){crossProfilePkg.remove(pkgName)}
myDpm.setCrossProfilePackages(myComponent, crossProfilePkg)
refresh()
},
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text("移除")
}
}
}
}
if(isProfileOwner(myDpm)){
Column(modifier = sections()){
var pkgList: MutableList<String>
var list by remember{mutableStateOf("")}
val refresh = {
pkgList = myDpm.getCrossProfileWidgetProviders(myComponent)
list = ""
var count = pkgList.size
for(each in pkgList){ count-=1; list+=each; if(count>0){list+="\n"}}
}
var inited by remember{mutableStateOf(false)}
if(!inited){refresh();inited=true}
Text(text = "跨资料微件", style = typography.titleLarge)
Text(text = "(跨资料桌面小部件提供者)", style = bodyTextStyle)
Text(text = if(list!=""){list}else{""}, style = bodyTextStyle)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
Button(
onClick = {
if(pkgName!=""){myDpm.addCrossProfileWidgetProvider(myComponent,pkgName)}
refresh()
},
modifier = Modifier.fillMaxWidth(0.49F)
){
Text("添加")
}
Button(
onClick = {
if(pkgName!=""){myDpm.removeCrossProfileWidgetProvider(myComponent,pkgName)}
refresh()
},
modifier = Modifier.fillMaxWidth(0.96F)
){
Text("移除")
}
}
}
}
if(VERSION.SDK_INT>=34&&isDeviceOwner(myDpm)){
var policy:PackagePolicy?
var policyType by remember{mutableIntStateOf(-1)}

View File

@@ -22,9 +22,7 @@ import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -97,6 +95,9 @@ fun MyScaffold(){
val focusMgr = LocalFocusManager.current
val navCtrl = rememberNavController()
val backStackEntry by navCtrl.currentBackStackEntryAsState()
val myContext = LocalContext.current
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
val topBarNameMap = mapOf(
"HomePage" to R.string.app_name,
"DeviceControl" to R.string.device_ctrl,
@@ -155,6 +156,9 @@ fun MyScaffold(){
}
}
) {
val profileInited = sharedPref.getBoolean("ManagedProfileActivated",false)
var inited by remember{mutableStateOf(false)}
val jumpToActivateProfile = !profileInited&&isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))
NavHost(
navController = navCtrl,
startDestination = "HomePage",
@@ -162,7 +166,7 @@ fun MyScaffold(){
){
composable(route = "HomePage", content = { HomePage(navCtrl)})
composable(route = "DeviceControl", content = { DeviceControl()})
composable(route = "ManagedProfile", content = {ManagedProfile(navCtrl)})
composable(route = "ManagedProfile", content = {ManagedProfile()})
composable(route = "Permissions", content = { DpmPermissions(navCtrl)})
composable(route = "ApplicationManage", content = { ApplicationManage()})
composable(route = "UserRestriction", content = { UserRestriction()})
@@ -170,7 +174,9 @@ fun MyScaffold(){
composable(route = "Password", content = { Password()})
composable(route = "AppSetting", content = { AppSetting(navCtrl)})
composable(route = "Network", content = {Network()})
composable(route = "ActivateManagedProfile", content = {ActivateManagedProfile(navCtrl)})
}
if(!inited&&jumpToActivateProfile){navCtrl.navigate("ActivateManagedProfile");inited=true}
}
}

View File

@@ -1,28 +1,30 @@
package com.binbin.androidowner
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE
import android.app.admin.DevicePolicyManager.*
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInstaller
import android.os.Build.VERSION
import android.os.Bundle
import android.os.Parcelable
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
@@ -32,7 +34,7 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
@Composable
fun ManagedProfile(navCtrl:NavHostController){
fun ManagedProfile() {
val myContext = LocalContext.current
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
@@ -41,37 +43,67 @@ fun ManagedProfile(navCtrl:NavHostController){
val isWear = sharedPref.getBoolean("isWear",false)
val bodyTextStyle = if(isWear){ typography.bodyMedium}else{ typography.bodyLarge}
Column(modifier = Modifier.verticalScroll(rememberScrollState())){
Column(modifier = sections()){
Text(text = "信息", style = typography.titleLarge)
if(VERSION.SDK_INT>=30){
Text(text = "由组织拥有的工作资料:${myDpm.isOrganizationOwnedDeviceWithManagedProfile}", style = bodyTextStyle)
}
}
Column(modifier = sections()) {
Text(text = "工作资料", style = typography.titleLarge)
if(VERSION.SDK_INT>=24){
if(isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
Text(text = "已是工作资料")
}else{
Text(text = "可以创建工作资料:${myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)}", style = bodyTextStyle)
}
}
if(isDeviceOwner(myDpm)){
Text(text = "Device owner不能创建工作资料", style = bodyTextStyle)
}
if(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE))){
}
}
if(VERSION.SDK_INT>=30){
Text(text = "由组织拥有的工作资料:${myDpm.isOrganizationOwnedDeviceWithManagedProfile}", style = bodyTextStyle)
}
if(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent))){
Button(
onClick = { myContext.startActivity(Intent("com.binbin.androidowner.MAIN_ACTION")) }, modifier = Modifier.fillMaxWidth()
){
Text("跳转至个人应用")
}
}else{
if(!myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)){
Button(
onClick = { myContext.startActivity(Intent("com.binbin.androidowner.MAIN_ACTION")) }, modifier = Modifier.fillMaxWidth()
){
Text("跳转至工作资料")
}
}
}
}
if(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)&&!myDpm.isOrganizationOwnedDeviceWithManagedProfile){
Column(modifier = sections(colorScheme.tertiaryContainer)){
Text("成为组织拥有的工作资料")
Text(text = "首先在“用户管理”中查看UserID然后使用ADB执行下面这条命令", style = bodyTextStyle)
SelectionContainer {
Text(
text = "adb shell “dpm mark-profile-owner-on-organization-owned-device --user USER_ID com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver”",
color = colorScheme.onTertiaryContainer, style = bodyTextStyle
)
}
Text(text = "把上面命令中的USER_ID替换成你的UserID", style = bodyTextStyle)
}
}
if(!isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)))){
Column(modifier = sections()) {
Text(text = "工作资料", style = typography.titleLarge)
var skipEncrypt by remember{mutableStateOf(false)}
if(VERSION.SDK_INT>=24){CheckBoxItem("跳过加密",{skipEncrypt},{skipEncrypt=!skipEncrypt})}
Button(
onClick = {
val intent = Intent(ACTION_PROVISION_MANAGED_PROFILE)
if(VERSION.SDK_INT>=23){
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,myComponent)
intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,myComponent)
}else{
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,"com.binbin.androidowner")
intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,"com.binbin.androidowner")
}
if(VERSION.SDK_INT>=24){intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION,skipEncrypt)}
if(VERSION.SDK_INT>=33){intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_ALLOW_OFFLINE,true)}
if(VERSION.SDK_INT>=24){intent.putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION,skipEncrypt)}
if(VERSION.SDK_INT>=33){intent.putExtra(EXTRA_PROVISIONING_ALLOW_OFFLINE,true)}
createManagedProfile.launch(intent)
},
modifier = Modifier.fillMaxWidth()
@@ -79,17 +111,20 @@ fun ManagedProfile(navCtrl:NavHostController){
Text("创建")
}
}
if(isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))){
Button(
onClick = {
myDpm.setProfileEnabled(myComponent)
navCtrl.navigateUp()
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
) {
Text(text = "激活")
}
if(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile){
Row(modifier = sections(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically){
var suspended by remember{mutableStateOf(false)}
suspended = myDpm.getPersonalAppsSuspendedReasons(myComponent)!=PERSONAL_APPS_NOT_SUSPENDED
Text(text = "挂起个人应用", style = typography.titleLarge)
Switch(
checked = suspended,
onCheckedChange ={
myDpm.setPersonalAppsSuspended(myComponent,!suspended)
suspended = myDpm.getPersonalAppsSuspendedReasons(myComponent)!=PERSONAL_APPS_NOT_SUSPENDED
}
)
}
}
@@ -98,25 +133,135 @@ fun ManagedProfile(navCtrl:NavHostController){
var time by remember{mutableStateOf("")}
time = myDpm.getManagedProfileMaximumTimeOff(myComponent).toString()
Text(text = "资料关闭时间", style = typography.titleLarge)
Text(text = "工作资料处于关闭状态的时间达到该限制后会停用个人应用0为无限制(单位:毫秒)", style = bodyTextStyle)
Text(text = "工作资料处于关闭状态的时间达到该限制后会挂起个人应用0为无限制", style = bodyTextStyle)
Text(text = "个人应用已经因此挂起:${myDpm.getPersonalAppsSuspendedReasons(myComponent)==PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT}")
TextField(
value = time, onValueChange = {time=it}, modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
label = {Text("时间(ms)")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
)
Text(text = "不能少于72小时")
Text(text = "不能少于72小时", style = bodyTextStyle)
Button(
onClick = {
myDpm.setManagedProfileMaximumTimeOff(myComponent,time.toLong())
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("应用")
}
}
}
if(isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))){
Column(modifier = sections()){
var action by remember{mutableStateOf("")}
Text(text = "Intent过滤器", style = typography.titleLarge)
TextField(
value = action, onValueChange = {action = it},
label = {Text("Action")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
)
Button(
onClick = {
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter(action), FLAG_PARENT_CAN_ACCESS_MANAGED)
Toast.makeText(myContext,"成功",Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
) {
Text("添加(工作到个人)")
}
Button(
onClick = {
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter(action), FLAG_MANAGED_CAN_ACCESS_PARENT)
Toast.makeText(myContext,"成功",Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
) {
Text("添加(个人到工作)")
}
Button(
onClick = {
myDpm.clearCrossProfileIntentFilters(myComponent)
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter("com.binbin.androidowner.MAIN_ACTION"), FLAG_MANAGED_CAN_ACCESS_PARENT)
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter("com.binbin.androidowner.MAIN_ACTION"), FLAG_PARENT_CAN_ACCESS_MANAGED)
Toast.makeText(myContext,"成功",Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
){
Text("清除所有过滤器")
}
}
}
if(VERSION.SDK_INT>=31&&(isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent))){
Column(modifier = sections()){
var orgId by remember{mutableStateOf("")}
Text(text = "组织ID", style = typography.titleLarge)
TextField(
value = orgId, onValueChange = {orgId=it},
label = {Text("组织ID")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
)
AnimatedVisibility(orgId.length !in 6..64) {
Text(text = "长度应在6~64个字符之间", style = bodyTextStyle)
}
Button(
onClick = {
myDpm.setOrganizationId(orgId)
Toast.makeText(myContext,"成功",Toast.LENGTH_SHORT).show()
},
enabled = orgId.length in 6..64,
modifier = Modifier.fillMaxWidth()
){
Text("应用")
}
Text(text = "设置组织ID后才能获取设备唯一标识码", style = bodyTextStyle)
}
}
if(isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))){
Column(modifier = sections(colorScheme.tertiaryContainer)){
Text(text = "提示", style = typography.titleLarge)
SelectionContainer {
Text(
text = "安装应用的Action是android.intent.action.INSTALL_PACKAGE需配合android.intent.action.VIEW使用",
style = bodyTextStyle, color = colorScheme.onTertiaryContainer
)
}
}
}
Spacer(Modifier.padding(vertical = 30.dp))
}
}
@Composable
fun ActivateManagedProfile(navCtrl: NavHostController){
val myContext = LocalContext.current
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
val sharedPref = myContext.getSharedPreferences("data", Context.MODE_PRIVATE)
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter("com.binbin.androidowner.MAIN_ACTION"), FLAG_MANAGED_CAN_ACCESS_PARENT)
myDpm.addCrossProfileIntentFilter(myComponent, IntentFilter("com.binbin.androidowner.MAIN_ACTION"), FLAG_PARENT_CAN_ACCESS_MANAGED)
Column(modifier = Modifier.verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally){
Text(text = "激活工作资料", style = typography.titleLarge)
Text(text = "你还没有激活工作资料,请立即激活")
Button(
onClick = {
myDpm.setProfileEnabled(myComponent)
navCtrl.popBackStack("HomePage",false)
sharedPref.edit().putBoolean("ManagedProfileActivated",true).apply()
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth().padding(8.dp)
) {
Text("激活")
}
}
}

View File

@@ -99,7 +99,7 @@ fun Password(){
}else{ Toast.makeText(myContext, "清除失败", Toast.LENGTH_SHORT).show() }
},
modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.32F)},
enabled = isDeviceOwner(myDpm)
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm)
) {
Text("清除")
}
@@ -116,7 +116,7 @@ fun Password(){
Toast.makeText(myContext, "失败(安全异常)", Toast.LENGTH_SHORT).show()
}
},
enabled = isDeviceOwner(myDpm),
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm),
modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.47F)}
) {
Text("设置")
@@ -129,7 +129,7 @@ fun Password(){
}catch(e:NullPointerException){ Toast.makeText(myContext, "请先设置令牌", Toast.LENGTH_SHORT).show() }
}else{ Toast.makeText(myContext, "已经激活", Toast.LENGTH_SHORT).show() }
},
enabled = isDeviceOwner(myDpm),
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm),
modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.88F)}
) {
Text("激活")

View File

@@ -28,7 +28,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat.startActivity
@@ -223,12 +222,9 @@ fun DpmPermissions(navCtrl:NavHostController){
Text(text = "设备唯一标识码", style = typography.titleLarge,color = titleColor)
Text("(恢复出厂设置不变)",style=bodyTextStyle)
if(specificId!=""){
Text(specificId)
Button(onClick = {myDpm.setOrganizationId(specificId)}) {
Text("设置为组织ID")
}
SelectionContainer{ Text(specificId, style = bodyTextStyle) }
}else{
Text("你的设备不支持",style=bodyTextStyle)
Text("需要设置组织ID",style=bodyTextStyle)
}
}
}
@@ -249,6 +245,7 @@ fun DpmPermissions(navCtrl:NavHostController){
)
Button(
onClick = {
focusManager.clearFocus()
myDpm.setOrganizationName(myComponent,orgName)
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
},

View File

@@ -43,6 +43,7 @@ private data class Restriction(
fun UserRestriction(){
val myContext = LocalContext.current
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
var internetVisible by remember{ mutableStateOf(false) }
var connectivityVisible by remember{ mutableStateOf(false) }
var applicationVisible by remember{ mutableStateOf(false) }
@@ -53,13 +54,16 @@ fun UserRestriction(){
val isWear = sharedPref.getBoolean("isWear",false)
val bodyTextStyle = if(isWear){typography.bodyMedium}else{typography.bodyLarge}
Column(modifier = Modifier.verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally){
Text(text = "打开开关后会禁用对应的功能",modifier = Modifier.padding(3.dp), style = bodyTextStyle)
Text(text = "打开开关后会禁用对应的功能",style = bodyTextStyle)
if(VERSION.SDK_INT<24){
Text(text = "所有的用户限制都需要API24你的设备低于API24无法使用。", style = bodyTextStyle, color = colorScheme.error)
}
if(isProfileOwner(myDpm)){
Text(text = "Profile owner无法使用部分功能", style = bodyTextStyle)
}
if(isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))){
Text(text = "工作资料中部分功能无效", style = bodyTextStyle)
}
if(isWear){
Text(text = "部分功能在手表上无效", style = typography.bodyMedium)
}