ShortSupportMessage can be modified

This commit is contained in:
BinTianqi
2024-01-19 19:50:45 +08:00
parent c8af8f054f
commit 62c3144a76
9 changed files with 171 additions and 13 deletions

View File

@@ -11,8 +11,8 @@ android {
applicationId = "com.binbin.androidowner" applicationId = "com.binbin.androidowner"
minSdk = 23 minSdk = 23
targetSdk = 34 targetSdk = 34
versionCode = 3 versionCode = 4
versionName = "1.2" versionName = "1.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {

View File

@@ -49,7 +49,8 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
onValueChange = { onValueChange = {
pkgName = it pkgName = it
}, },
label = { Text("包名") } label = { Text("包名") },
modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)
) )
if(VERSION.SDK_INT>=24){ if(VERSION.SDK_INT>=24){
val isSuspended = { val isSuspended = {

View File

@@ -11,6 +11,7 @@ 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
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -40,6 +41,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
modifier = Modifier modifier = Modifier
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding(bottom = 20.dp) .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_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) }) 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){ 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) }) 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){ if(VERSION.SDK_INT>=24){
Button(onClick = {myDpm.reboot(myComponent)}) { Button(onClick = {myDpm.reboot(myComponent)}) {
Text("重启") Text("重启")
@@ -74,6 +83,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
if(VERSION.SDK_INT<30){ if(VERSION.SDK_INT<30){
Text("自动设置时间和自动设置时区需要API30") Text("自动设置时间和自动设置时区需要API30")
} }
if(VERSION.SDK_INT<31){Text("关闭USB信号需API31")}
if(VERSION.SDK_INT<34){ if(VERSION.SDK_INT<34){
Text("隐藏状态栏需要API34") Text("隐藏状态栏需要API34")
} }

View File

@@ -13,6 +13,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@@ -120,6 +121,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
startDestination = "HomePage", startDestination = "HomePage",
modifier = Modifier modifier = Modifier
.padding(top = it.calculateTopPadding()) .padding(top = it.calculateTopPadding())
.imePadding()
){ ){
composable(route = "HomePage", content = { HomePage(navCtrl,mainDpm,mainComponent)}) composable(route = "HomePage", content = { HomePage(navCtrl,mainDpm,mainComponent)})
composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)}) composable(route = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)})

View File

@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -54,6 +55,7 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.verticalScroll(rememberScrollState()) .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)) } 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( Text(
@@ -66,6 +68,27 @@ fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
.background(color = MaterialTheme.colorScheme.errorContainer) .background(color = MaterialTheme.colorScheme.errorContainer)
.padding(8.dp) .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){ if(VERSION.SDK_INT>=26){
Column( Column(
horizontalAlignment = Alignment.Start, 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, 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()) }) {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, 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, 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()) }) {myDpm.getPasswordHistoryLength(null).toString()},{ic -> myDpm.setPasswordHistoryLength(myComponent, ic.toInt()) })

View File

@@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION import android.os.Build.VERSION
import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -29,20 +30,21 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity import androidx.core.content.ContextCompat.startActivity
import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
@Composable @Composable
fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myContext:Context,navCtrl:NavHostController){ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myContext:Context,navCtrl:NavHostController){
//da:DeviceAdmin do:DeviceOwner //da:DeviceAdmin do:DeviceOwner
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 focusManager = LocalFocusManager.current
Column( Column(
modifier = Modifier modifier = Modifier
.padding(8.dp) .padding(horizontal = 8.dp)
.verticalScroll(rememberScrollState()), .verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
@@ -111,7 +113,17 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
Column( Column(
horizontalAlignment = Alignment.Start 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)) Spacer(Modifier.padding(5.dp))
if(!isda){ if(!isda){
Text("你可以在adb shell中使用以下命令激活Device Admin") Text("你可以在adb shell中使用以下命令激活Device Admin")
@@ -131,11 +143,85 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
} }
} }
if(isdo&&VERSION.SDK_INT>=24){ if(isdo&&VERSION.SDK_INT>=24){
var lockScrInfo by remember { mutableStateOf("") } Column(
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") }) modifier = Modifier
Spacer(Modifier.padding(5.dp)) .fillMaxWidth()
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) { .padding(bottom = 10.dp)
Text("设置锁屏DeviceOwner信息") .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 = "默认")
}
}
} }
} }
} }

View File

@@ -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")
}
}
}
}

View File

@@ -10,6 +10,7 @@ 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
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -40,6 +41,7 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
modifier = Modifier modifier = Modifier
.verticalScroll(verticalScrolling) .verticalScroll(verticalScrolling)
.padding(bottom = 20.dp) .padding(bottom = 20.dp)
.navigationBarsPadding()
) { ) {
Text("打开开关后会禁用对应的功能") Text("打开开关后会禁用对应的功能")
@@ -217,7 +219,8 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
) { ) {
Text( Text(
text = stringResource(itemName), text = stringResource(itemName),
style = MaterialTheme.typography.titleLarge style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onTertiaryContainer
) )
if(restrictionDescription!=""){Text(text = restrictionDescription, color = MaterialTheme.colorScheme.onSecondaryContainer)} if(restrictionDescription!=""){Text(text = restrictionDescription, color = MaterialTheme.colorScheme.onSecondaryContainer)}
} }

View File

@@ -113,4 +113,5 @@
<string name="pwd_history">密码历史记录长度</string> <string name="pwd_history">密码历史记录长度</string>
<string name="pwd_history_desc">用户输入的密码不能与历史记录中的任何密码相同0为无限制</string> <string name="pwd_history_desc">用户输入的密码不能与历史记录中的任何密码相同0为无限制</string>
<string name="pwd_history_textfield">历史记录长度</string> <string name="pwd_history_textfield">历史记录长度</string>
<string name="usb_signal">USB信号</string>
</resources> </resources>