From b0535f54a56de508711f8fde74cfb93176da1b11 Mon Sep 17 00:00:00 2001
From: BinTianqi <1220958406@qq.com>
Date: Mon, 5 Feb 2024 13:16:15 +0800
Subject: [PATCH] set maximum time to lock
---
.../com/binbin/androidowner/DeviceControl.kt | 34 +++++++++-----
.../com/binbin/androidowner/MainActivity.kt | 29 ++++--------
.../java/com/binbin/androidowner/Password.kt | 46 +++++++++----------
.../com/binbin/androidowner/Permissions.kt | 37 +++------------
.../java/com/binbin/androidowner/Receiver.kt | 13 +++---
app/src/main/res/values/strings.xml | 5 +-
6 files changed, 70 insertions(+), 94 deletions(-)
diff --git a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
index 88f7eb8..a60d34f 100644
--- a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
+++ b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt
@@ -1,10 +1,12 @@
package com.binbin.androidowner
+import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.*
import android.content.ComponentName
import android.content.Context
import android.os.Build.VERSION
+import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.compose.animation.AnimatedVisibility
@@ -26,7 +28,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -221,19 +222,23 @@ fun DeviceControl(){
var keyGuard by remember{mutableStateOf(false)}
var blockAct by remember{mutableStateOf(false)}
if(VERSION.SDK_INT>=30){lockTaskPolicyList.add(LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK)}
- val refreshFeature = {
- var calculate = myDpm.getLockTaskFeatures(myComponent)
- if(VERSION.SDK_INT>=30&&calculate-lockTaskPolicyList[7]>=0){blockAct=true;calculate-=lockTaskPolicyList[7]}
- if(calculate-lockTaskPolicyList[6]>=0){keyGuard=true;calculate-=lockTaskPolicyList[6]}
- if(calculate-lockTaskPolicyList[5]>=0){globalAction=true;calculate-=lockTaskPolicyList[5]}
- if(calculate-lockTaskPolicyList[4]>=0){overview=true;calculate-=lockTaskPolicyList[4]}
- if(calculate-lockTaskPolicyList[3]>=0){home=true;calculate-=lockTaskPolicyList[3]}
- if(calculate-lockTaskPolicyList[2]>=0){notifications=true;calculate-=lockTaskPolicyList[2]}
- if(calculate-lockTaskPolicyList[1]>=0){sysInfo=true;calculate-=lockTaskPolicyList[1]}
- }
- Text(text = "锁定任务模式", style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
var inited by remember{mutableStateOf(false)}
var custom by remember{mutableStateOf(false)}
+ val refreshFeature = {
+ var calculate = myDpm.getLockTaskFeatures(myComponent)
+ if(calculate!=0){
+ if(VERSION.SDK_INT>=30&&calculate-lockTaskPolicyList[7]>=0){blockAct=true;calculate-=lockTaskPolicyList[7]}
+ if(calculate-lockTaskPolicyList[6]>=0){keyGuard=true;calculate-=lockTaskPolicyList[6]}
+ if(calculate-lockTaskPolicyList[5]>=0){globalAction=true;calculate-=lockTaskPolicyList[5]}
+ if(calculate-lockTaskPolicyList[4]>=0){overview=true;calculate-=lockTaskPolicyList[4]}
+ if(calculate-lockTaskPolicyList[3]>=0){home=true;calculate-=lockTaskPolicyList[3]}
+ if(calculate-lockTaskPolicyList[2]>=0){notifications=true;calculate-=lockTaskPolicyList[2]}
+ if(calculate-lockTaskPolicyList[1]>=0){sysInfo=true;calculate-=lockTaskPolicyList[1]}
+ }else{
+ custom = false
+ }
+ }
+ Text(text = "锁定任务模式", style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
if(!inited){ refreshFeature();custom=myDpm.getLockTaskFeatures(myComponent)!=0;inited=true }
Text(text = "在锁定任务模式下:", style = bodyTextStyle)
RadioButtonItem("禁用全部",{!custom},{custom=false})
@@ -295,9 +300,11 @@ fun DeviceControl(){
)
Button(
onClick = {
+ focusMgr.clearFocus()
whitelist.add(inputPkg)
myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ inputPkg=""
refreshWhitelist()
},
modifier = Modifier.fillMaxWidth()
@@ -306,6 +313,7 @@ fun DeviceControl(){
}
Button(
onClick = {
+ focusMgr.clearFocus()
if(inputPkg in whitelist){
whitelist.remove(inputPkg)
myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
@@ -313,6 +321,7 @@ fun DeviceControl(){
}else{
Toast.makeText(myContext, "不存在", Toast.LENGTH_SHORT).show()
}
+ inputPkg=""
refreshWhitelist()
},
modifier = Modifier.fillMaxWidth()
@@ -382,6 +391,7 @@ fun DeviceControl(){
if(isDeviceOwner(myDpm)){
SysUpdatePolicy()
}
+
Column(modifier = sections(if(isSystemInDarkTheme()){
colorScheme.errorContainer}else{
colorScheme.errorContainer.copy(alpha = 0.6F)})) {
diff --git a/app/src/main/java/com/binbin/androidowner/MainActivity.kt b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
index 3673779..aeceae1 100644
--- a/app/src/main/java/com/binbin/androidowner/MainActivity.kt
+++ b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
@@ -4,13 +4,10 @@ import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
-import android.content.Intent
-import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.animation.*
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -95,14 +92,7 @@ fun MyScaffold(){
modifier = Modifier
.padding(horizontal = 6.dp)
.clip(RoundedCornerShape(50))
- .clickable(onClick = {
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
- focusMgr.clearFocus()
- })
+ .clickable{ navCtrl.navigateUp(); focusMgr.clearFocus() }
.padding(5.dp)
)
}
@@ -235,14 +225,15 @@ fun RadioButtonItem(
textColor:Color = MaterialTheme.colorScheme.onBackground
){
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
+ val isWear = sharedPref.getBoolean("isWear",false)
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier
.fillMaxWidth()
- .padding(vertical = if(sharedPref.getBoolean("isWear",false)){3.dp}else{0.dp})
+ .padding(vertical = if(isWear){3.dp}else{0.dp})
.clip(RoundedCornerShape(25))
.clickable(onClick = operation)
) {
- RadioButton(selected = selected(), onClick = operation,modifier=if(sharedPref.getBoolean("isWear",false)){Modifier.size(28.dp)}else{Modifier})
- Text(text = text, style = if(!sharedPref.getBoolean("isWear",false)){typography.bodyLarge}else{typography.bodyMedium}, color = textColor,
+ RadioButton(selected = selected(), onClick = operation,modifier=if(isWear){Modifier.size(28.dp)}else{Modifier})
+ Text(text = text, style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium}, color = textColor,
modifier = Modifier.padding(bottom = 2.dp))
}
}
@@ -254,19 +245,19 @@ fun CheckBoxItem(
textColor:Color = MaterialTheme.colorScheme.onBackground
){
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
+ val isWear = sharedPref.getBoolean("isWear",false)
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier
.fillMaxWidth()
- .padding(vertical = if(sharedPref.getBoolean("isWear",false)){3.dp}else{0.dp})
+ .padding(vertical = if(isWear){3.dp}else{0.dp})
.clip(RoundedCornerShape(25))
.clickable(onClick = operation)
) {
Checkbox(
checked = checked(),
onCheckedChange = {operation()},
- modifier=if(sharedPref.getBoolean("isWear",false)){Modifier.size(28.dp)}else{Modifier}
+ modifier=if(isWear){Modifier.size(28.dp)}else{Modifier}
)
- Text(text = text, style = if(!sharedPref.getBoolean("isWear",false)){typography.bodyLarge}else{typography.bodyMedium}, color = textColor,
- modifier = Modifier.padding(bottom = 2.dp))
+ Text(text = text, style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium}, color = textColor, modifier = Modifier.padding(bottom = 2.dp))
}
}
diff --git a/app/src/main/java/com/binbin/androidowner/Password.kt b/app/src/main/java/com/binbin/androidowner/Password.kt
index e51316e..4b4ab70 100644
--- a/app/src/main/java/com/binbin/androidowner/Password.kt
+++ b/app/src/main/java/com/binbin/androidowner/Password.kt
@@ -24,7 +24,6 @@ import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
@@ -197,12 +196,14 @@ fun Password(){
}
}
- PasswordItem(R.string.max_pwd_fail,R.string.max_pwd_fail_desc,R.string.max_pwd_fail_textfield, myDpm,focusMgr,false,
+ PasswordItem(R.string.max_pwd_fail,R.string.max_pwd_fail_desc,R.string.max_pwd_fail_textfield, 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, myDpm,focusMgr,true,
+ PasswordItem(R.string.pwd_timeout,R.string.pwd_timeout_desc,R.string.pwd_timeout_textfield,true,
{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,myDpm, focusMgr,true,
+ PasswordItem(R.string.pwd_history,R.string.pwd_history_desc,R.string.pwd_history_textfield,true,
{myDpm.getPasswordHistoryLength(null).toString()},{ic -> myDpm.setPasswordHistoryLength(myComponent, ic.toInt()) })
+ PasswordItem(R.string.max_time_to_lock,R.string.max_time_to_lock_desc,R.string.max_time_to_lock_textfield,true,
+ {myDpm.getMaximumTimeToLock(myComponent).toString()},{ic -> myDpm.setMaximumTimeToLock(myComponent,ic.toLong())})
if(VERSION.SDK_INT>=31){
Column(modifier = sections()) {
@@ -408,21 +409,21 @@ private fun PasswordItem(
itemName:Int,
itemDesc:Int,
textFieldLabel:Int,
- myDpm:DevicePolicyManager,
- focusMgr:FocusManager,
allowZero:Boolean,
getMethod:()->String,
setMethod:(ic:String)->Unit
){
+ val myContext = LocalContext.current
+ val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
+ val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
+ val isWear = sharedPref.getBoolean("isWear",false)
+ val focusMgr = LocalFocusManager.current
Column(modifier = sections()) {
var inputContent by remember{ mutableStateOf(if(isDeviceOwner(myDpm)){getMethod()}else{""}) }
- var inputContentEdited by remember{ mutableStateOf(false) }
- var ableToApply by remember{ mutableStateOf(true) }
- val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
+ var ableToApply by remember{ mutableStateOf(inputContent!=""&&((inputContent=="0"&&allowZero)||inputContent!="0")) }
Text(text = stringResource(itemName), style = typography.titleLarge,color = colorScheme.onPrimaryContainer)
- Text(text= stringResource(itemDesc),modifier=Modifier.padding(vertical = 2.dp),
- style = if(!sharedPref.getBoolean("isWear",false)){typography.bodyLarge}else{typography.bodyMedium})
- if(!sharedPref.getBoolean("isWear",false)){Spacer(Modifier.padding(vertical = 2.dp))}
+ Text(text= stringResource(itemDesc),modifier=Modifier.padding(vertical = 2.dp), style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium})
+ if(!isWear){Spacer(Modifier.padding(vertical = 2.dp))}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
@@ -433,25 +434,20 @@ private fun PasswordItem(
label = { Text(stringResource(textFieldLabel))},
onValueChange = {
inputContent = it
- if(inputContent!=""&&((inputContent=="0"&&allowZero)||inputContent!="0")){
- inputContentEdited = inputContent!=getMethod()
- ableToApply = true
- }else{
- ableToApply = false
- }
+ ableToApply = inputContent!=""&&((inputContent=="0"&&allowZero)||inputContent!="0")
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
enabled = isDeviceOwner(myDpm),
- modifier = if(sharedPref.getBoolean("isWear",false)){Modifier.fillMaxWidth()}else{Modifier.fillMaxWidth(0.8F)}
+ modifier = if(isWear){Modifier.fillMaxWidth()}else{Modifier.fillMaxWidth(0.8F)}
)
- if(!sharedPref.getBoolean("isWear",false)){
+ if(!isWear){
IconButton(
- onClick = { focusMgr.clearFocus() ; setMethod(inputContent) ; inputContentEdited=inputContent!=getMethod() },
+ onClick = { focusMgr.clearFocus() ; setMethod(inputContent) },
enabled = isDeviceOwner(myDpm)&&ableToApply,
colors = IconButtonDefaults.iconButtonColors(
- contentColor = if(inputContentEdited){ colorScheme.onError}else{ colorScheme.onPrimary},
- containerColor = if(inputContentEdited){ colorScheme.error}else{ colorScheme.primary},
+ contentColor = colorScheme.onPrimary,
+ containerColor = colorScheme.primary,
disabledContentColor = Color.Transparent,
disabledContainerColor = Color.Transparent
)
@@ -459,9 +455,9 @@ private fun PasswordItem(
Icon(imageVector = Icons.Outlined.Check, contentDescription = null)
}}
}
- if(sharedPref.getBoolean("isWear",false)){
+ if(isWear){
Button(
- onClick = {focusMgr.clearFocus() ; setMethod(inputContent) ; inputContentEdited=inputContent!=getMethod()},
+ onClick = {focusMgr.clearFocus() ; setMethod(inputContent)},
enabled = isDeviceOwner(myDpm)&&ableToApply,
modifier = Modifier.fillMaxWidth()
) {
diff --git a/app/src/main/java/com/binbin/androidowner/Permissions.kt b/app/src/main/java/com/binbin/androidowner/Permissions.kt
index f7b5c56..4998bcc 100644
--- a/app/src/main/java/com/binbin/androidowner/Permissions.kt
+++ b/app/src/main/java/com/binbin/androidowner/Permissions.kt
@@ -31,7 +31,6 @@ 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
@@ -69,11 +68,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.removeActiveAdmin(myComponent)
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
}
) {
Text("撤销")
@@ -109,11 +104,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.clearProfileOwner(myComponent)
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
}
) {
Text("撤销")
@@ -150,11 +141,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.clearDeviceOwnerApp("com.binbin.androidowner")
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
}
) {
Text("撤销")
@@ -330,11 +317,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.removeActiveAdmin(myComponent)
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
},
colors = ButtonDefaults.buttonColors(contentColor = colorScheme.onError, containerColor = colorScheme.error),
enabled = myDpm.isAdminActive(myComponent)
@@ -345,11 +328,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.clearProfileOwner(myComponent)
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
},
colors = ButtonDefaults.buttonColors(contentColor = colorScheme.onError, containerColor = colorScheme.error),
enabled = isProfileOwner(myDpm)
@@ -360,11 +339,7 @@ fun DpmPermissions(navCtrl:NavHostController){
Button(
onClick = {
myDpm.clearDeviceOwnerApp("com.binbin.androidowner")
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ navCtrl.navigateUp()
},
colors = ButtonDefaults.buttonColors(contentColor = colorScheme.onError, containerColor = colorScheme.error),
enabled = isDeviceOwner(myDpm)
diff --git a/app/src/main/java/com/binbin/androidowner/Receiver.kt b/app/src/main/java/com/binbin/androidowner/Receiver.kt
index 43efff7..c0b5e2a 100644
--- a/app/src/main/java/com/binbin/androidowner/Receiver.kt
+++ b/app/src/main/java/com/binbin/androidowner/Receiver.kt
@@ -1,9 +1,11 @@
package com.binbin.androidowner
+import android.annotation.SuppressLint
import android.app.admin.DeviceAdminReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
+import android.os.Build.VERSION
import android.widget.Toast
class MyDeviceAdminReceiver : DeviceAdminReceiver() {
@@ -11,10 +13,11 @@ class MyDeviceAdminReceiver : DeviceAdminReceiver() {
super.onEnabled(context, intent)
Toast.makeText(context, "已启用", Toast.LENGTH_SHORT).show()
}
- /*override fun onReceive(context: Context, intent: Intent) {
+ @SuppressLint("UnsafeProtectedBroadcastReceiver")
+ override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
- Toast.makeText(context, "已接收", Toast.LENGTH_SHORT).show()
- }*/
+ if(VERSION.SDK_INT>=26){ DeviceAdminReceiver().onNetworkLogsAvailable(context,intent,1234567890,20) }
+ }
override fun onDisableRequested(context: Context, intent: Intent): CharSequence {
Toast.makeText(context, "撤销授权", Toast.LENGTH_SHORT).show()
return "这是取消时的提示"
@@ -24,9 +27,7 @@ class MyDeviceAdminReceiver : DeviceAdminReceiver() {
Toast.makeText(context, "已禁用", Toast.LENGTH_SHORT).show()
}
override fun onSystemUpdatePending(context: Context, intent: Intent, receivedTime: Long) {
- if (Build.VERSION.SDK_INT < 26) {
- return
- }
+ if (VERSION.SDK_INT < 26) { return }
Toast.makeText(context, "新的系统更新!", Toast.LENGTH_SHORT).show()
}
}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index acd146e..b0f64ee 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -93,7 +93,7 @@
错误次数
密码失效超时时间
超时后用户需重新设置密码(毫秒),0为无限制
- 超时时间
+ 超时时间(ms)
密码历史记录长度
用户输入的密码不能与历史记录中的任何密码相同,0为无限制
历史记录长度
@@ -112,4 +112,7 @@
实验性功能
网络日志记录
没啥用
+ 屏幕超时
+ 超时后锁屏(毫秒),0为由用户决定
+ 超时时间(ms)