mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Add a ManagedProfile page
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK_TASK"/>
|
||||
<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"/>
|
||||
<application
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
||||
@@ -76,7 +76,7 @@ fun ApplicationManage(){
|
||||
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT>=24&&isDeviceOwner(myDpm)){
|
||||
if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
||||
val isSuspended: Boolean = try{ myDpm.isPackageSuspended(myComponent,pkgName) }
|
||||
catch(e:NameNotFoundException){ false }
|
||||
catch(w:NameNotFoundException){ false }
|
||||
@@ -472,7 +472,6 @@ private fun AppManageItem(
|
||||
val myDpm = LocalContext.current.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var isEnabled by remember{ mutableStateOf(false) }
|
||||
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){ isEnabled = getMethod() }
|
||||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
if(!sharedPref.getBoolean("isWear",false)){
|
||||
Row(
|
||||
|
||||
@@ -492,7 +492,7 @@ fun DeviceControl(){
|
||||
Text(text = "清除数据",style = typography.titleLarge,modifier = Modifier.padding(6.dp),color = colorScheme.onErrorContainer)
|
||||
RadioButtonItem("默认",{flag==0},{flag=0}, colorScheme.onErrorContainer)
|
||||
RadioButtonItem("WIPE_EXTERNAL_STORAGE",{flag==WIPE_EXTERNAL_STORAGE},{flag=WIPE_EXTERNAL_STORAGE}, colorScheme.onErrorContainer)
|
||||
if(VERSION.SDK_INT>=22){
|
||||
if(VERSION.SDK_INT>=22&&isDeviceOwner(myDpm)){
|
||||
RadioButtonItem("WIPE_RESET_PROTECTION_DATA",{flag==WIPE_RESET_PROTECTION_DATA},{flag=WIPE_RESET_PROTECTION_DATA}, colorScheme.onErrorContainer)
|
||||
}
|
||||
if(VERSION.SDK_INT>=28){ RadioButtonItem("WIPE_EUICC",{flag==WIPE_EUICC},{flag=WIPE_EUICC}, colorScheme.onErrorContainer) }
|
||||
@@ -533,6 +533,9 @@ fun DeviceControl(){
|
||||
}
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
|
||||
Text("将会删除工作资料")
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -100,6 +101,7 @@ fun MyScaffold(){
|
||||
"HomePage" to R.string.app_name,
|
||||
"DeviceControl" to R.string.device_ctrl,
|
||||
"Network" to R.string.network,
|
||||
"ManagedProfile" to R.string.work_profile,
|
||||
"Permissions" to R.string.permission,
|
||||
"UserManage" to R.string.user_manage,
|
||||
"ApplicationManage" to R.string.app_manage,
|
||||
@@ -160,6 +162,7 @@ fun MyScaffold(){
|
||||
){
|
||||
composable(route = "HomePage", content = { HomePage(navCtrl)})
|
||||
composable(route = "DeviceControl", content = { DeviceControl()})
|
||||
composable(route = "ManagedProfile", content = {ManagedProfile(navCtrl)})
|
||||
composable(route = "Permissions", content = { DpmPermissions(navCtrl)})
|
||||
composable(route = "ApplicationManage", content = { ApplicationManage()})
|
||||
composable(route = "UserRestriction", content = { UserRestriction()})
|
||||
@@ -216,6 +219,7 @@ fun HomePage(navCtrl:NavHostController){
|
||||
}
|
||||
HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, "DeviceControl", navCtrl)
|
||||
if(VERSION.SDK_INT>=26){HomePageItem(R.string.network, R.drawable.wifi_fill0, "Network",navCtrl)}
|
||||
HomePageItem(R.string.work_profile, R.drawable.work_fill0, "ManagedProfile",navCtrl)
|
||||
HomePageItem(R.string.app_manage, R.drawable.apps_fill0, "ApplicationManage", navCtrl)
|
||||
HomePageItem(R.string.user_restrict, R.drawable.manage_accounts_fill0, "UserRestriction", navCtrl)
|
||||
HomePageItem(R.string.user_manage,R.drawable.account_circle_fill0,"UserManage",navCtrl)
|
||||
@@ -311,6 +315,7 @@ fun isProfileOwner(dpm:DevicePolicyManager): Boolean {
|
||||
|
||||
@SuppressLint("ModifierFactoryExtensionFunction", "ComposableModifierFactory")
|
||||
@Composable
|
||||
@Stable
|
||||
fun sections(bgColor:Color=MaterialTheme.colorScheme.primaryContainer):Modifier{
|
||||
val backgroundColor = if(isSystemInDarkTheme()){bgColor.copy(0.4F)}else{bgColor.copy(0.6F)}
|
||||
return if(!LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE).getBoolean("isWear",false)){
|
||||
|
||||
122
app/src/main/java/com/binbin/androidowner/ManagedProfile.kt
Normal file
122
app/src/main/java/com/binbin/androidowner/ManagedProfile.kt
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.binbin.androidowner
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
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.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
|
||||
@Composable
|
||||
fun ManagedProfile(navCtrl:NavHostController){
|
||||
val myContext = LocalContext.current
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
|
||||
val focusMgr = LocalFocusManager.current
|
||||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
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))){
|
||||
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)
|
||||
}else{
|
||||
intent.putExtra(DevicePolicyManager.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)}
|
||||
createManagedProfile.launch(intent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
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){
|
||||
Column(modifier = sections()){
|
||||
var time by remember{mutableStateOf("")}
|
||||
time = myDpm.getManagedProfileMaximumTimeOff(myComponent).toString()
|
||||
Text(text = "资料关闭时间", style = typography.titleLarge)
|
||||
Text(text = "工作资料处于关闭状态的时间达到该限制后会停用个人应用,0为无限制(单位:毫秒)", style = bodyTextStyle)
|
||||
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小时")
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setManagedProfileMaximumTimeOff(myComponent,time.toLong())
|
||||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
) {
|
||||
Text("应用")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ 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
|
||||
@@ -160,6 +161,7 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
if(!isda){
|
||||
Text(text = "使用此命令也会激活Device Admin", style = bodyTextStyle)
|
||||
}
|
||||
Text(text = "成为Device owner后将不能新建工作资料", style = bodyTextStyle)
|
||||
}
|
||||
}
|
||||
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)||myDpm.isAdminActive(myComponent)){
|
||||
@@ -175,8 +177,6 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
modifier = sections()
|
||||
) {
|
||||
Text(text = "设备信息", style = typography.titleLarge,color = titleColor)
|
||||
val orgDevice = myDpm.isOrganizationOwnedDeviceWithManagedProfile
|
||||
Text("由组织拥有的受管理资料设备:$orgDevice",style=bodyTextStyle)
|
||||
if(VERSION.SDK_INT>=34&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){
|
||||
val financed = myDpm.isDeviceFinanced
|
||||
Text("企业资产 : $financed",style=bodyTextStyle)
|
||||
@@ -186,9 +186,7 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
Text("设备策略管理器角色:${if(dpmRole==null){"null"}else{""}}",style=bodyTextStyle)
|
||||
if(dpmRole!=null){
|
||||
Row(modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState())){
|
||||
SelectionContainer {
|
||||
Text(dpmRole)
|
||||
}
|
||||
SelectionContainer { Text(dpmRole) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,6 +232,33 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((VERSION.SDK_INT>=26&&isDeviceOwner(myDpm))||(VERSION.SDK_INT>=24&&isProfileOwner(myDpm))){
|
||||
Column(modifier = sections()){
|
||||
var orgName by remember{
|
||||
mutableStateOf(
|
||||
if(myDpm.getOrganizationName(myComponent).toString()=="null"){ "" }else{ myDpm.getOrganizationName(myComponent).toString() }
|
||||
)
|
||||
}
|
||||
Text(text = "组织名称", style = typography.titleLarge)
|
||||
TextField(
|
||||
value = orgName, onValueChange = {orgName=it}, modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp),
|
||||
label = {Text("组织名称")},
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = {focusManager.clearFocus()})
|
||||
)
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setOrganizationName(myComponent,orgName)
|
||||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
){
|
||||
Text("应用")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isDeviceOwner(myDpm) || isProfileOwner(myDpm)){
|
||||
Column(modifier = sections()) {
|
||||
Text(text = "不受控制的账号类型", style = typography.titleLarge,color = titleColor)
|
||||
@@ -267,12 +292,16 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
keyboardActions = KeyboardActions(onDone = {focusManager.clearFocus()})
|
||||
)
|
||||
Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween){
|
||||
Button(onClick={focusManager.clearFocus()
|
||||
myDpm.setAccountManagementDisabled(myComponent,inputText,true)
|
||||
noManageAccount=myDpm.accountTypesWithManagementDisabled
|
||||
refreshList()
|
||||
},modifier = Modifier.fillMaxWidth(0.49f)){
|
||||
Text("列表")
|
||||
Button(
|
||||
onClick={
|
||||
focusManager.clearFocus()
|
||||
myDpm.setAccountManagementDisabled(myComponent,inputText,true)
|
||||
noManageAccount=myDpm.accountTypesWithManagementDisabled
|
||||
refreshList()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.49f)
|
||||
){
|
||||
Text("添加")
|
||||
}
|
||||
Button(
|
||||
onClick={focusManager.clearFocus()
|
||||
@@ -282,7 +311,7 @@ fun DpmPermissions(navCtrl:NavHostController){
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.96F)
|
||||
){
|
||||
Text("从列表中移除")
|
||||
Text("移除")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,7 +399,7 @@ fun DeviceOwnerInfo(
|
||||
fm.clearFocus()
|
||||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = if(isWear){Modifier.fillMaxWidth(0.48F)}else{Modifier.fillMaxWidth(0.6F)}
|
||||
modifier = if(isWear){Modifier.fillMaxWidth(0.49F)}else{Modifier.fillMaxWidth(0.6F)}
|
||||
) {
|
||||
Text(text = "应用")
|
||||
}
|
||||
@@ -381,7 +410,7 @@ fun DeviceOwnerInfo(
|
||||
fm.clearFocus()
|
||||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.95F)
|
||||
modifier = Modifier.fillMaxWidth(0.96F)
|
||||
) {
|
||||
Text(text = "重置")
|
||||
}
|
||||
|
||||
@@ -192,43 +192,6 @@ fun UserManage(navCtrl:NavHostController){
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = sections()) {
|
||||
Text(text = "工作资料", style = typography.titleLarge)
|
||||
if(VERSION.SDK_INT>=24){Text(text = "可以创建工作资料:${myDpm.isProvisioningAllowed(DevicePolicyManager.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(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE))){
|
||||
var skipEncrypt by remember{mutableStateOf(false)}
|
||||
if(VERSION.SDK_INT>=24){CheckBoxItem("跳过加密",{skipEncrypt},{skipEncrypt=!skipEncrypt})}
|
||||
Button(
|
||||
onClick = {
|
||||
val intent = Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE)
|
||||
if(VERSION.SDK_INT>=23){
|
||||
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,myComponent)
|
||||
}else{
|
||||
intent.putExtra(DevicePolicyManager.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)}
|
||||
createManagedProfile.launch(intent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("创建")
|
||||
}
|
||||
}
|
||||
if(isProfileOwner(myDpm)){
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setProfileEnabled(myComponent)
|
||||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = "启用")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(VERSION.SDK_INT>=24){
|
||||
Column(modifier = sections()) {
|
||||
var userName by remember{ mutableStateOf("") }
|
||||
|
||||
@@ -122,4 +122,5 @@
|
||||
<string name="network">网络</string>
|
||||
<string name="developing">功能开发中</string>
|
||||
<string name="wifi_lockdown">WiFi锁定</string>
|
||||
<string name="work_profile">工作资料</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user