Add new features to the password section

This commit is contained in:
BinTianqi
2024-01-18 20:53:16 +08:00
parent 5aab260644
commit 13fa0d7b4d
4 changed files with 180 additions and 96 deletions

View File

@@ -86,7 +86,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
"UIControl" to R.string.ui_ctrl,
"ApplicationManage" to R.string.app_manage,
"UserRestriction" to R.string.user_restrict,
"Security" to R.string.security
"Password" to R.string.password
)
val topBarName = topBarNameMap[backStackEntry?.destination?.route]?: R.string.app_name
Scaffold(
@@ -135,7 +135,7 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)})
composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)})
composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent)})
composable(route = "Security", content = { Security(mainDpm,mainComponent,mainContext)})
composable(route = "Password", content = { Password(mainDpm,mainComponent,mainContext)})
}
}
}
@@ -181,7 +181,7 @@ fun HomePage(navCtrl:NavHostController,myDpm:DevicePolicyManager,myComponent:Com
HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, R.string.device_ctrl_desc, "DeviceControl", navCtrl)
HomePageItem(R.string.app_manage, R.drawable.apps_fill0, R.string.apps_ctrl_description, "ApplicationManage", navCtrl)
HomePageItem(R.string.user_restrict, R.drawable.manage_accounts_fill0, R.string.user_restrict_desc, "UserRestriction", navCtrl)
HomePageItem(R.string.security, R.drawable.security_fill0,R.string.security_desc, "Security",navCtrl)
HomePageItem(R.string.password, R.drawable.password_fill0,R.string.security_desc, "Password",navCtrl)
}
}

View File

