mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
429 lines
20 KiB
Kotlin
429 lines
20 KiB
Kotlin
package com.binbin.androidowner
|
||
|
||
import android.app.admin.DevicePolicyManager
|
||
import android.content.ComponentName
|
||
import android.content.Context
|
||
import android.content.Intent
|
||
import android.os.Build.VERSION
|
||
import android.widget.Toast
|
||
import androidx.activity.ComponentActivity
|
||
import androidx.compose.foundation.layout.Arrangement
|
||
import androidx.compose.foundation.layout.Column
|
||
import androidx.compose.foundation.layout.Row
|
||
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.text.selection.SelectionContainer
|
||
import androidx.compose.foundation.verticalScroll
|
||
import androidx.compose.material3.Button
|
||
import androidx.compose.material3.ButtonDefaults
|
||
import androidx.compose.material3.MaterialTheme
|
||
import androidx.compose.material3.MaterialTheme.typography
|
||
import androidx.compose.material3.Text
|
||
import androidx.compose.material3.TextField
|
||
import androidx.compose.runtime.Composable
|
||
import androidx.compose.runtime.getValue
|
||
import androidx.compose.runtime.mutableStateOf
|
||
import androidx.compose.runtime.remember
|
||
import androidx.compose.runtime.setValue
|
||
import androidx.compose.ui.Alignment
|
||
import androidx.compose.ui.Modifier
|
||
import androidx.compose.ui.focus.FocusManager
|
||
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.unit.dp
|
||
import androidx.compose.ui.unit.sp
|
||
import androidx.core.content.ContextCompat.startActivity
|
||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||
import androidx.navigation.NavHostController
|
||
|
||
|
||
@Composable
|
||
fun DpmPermissions(navCtrl:NavHostController){
|
||
val myContext = LocalContext.current
|
||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
|
||
val isda = myDpm.isAdminActive(myComponent)
|
||
val focusManager = LocalFocusManager.current
|
||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||
val isWear = sharedPref.getBoolean("isWear",false)
|
||
val titleColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||
val bodyTextStyle = if(isWear){typography.bodyMedium}else{typography.bodyLarge}
|
||
Column(
|
||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||
horizontalAlignment = Alignment.CenterHorizontally
|
||
) {
|
||
if(!myDpm.isAdminActive(myComponent)&&isWear){
|
||
Button(onClick = { activateDeviceAdmin(myContext,myComponent) },modifier = Modifier.padding(horizontal = 3.dp).fillMaxWidth()) {
|
||
Text("激活Device admin")
|
||
}
|
||
}
|
||
Row(
|
||
modifier = sections(),
|
||
horizontalArrangement = Arrangement.SpaceBetween,
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Column {
|
||
Text(text = "Device Admin", fontSize = if(!isWear){22.sp}else{20.sp},color = titleColor)
|
||
Text(text = if(isda){"已激活"}else{"未激活"})
|
||
}
|
||
if(!isWear)
|
||
if(isda){
|
||
Button(
|
||
onClick = {
|
||
myDpm.removeActiveAdmin(myComponent)
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
}
|
||
) {
|
||
Text("撤销")
|
||
}
|
||
}else{
|
||
Button(onClick = { activateDeviceAdmin(myContext,myComponent) }) {
|
||
Text("激活")
|
||
}
|
||
}
|
||
}
|
||
if(!isda){
|
||
Column(
|
||
modifier = sections(MaterialTheme.colorScheme.tertiaryContainer.copy(alpha = 0.8F)),
|
||
horizontalAlignment = Alignment.Start
|
||
) {
|
||
SelectionContainer {
|
||
Text("adb shell dpm set-active-admin com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver",
|
||
color = MaterialTheme.colorScheme.onTertiaryContainer, style = bodyTextStyle)
|
||
}
|
||
Text(text = "或者进入设置(原生安卓) -> 安全 -> 更多安全设置 -> 设备管理应用 -> Android Owner", style = bodyTextStyle)
|
||
}
|
||
}
|
||
Row(
|
||
modifier = sections(),
|
||
horizontalArrangement = Arrangement.SpaceBetween,
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Column {
|
||
Text(text = "Profile Owner", fontSize = if(!isWear){22.sp}else{20.sp},color = titleColor)
|
||
Text(if(isProfileOwner(myDpm)){"已激活"}else{"未激活"})
|
||
}
|
||
if(isProfileOwner(myDpm)&&VERSION.SDK_INT>=24&&!isWear){
|
||
Button(
|
||
onClick = {
|
||
myDpm.clearProfileOwner(myComponent)
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
}
|
||
) {
|
||
Text("撤销")
|
||
}
|
||
}
|
||
}
|
||
if(!isProfileOwner(myDpm)){
|
||
Column(
|
||
modifier = sections(MaterialTheme.colorScheme.tertiaryContainer.copy(alpha = 0.8F)),
|
||
horizontalAlignment = Alignment.Start
|
||
) {
|
||
if(!isDeviceOwner(myDpm)){
|
||
SelectionContainer {
|
||
Text("adb shell dpm set-profile-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver",
|
||
color = MaterialTheme.colorScheme.onTertiaryContainer, style = bodyTextStyle)
|
||
}
|
||
Text(text = "Device owner和Profile owner不能同时存在,强烈建议激活Device owner", style = bodyTextStyle)
|
||
}
|
||
if(isDeviceOwner(myDpm)){
|
||
Text(text = "Device owner创建其他用户后,这个应用会成为新用户的Profile owner", style = bodyTextStyle)
|
||
}
|
||
}
|
||
}
|
||
Row(
|
||
modifier = sections(),
|
||
horizontalArrangement = Arrangement.SpaceBetween,
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Column {
|
||
Text(text = "Device Owner", fontSize = if(!isWear){22.sp}else{20.sp},color = titleColor)
|
||
Text(if(isDeviceOwner(myDpm)){"已激活"}else{"未激活"})
|
||
}
|
||
if(isDeviceOwner(myDpm)&&!isWear){
|
||
Button(
|
||
onClick = {
|
||
myDpm.clearDeviceOwnerApp("com.binbin.androidowner")
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
}
|
||
) {
|
||
Text("撤销")
|
||
}
|
||
}
|
||
}
|
||
if(!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)){
|
||
Column(
|
||
modifier = sections(MaterialTheme.colorScheme.tertiaryContainer.copy(alpha = 0.8F)),
|
||
horizontalAlignment = Alignment.Start
|
||
) {
|
||
SelectionContainer {
|
||
Text(text = "adb shell dpm set-device-owner com.binbin.androidowner/com.binbin.androidowner.MyDeviceAdminReceiver",
|
||
color = MaterialTheme.colorScheme.onTertiaryContainer, style = bodyTextStyle)
|
||
}
|
||
if(!isda){
|
||
Text(text = "使用此命令也会激活Device Admin", style = bodyTextStyle)
|
||
}
|
||
}
|
||
}
|
||
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)||myDpm.isAdminActive(myComponent)){
|
||
Text(
|
||
text = "注意!在这里撤销权限不会清除配置。比如:被停用的应用会保持停用状态",
|
||
color = MaterialTheme.colorScheme.onErrorContainer,
|
||
modifier = sections(MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.8F)),
|
||
style = bodyTextStyle
|
||
)
|
||
}
|
||
if(VERSION.SDK_INT>=30){
|
||
Column(
|
||
modifier = sections()
|
||
) {
|
||
Text(text = "设备信息", style = typography.titleLarge,color = titleColor)
|
||
val orgDevice = myDpm.isOrganizationOwnedDeviceWithManagedProfile
|
||
Text("由组织拥有的受管理资料设备:$orgDevice",style=bodyTextStyle)
|
||
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){
|
||
Text("Managed profile: ${myDpm.isManagedProfile(myComponent)}",style=bodyTextStyle)
|
||
}
|
||
if(VERSION.SDK_INT>=34&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){
|
||
val financed = myDpm.isDeviceFinanced
|
||
Text("企业资产 : $financed",style=bodyTextStyle)
|
||
}
|
||
if(VERSION.SDK_INT>=33){
|
||
Text("最小WiFi安全等级:${myDpm.minimumRequiredWifiSecurityLevel}",style=bodyTextStyle)
|
||
Text("设备策略管理器角色:${myDpm.devicePolicyManagementRoleHolderPackage}",style=bodyTextStyle)
|
||
}
|
||
val encryptionStatus = mapOf(
|
||
DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE to "未使用",
|
||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE to "正在使用",
|
||
DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED to "不支持",
|
||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY to "使用默认密钥",
|
||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER to "每个用户分别加密",
|
||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING to "未知"
|
||
)
|
||
Text("加密状态:${encryptionStatus[myDpm.storageEncryptionStatus]}",style=bodyTextStyle)
|
||
if(isDeviceOwner(myDpm)&&VERSION.SDK_INT>=34){
|
||
Text("MTE策略:${myDpm.mtePolicy}",style=bodyTextStyle)
|
||
}
|
||
}
|
||
}
|
||
if(VERSION.SDK_INT>=31&&(isProfileOwner(myDpm)|| isDeviceOwner(myDpm))){
|
||
Column(modifier = sections()) {
|
||
val specificId:String = myDpm.enrollmentSpecificId
|
||
Text(text = "设备唯一标识码", style = typography.titleLarge,color = titleColor)
|
||
Text("(恢复出厂设置不变)",style=bodyTextStyle)
|
||
if(specificId!=""){
|
||
Text(specificId)
|
||
Button(onClick = {myDpm.setOrganizationId(specificId)}) {
|
||
Text("设置为组织ID")
|
||
}
|
||
}else{
|
||
Text("你的设备不支持",style=bodyTextStyle)
|
||
}
|
||
}
|
||
}
|
||
if(isDeviceOwner(myDpm) || isProfileOwner(myDpm)){
|
||
Column(modifier = sections()) {
|
||
Text(text = "不受控制的账号类型", style = typography.titleLarge,color = titleColor)
|
||
Text("作用未知",style=bodyTextStyle)
|
||
var noManageAccount = myDpm.accountTypesWithManagementDisabled?.toMutableList()
|
||
var accountlist by remember{ mutableStateOf("") }
|
||
val refreshList = {
|
||
accountlist = ""
|
||
if (noManageAccount != null) {
|
||
for(eachAccount in noManageAccount!!){
|
||
accountlist+="$eachAccount \n"
|
||
}
|
||
}
|
||
}
|
||
refreshList()
|
||
if(accountlist!=""){
|
||
Text(accountlist)
|
||
}else{
|
||
Text("列表为空 \n",style=bodyTextStyle)
|
||
}
|
||
var inputText by remember{ mutableStateOf("") }
|
||
TextField(
|
||
value = inputText,
|
||
onValueChange = {inputText=it},
|
||
label = {Text("账号类型")},
|
||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp),
|
||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||
keyboardActions = KeyboardActions(onDone = {focusManager.clearFocus()})
|
||
)
|
||
if(isWear){
|
||
Button(onClick={focusManager.clearFocus()
|
||
myDpm.setAccountManagementDisabled(myComponent,inputText,true)
|
||
noManageAccount=myDpm.accountTypesWithManagementDisabled?.toMutableList()
|
||
refreshList()
|
||
},modifier = Modifier.fillMaxWidth()){
|
||
Text("添加至列表")
|
||
}
|
||
Button(onClick={focusManager.clearFocus()
|
||
myDpm.setAccountManagementDisabled(myComponent,inputText,false)
|
||
noManageAccount=myDpm.accountTypesWithManagementDisabled?.toMutableList()
|
||
refreshList()
|
||
},modifier = Modifier.fillMaxWidth()){
|
||
Text("从列表中移除")
|
||
}}else{
|
||
Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween){
|
||
Button(onClick={focusManager.clearFocus()
|
||
myDpm.setAccountManagementDisabled(myComponent,inputText,true)
|
||
noManageAccount=myDpm.accountTypesWithManagementDisabled?.toMutableList()
|
||
refreshList()
|
||
},modifier = Modifier.fillMaxWidth(0.48f)){
|
||
Text("添加至列表")
|
||
}
|
||
Button(onClick={focusManager.clearFocus()
|
||
myDpm.setAccountManagementDisabled(myComponent,inputText,false)
|
||
noManageAccount=myDpm.accountTypesWithManagementDisabled?.toMutableList()
|
||
refreshList()
|
||
},modifier = Modifier.fillMaxWidth(0.92F)){
|
||
Text("从列表中移除")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(isDeviceOwner(myDpm)&&VERSION.SDK_INT>=24){
|
||
DeviceOwnerInfo(R.string.owner_lockscr_info,R.string.place_holder,R.string.owner_lockscr_info,focusManager,myContext,
|
||
{myDpm.deviceOwnerLockScreenInfo},{content -> myDpm.setDeviceOwnerLockScreenInfo(myComponent,content)})
|
||
DeviceOwnerInfo(R.string.support_msg,R.string.support_msg_desc,R.string.message,focusManager,myContext,
|
||
{myDpm.getShortSupportMessage(myComponent)},{content -> myDpm.setShortSupportMessage(myComponent,content)})
|
||
DeviceOwnerInfo(R.string.long_support_msg,R.string.long_support_msg_desc,R.string.message,focusManager,myContext,
|
||
{myDpm.getLongSupportMessage(myComponent)},{content -> myDpm.setLongSupportMessage(myComponent,content)})
|
||
}
|
||
if(isWear&&(myDpm.isAdminActive(myComponent)||isProfileOwner(myDpm)||isDeviceOwner(myDpm))){
|
||
Column(modifier = sections(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||
Button(
|
||
onClick = {
|
||
myDpm.removeActiveAdmin(myComponent)
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
},
|
||
colors = ButtonDefaults.buttonColors(contentColor = MaterialTheme.colorScheme.onError, containerColor = MaterialTheme.colorScheme.error),
|
||
enabled = myDpm.isAdminActive(myComponent)
|
||
) {
|
||
Text("撤销Device admin")
|
||
}
|
||
if(VERSION.SDK_INT>=24){
|
||
Button(
|
||
onClick = {
|
||
myDpm.clearProfileOwner(myComponent)
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
},
|
||
colors = ButtonDefaults.buttonColors(contentColor = MaterialTheme.colorScheme.onError, containerColor = MaterialTheme.colorScheme.error),
|
||
enabled = isProfileOwner(myDpm)
|
||
) {
|
||
Text("撤销Profile owner")
|
||
}
|
||
}
|
||
Button(
|
||
onClick = {
|
||
myDpm.clearDeviceOwnerApp("com.binbin.androidowner")
|
||
navCtrl.navigate("HomePage") {
|
||
popUpTo(
|
||
navCtrl.graph.findStartDestination().id
|
||
) { saveState = true }
|
||
}
|
||
},
|
||
colors = ButtonDefaults.buttonColors(contentColor = MaterialTheme.colorScheme.onError, containerColor = MaterialTheme.colorScheme.error),
|
||
enabled = isDeviceOwner(myDpm)
|
||
) {
|
||
Text("撤销Device owner")
|
||
}
|
||
}
|
||
}
|
||
Spacer(Modifier.padding(vertical = 30.dp))
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun DeviceOwnerInfo(
|
||
name:Int,
|
||
desc:Int,
|
||
textfield:Int,
|
||
fm:FocusManager,
|
||
myContext:Context,
|
||
input:()->CharSequence?,
|
||
output:(content:String?)->Unit
|
||
){
|
||
Column(modifier = sections()) {
|
||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||
val isWear = sharedPref.getBoolean("isWear",false)
|
||
Text(text = stringResource(name), style = typography.titleLarge, softWrap = false, color = MaterialTheme.colorScheme.onPrimaryContainer)
|
||
if(desc!=R.string.place_holder){
|
||
Text(
|
||
text = stringResource(desc),modifier = Modifier.padding(top = 6.dp),
|
||
style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium})
|
||
}
|
||
var inputContent by remember{ mutableStateOf(input()) }
|
||
TextField(
|
||
value = if(inputContent!=null){ inputContent.toString() }else{""},
|
||
label = {Text(stringResource(textfield))},
|
||
onValueChange = { inputContent=it },
|
||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
||
)
|
||
Row(
|
||
modifier = Modifier.padding(vertical = if(isWear){2.dp}else{6.dp}),
|
||
horizontalArrangement = Arrangement.SpaceBetween
|
||
) {
|
||
Button(
|
||
onClick = {
|
||
output(inputContent.toString())
|
||
inputContent= input()
|
||
fm.clearFocus()
|
||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||
},
|
||
modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.6F)}
|
||
) {
|
||
Text(text = "应用")
|
||
}
|
||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||
Button(
|
||
onClick = {
|
||
output(null)
|
||
inputContent = input()
|
||
fm.clearFocus()
|
||
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
||
},
|
||
modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.95F)}
|
||
) {
|
||
Text(text = "重置")
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
fun activateDeviceAdmin(inputContext:Context,inputComponent:ComponentName){
|
||
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
|
||
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, inputComponent)
|
||
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "在这里激活Android Owner")
|
||
startActivity(inputContext,intent,null)
|
||
}
|