diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 51c06d9..2a62567 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -11,8 +11,8 @@ android {
applicationId = "com.binbin.androidowner"
minSdk = 23
targetSdk = 34
- versionCode = 3
- versionName = "1.2"
+ versionCode = 4
+ versionName = "1.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt b/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt
index 87831f4..58c26a6 100644
--- a/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt
+++ b/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt
@@ -49,7 +49,8 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
onValueChange = {
pkgName = it
},
- label = { Text("包名") }
+ label = { Text("包名") },
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)
)
if(VERSION.SDK_INT>=24){
val isSuspended = {
diff --git a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
index bacd21c..9c167ed 100644
--- a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
+++ b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
@@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -40,6 +41,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(bottom = 20.dp)
+ .navigationBarsPadding()
) {
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_scrcap,R.string.aosp_scrrec_also_work,R.drawable.screenshot_fill0,myDpm,{myDpm.getScreenCaptureDisabled(null)},{b -> myDpm.setScreenCaptureDisabled(myComponent,b) })
@@ -54,6 +56,13 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
if(VERSION.SDK_INT>=26){
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,R.drawable.backup_fill0,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
}
+ if(VERSION.SDK_INT>=31){
+ if(myDpm.canUsbDataSignalingBeDisabled()){
+ DeviceCtrlItem(R.string.usb_signal,R.string.place_holder,R.drawable.usb_fill0,myDpm,{myDpm.isUsbDataSignalingEnabled},{b -> myDpm.isUsbDataSignalingEnabled = b })
+ }else{
+ Text("你的设备不支持关闭USB信号")
+ }
+ }
if(VERSION.SDK_INT>=24){
Button(onClick = {myDpm.reboot(myComponent)}) {
Text("重启")
@@ -74,6 +83,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
if(VERSION.SDK_INT<30){
Text("自动设置时间和自动设置时区需要API30")
}
+ if(VERSION.SDK_INT<31){Text("关闭USB信号需API31")}
if(VERSION.SDK_INT<34){
Text("隐藏状态栏需要API34")
}
diff --git a/app/src/main/java/com/binbin/androidowner/MainActivity.kt b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
index 1477cc9..571da91 100644
--- a/app/src/main/java/com/binbin/androidowner/MainActivity.kt
+++ b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
@@ -13,6 +13,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
@@ -120,6 +121,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
startDestination = "HomePage",
modifier = Modifier
.padding(top = it.calculateTopPadding())
+ .imePadding()
){
composable(route = "HomePage", content = { HomePage(navCtrl,mainDpm,mainComponent)})
composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)})
diff --git a/app/src/main/java/com/binbin/androidowner/Password.kt b/app/src/main/java/com/binbin/androidowner/Password.kt
index c169bae..d43c0b7 100644
--- a/app/src/main/java/com/binbin/androidowner/Password.kt
+++ b/app/src/main/java/com/binbin/androidowner/Password.kt
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -54,6 +55,7 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
+ .navigationBarsPadding()
) {
val myByteArray by remember{ mutableStateOf(byteArrayOf(1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0)) }
Text(
@@ -66,6 +68,27 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
.background(color = MaterialTheme.colorScheme.errorContainer)
.padding(8.dp)
)
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 8.dp, vertical = 4.dp)
+ .clip(RoundedCornerShape(15))
+ .background(color = MaterialTheme.colorScheme.primaryContainer)
+ .padding(8.dp)
+ ) {
+ if(myDpm.isDeviceOwnerApp("com.binbin.androidowner")){
+ if(VERSION.SDK_INT>=29){
+ val pwdComplex = myDpm.passwordComplexity
+ Text(text = "密码复杂度:$pwdComplex")
+ }
+ val pwdFailedAttempts = myDpm.currentFailedPasswordAttempts
+ Text(text = "密码已错误次数:$pwdFailedAttempts")
+ if(VERSION.SDK_INT>=28&&(myDpm.isManagedProfile(myComponent)||myDpm.isProfileOwnerApp("com.binbin.androidowner"))){
+ val unifiedPwd = myDpm.isUsingUnifiedPassword(myComponent)
+ Text("个人与工作应用密码一致:$unifiedPwd")
+ }
+ }
+ }
if(VERSION.SDK_INT>=26){
Column(
horizontalAlignment = Alignment.Start,
@@ -168,7 +191,7 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
PasswordItem(R.string.max_pwd_fail,R.string.max_pwd_fail_desc,R.string.max_pwd_fail_textfield, focusMgr,false,
{myDpm.getMaximumFailedPasswordsForWipe(null).toString()},{ic -> myDpm.setMaximumFailedPasswordsForWipe(myComponent, ic.toInt()) })
PasswordItem(R.string.pwd_timeout,R.string.pwd_timeout_desc,R.string.pwd_timeout_textfield, focusMgr,true,
- {myDpm.getPasswordExpirationTimeout(null).toString()},{ic -> myDpm.setPasswordExpirationTimeout(myComponent, ic.toLong()) })
+ {myDpm.getPasswordExpiration(null).toString()},{ic -> myDpm.setPasswordExpirationTimeout(myComponent, ic.toLong()) })
PasswordItem(R.string.pwd_history,R.string.pwd_history_desc,R.string.pwd_history_textfield, focusMgr,true,
{myDpm.getPasswordHistoryLength(null).toString()},{ic -> myDpm.setPasswordHistoryLength(myComponent, ic.toInt()) })
diff --git a/app/src/main/java/com/binbin/androidowner/Permissions.kt b/app/src/main/java/com/binbin/androidowner/Permissions.kt
index 3800115..d9a61be 100644
--- a/app/src/main/java/com/binbin/androidowner/Permissions.kt
+++ b/app/src/main/java/com/binbin/androidowner/Permissions.kt
@@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION
+import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -29,20 +30,21 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
-
@Composable
fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myContext:Context,navCtrl:NavHostController){
//da:DeviceAdmin do:DeviceOwner
val isda = myDpm.isAdminActive(myComponent)
val isdo = myDpm.isDeviceOwnerApp("com.binbin.androidowner")
+ val focusManager = LocalFocusManager.current
Column(
modifier = Modifier
- .padding(8.dp)
+ .padding(horizontal = 8.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -111,7 +113,17 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
Column(
horizontalAlignment = Alignment.Start
) {
- if(isdo||isda){Text("注意!在这里撤销权限不会清除配置。比如:被停用的应用会保持停用状态")}
+ if(isdo||isda){
+ Text(
+ text = "注意!在这里撤销权限不会清除配置。比如:被停用的应用会保持停用状态",
+ color = MaterialTheme.colorScheme.onErrorContainer,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(15))
+ .background(color = MaterialTheme.colorScheme.errorContainer)
+ .padding(6.dp)
+ )
+ }
Spacer(Modifier.padding(5.dp))
if(!isda){
Text("你可以在adb shell中使用以下命令激活Device Admin")
@@ -131,11 +143,85 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
}
}
if(isdo&&VERSION.SDK_INT>=24){
- var lockScrInfo by remember { mutableStateOf("") }
- TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
- Spacer(Modifier.padding(5.dp))
- Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
- Text("设置锁屏DeviceOwner信息")
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 10.dp)
+ .clip(RoundedCornerShape(12.dp))
+ .background(color = MaterialTheme.colorScheme.primaryContainer)
+ .padding(10.dp)
+ ) {
+ var lockScrInfo by remember { mutableStateOf(myDpm.deviceOwnerLockScreenInfo) }
+ Text(text = "锁屏DeviceOwner信息", style = MaterialTheme.typography.titleLarge)
+ TextField(
+ value = if(lockScrInfo!=null){lockScrInfo.toString()}else{""},
+ onValueChange = { lockScrInfo= it},
+ label = { Text("锁屏信息") },
+ modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)
+ )
+ Row {
+ Button(onClick = {
+ myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)
+ lockScrInfo=myDpm.deviceOwnerLockScreenInfo
+ focusManager.clearFocus()
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ }) {
+ Text("应用")
+ }
+ Spacer(Modifier.padding(horizontal = 4.dp))
+ Button(onClick = {
+ myDpm.setDeviceOwnerLockScreenInfo(myComponent,null)
+ lockScrInfo=myDpm.deviceOwnerLockScreenInfo
+ focusManager.clearFocus()
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ }) {
+ Text("默认")
+ }
+ }
+ }
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 10.dp)
+ .clip(RoundedCornerShape(12.dp))
+ .background(color = MaterialTheme.colorScheme.primaryContainer)
+ .padding(10.dp)
+ ) {
+ Text(text = "提示消息", style = MaterialTheme.typography.titleLarge)
+ Text(text = "如果你禁用了某个功能,用户尝试使用这个功能时会看见这个消息(可多行)",modifier = Modifier.padding(vertical = 6.dp))
+ var supportMsg by remember{ mutableStateOf(myDpm.getShortSupportMessage(myComponent)) }
+ TextField(
+ value = if(supportMsg!=null){ supportMsg.toString() }else{""},
+ label = {Text("提示消息")},
+ onValueChange = { supportMsg=it },
+ modifier = Modifier.fillMaxWidth()
+ )
+ Row(
+ modifier = Modifier.padding(vertical = 6.dp)
+ ) {
+ Button(
+ onClick = {
+ myDpm.setShortSupportMessage(myComponent,supportMsg)
+ supportMsg=if(myDpm.getShortSupportMessage(myComponent)!=null){ myDpm.getShortSupportMessage(myComponent).toString() }else{""}
+ focusManager.clearFocus()
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ }
+ ) {
+ Text(text = "应用")
+ }
+ Spacer(Modifier.padding(horizontal = 4.dp))
+ Button(
+ onClick = {
+ myDpm.setShortSupportMessage(myComponent,null)
+ supportMsg = myDpm.getShortSupportMessage(myComponent)
+ focusManager.clearFocus()
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ }
+ ) {
+ Text(text = "默认")
+ }
+ }
+
}
}
}
diff --git a/app/src/main/java/com/binbin/androidowner/User.kt b/app/src/main/java/com/binbin/androidowner/User.kt
new file mode 100644
index 0000000..7116a50
--- /dev/null
+++ b/app/src/main/java/com/binbin/androidowner/User.kt
@@ -0,0 +1,32 @@
+package com.binbin.androidowner
+
+import android.app.admin.DevicePolicyManager
+import android.content.ComponentName
+import android.os.Build
+import androidx.compose.foundation.layout.Column
+import androidx.compose.material3.Button
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+
+@Composable
+fun User(myDpm:DevicePolicyManager,myComponent:ComponentName){
+ Column {
+ Column {
+ Text(text = "参数", style = MaterialTheme.typography.titleLarge)
+ if(Build.VERSION.SDK_INT>=34&&(myDpm.isProfileOwnerApp("com.binbin.androidowner")||myDpm.isManagedProfile(myComponent))){
+ val financed = myDpm.isDeviceFinanced
+ Text("Financed Device : $financed")
+ }
+ if (Build.VERSION.SDK_INT >= 28) {
+ val logoutable = myDpm.isLogoutEnabled
+ Text(text = "用户可以退出 : $logoutable")
+ val ephemeralUser = myDpm.isEphemeralUser(myComponent)
+ Text(text = "临时用户: $ephemeralUser")
+ Text("切换用户后或设备重启后会删除临时用户")
+ val affiliatedUser = myDpm.isAffiliatedUser
+ Text(text = "Affiliated User:$affiliatedUser")
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/binbin/androidowner/UserRestrict.kt b/app/src/main/java/com/binbin/androidowner/UserRestrict.kt
index 0e39428..e6726b7 100644
--- a/app/src/main/java/com/binbin/androidowner/UserRestrict.kt
+++ b/app/src/main/java/com/binbin/androidowner/UserRestrict.kt
@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -40,6 +41,7 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
modifier = Modifier
.verticalScroll(verticalScrolling)
.padding(bottom = 20.dp)
+ .navigationBarsPadding()
) {
Text("打开开关后会禁用对应的功能")
@@ -217,7 +219,8 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
) {
Text(
text = stringResource(itemName),
- style = MaterialTheme.typography.titleLarge
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.onTertiaryContainer
)
if(restrictionDescription!=""){Text(text = restrictionDescription, color = MaterialTheme.colorScheme.onSecondaryContainer)}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c105eb8..3b8e9ad 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -113,4 +113,5 @@
密码历史记录长度
用户输入的密码不能与历史记录中的任何密码相同,0为无限制
历史记录长度
+ USB信号
\ No newline at end of file