@@ -74,7 +74,7 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
Text("撤销")
}
}else{
Button(onClick = { ActivateDeviceAdmin(myDpm, myComponent, myContext) }) {
Button(onClick = { ActivateDeviceAdmin(myComponent, myContext) }) {
Text("激活")
}
}
@@ -141,7 +141,7 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
}
}
fun ActivateDeviceAdmin(myDpm: DevicePolicyManager,myComponent: ComponentName,myContext: Context){
fun ActivateDeviceAdmin(myComponent: ComponentName,myContext: Context){
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, myComponent)
intent.putExtra(

View File

@@ -7,15 +7,24 @@ import android.content.Context
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Check
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
@@ -27,40 +36,52 @@ 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.focus.FocusManager
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.core.content.ContextCompat.startActivity
@Composable
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Context){
fun Password(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Context){
var newPwd by remember{ mutableStateOf("") }
var confirmed by remember{ mutableStateOf(false) }
val focusMgr = LocalFocusManager.current
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
) {
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 = "以下操作可能会造成不可挽回的损失,请先备份好数据。执行操作时一定要谨慎!!!",
color = MaterialTheme.colorScheme.onErrorContainer,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.errorContainer)
.padding(8.dp)
)
if(VERSION.SDK_INT>=26){
Column(
horizontalAlignment = Alignment.Start,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.padding(horizontal = 8.dp, vertical = 4.dp)
.clip(RoundedCornerShape(10))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(8.dp)
) {
Text(
text = "密码重置令牌",
style = MaterialTheme.typography.titleLarge
)
Text(text = "密码重置令牌", style = MaterialTheme.typography.titleLarge)
Row {
Button(
onClick = {
if(myDpm.clearResetPasswordToken(myComponent)){
Toast.makeText(myContext, "清除成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "清除失败", Toast.LENGTH_SHORT).show()
}
if(myDpm.clearResetPasswordToken(myComponent)){ Toast.makeText(myContext, "清除成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "清除失败", Toast.LENGTH_SHORT).show() }
},
modifier = Modifier.padding(end = 8.dp)
) {
@@ -68,11 +89,8 @@ fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
}
Button(
onClick = {
if(myDpm.setResetPasswordToken(myComponent, myByteArray)){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
if(myDpm.setResetPasswordToken(myComponent, myByteArray)){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
},
modifier = Modifier.padding(end = 8.dp)
) {
@@ -81,14 +99,9 @@ fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
Button(
onClick = {
if(!myDpm.isResetPasswordTokenActive(myComponent)){
try{
activateToken(myContext)
}catch(e:NullPointerException){
Toast.makeText(myContext, "请先设置令牌", Toast.LENGTH_SHORT).show()
}
}else{
Toast.makeText(myContext, "已经激活", Toast.LENGTH_SHORT).show()
}
try{ activateToken(myContext)
}catch(e:NullPointerException){ Toast.makeText(myContext, "请先设置令牌", Toast.LENGTH_SHORT).show() }
}else{ Toast.makeText(myContext, "已经激活", Toast.LENGTH_SHORT).show() }
}
) {
Text("激活")
@@ -97,24 +110,28 @@ fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
Text("没有密码时会自动激活令牌")
}
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
.clip(RoundedCornerShape(10))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(10.dp)
) {
TextField(
value = newPwd,
onValueChange = {newPwd=it},
enabled = !confirmed,
label = { Text("密码")}
)
Text(
text = "(留空可以清除密码)",
modifier = Modifier.padding(vertical = 5.dp)
label = { Text("密码")},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
)
Text(text = stringResource(R.string.reset_pwd_desc), modifier = Modifier.padding(vertical = 5.dp))
Row {
Button(
onClick = {
if(newPwd.length>=4||newPwd.isEmpty()){
confirmed=!confirmed
}else{
Toast.makeText(myContext, "需要4位数字或字母", Toast.LENGTH_SHORT).show()
}
if(newPwd.length>=4||newPwd.isEmpty()){ confirmed=!confirmed
}else{ Toast.makeText(myContext, "需要4位数字或字母", Toast.LENGTH_SHORT).show() }
},
modifier = Modifier.padding(end = 10.dp)
) {
@@ -124,18 +141,12 @@ fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
Button(
onClick = {
val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,0)
if(resetSuccess){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false
},
enabled = confirmed,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError
)
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error, contentColor = MaterialTheme.colorScheme.onError)
) {
Text("设置密码")
}
@@ -143,37 +154,100 @@ fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Conte
Button(
onClick = {
val resetSuccess = myDpm.resetPassword(newPwd,0)
if(resetSuccess){
Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show()
}
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show()
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false
},
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError
)
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error, contentColor = MaterialTheme.colorScheme.onError)
) {
Text("设置密码")
}
}
}
Text(
text = "该操作可能会造成不可挽回的损失,请先备份好数据。设置密码的时候一定要谨慎!!!",
color = MaterialTheme.colorScheme.onErrorContainer,
}
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()) })
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()) })
}
}
@Composable
fun PasswordItem(
itemName:Int,
itemDesc:Int,
textFieldLabel:Int,
focusMgr:FocusManager,
allowZero:Boolean,
getMethod:()->String,
setMethod:(ic:String)->Unit
){
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clip(RoundedCornerShape(15))
.background(color = MaterialTheme.colorScheme.errorContainer)
.padding(horizontal = 8.dp, vertical = 4.dp)
.clip(RoundedCornerShape(10))
.background(color = MaterialTheme.colorScheme.primaryContainer)
.padding(10.dp)
) {
var inputContent by remember{ mutableStateOf(getMethod()) }
var inputContentEdited by remember{ mutableStateOf(false) }
var ableToApply by remember{ mutableStateOf(true) }
Text(text = stringResource(itemName), style = MaterialTheme.typography.titleLarge)
Text(text= stringResource(itemDesc),modifier=Modifier.padding(vertical = 2.dp))
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(end = 8.dp)
){
TextField(
value = inputContent,
label = { Text(stringResource(textFieldLabel))},
onValueChange = {
inputContent = it
if(inputContent!=""&&((inputContent=="0"&&allowZero)||inputContent!="0")){
inputContentEdited = inputContent!=getMethod()
ableToApply = true
}else{
ableToApply = false
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
)
if(ableToApply){
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = null,
tint = if(inputContentEdited){MaterialTheme.colorScheme.onError}else{MaterialTheme.colorScheme.onPrimary},
modifier = Modifier
.clip(RoundedCornerShape(20))
.background(
color = if (inputContentEdited) {
MaterialTheme.colorScheme.error
} else {
MaterialTheme.colorScheme.primary
}
)
.clickable(onClick = {
focusMgr.clearFocus()
setMethod(inputContent)
inputContentEdited = inputContent != getMethod()
})
.padding(8.dp)
)
}
}
}
}
fun activateToken(myContext: Context){
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
val ACTIVATE_TOKEN_PROMPT = "在这里激活密码重置令牌"
val keyguardManager = myContext.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)
confirmIntent.setFlags(FLAG_ACTIVITY_NEW_TASK)

View File

@@ -47,7 +47,17 @@
<string name="sometimes_not_available">有时候不能用</string>
<string name="user_ctrl_disabled">禁止用户控制</string>
<string name="user_ctrl_disabled_desc">阻止清除应用数据和缓存</string>
<string name="security">安全</string>
<string name="password">密码</string>
<string name="inst_unknown_src">安装未知来源应用</string>
<string name="security_desc">修改或清除锁屏密码</string>>
<string name="security_desc">锁屏密码相关操作</string>
<string name="max_pwd_fail">最大密码错误次数</string>
<string name="max_pwd_fail_desc">达到该限制会恢复出厂设置</string>
<string name="max_pwd_fail_textfield">错误次数</string>
<string name="pwd_timeout">密码失效超时时间</string>
<string name="pwd_timeout_desc">超时后用户需重新设置密码毫秒0为无限制</string>
<string name="pwd_timeout_textfield">超时时间</string>
<string name="pwd_history">密码历史记录长度</string>
<string name="pwd_history_desc">用户输入的密码不能与历史记录中的任何密码相同0为无限制</string>
<string name="pwd_history_textfield">历史记录长度</string>
<string name="reset_pwd_desc">留空可以清除密码纯数字将使用PIN码</string>
</resources>