From 5bc3f40d6e11239c81f88acd9a7335409f64963a Mon Sep 17 00:00:00 2001 From: BinTianqi <1220958406@qq.com> Date: Sun, 4 Feb 2024 21:48:43 +0800 Subject: [PATCH] lock task features --- app/src/main/AndroidManifest.xml | 2 + .../com/binbin/androidowner/DeviceControl.kt | 125 +++++++++++++++++- .../com/binbin/androidowner/MainActivity.kt | 13 ++ .../binbin/androidowner/SystemUpdatePolicy.kt | 59 ++++++++- 4 files changed, 191 insertions(+), 8 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9107b5a..05dac6e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,8 @@ + + =28&&isDeviceOwner(myDpm)){ + Column(modifier = sections()){ + val lockTaskPolicyList = mutableListOf( + LOCK_TASK_FEATURE_NONE, + LOCK_TASK_FEATURE_SYSTEM_INFO, + LOCK_TASK_FEATURE_NOTIFICATIONS, + LOCK_TASK_FEATURE_HOME, + LOCK_TASK_FEATURE_OVERVIEW, + LOCK_TASK_FEATURE_GLOBAL_ACTIONS, + LOCK_TASK_FEATURE_KEYGUARD + ) + var sysInfo by remember{mutableStateOf(false)} + var notifications by remember{mutableStateOf(false)} + var home by remember{mutableStateOf(false)} + var overview by remember{mutableStateOf(false)} + var globalAction by remember{mutableStateOf(false)} + 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)} + if(!inited){ refreshFeature();custom=myDpm.getLockTaskFeatures(myComponent)!=0;inited=true } + Text(text = "在锁定任务模式下:", style = bodyTextStyle) + RadioButtonItem("禁用全部",{!custom},{custom=false}) + RadioButtonItem("自定义",{custom},{custom=true}) + AnimatedVisibility(custom) { + Column { + CheckBoxItem("允许状态栏信息",{sysInfo},{sysInfo=!sysInfo}) + CheckBoxItem("允许通知",{notifications},{notifications=!notifications}) + CheckBoxItem("允许返回主屏幕",{home},{home=!home}) + CheckBoxItem("允许打开后台应用概览",{overview},{overview=!overview}) + CheckBoxItem("允许全局行为(比如长按电源键对话框)",{globalAction},{globalAction=!globalAction}) + CheckBoxItem("允许锁屏(如果没有选择此项,即使有密码也不会锁屏)",{keyGuard},{keyGuard=!keyGuard}) + if(VERSION.SDK_INT>=30){ CheckBoxItem("阻止启动未允许的应用",{blockAct},{blockAct=!blockAct}) } + } + } + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { + var result = lockTaskPolicyList[0] + if(custom){ + if(blockAct&&VERSION.SDK_INT>=30){result+=lockTaskPolicyList[7]} + if(keyGuard){result+=lockTaskPolicyList[6]} + if(globalAction){result+=lockTaskPolicyList[5]} + if(overview){result+=lockTaskPolicyList[4]} + if(home){result+=lockTaskPolicyList[3]} + if(notifications){result+=lockTaskPolicyList[2]} + if(sysInfo){result+=lockTaskPolicyList[1]} + } + myDpm.setLockTaskFeatures(myComponent,result) + refreshFeature() + Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() + } + ) { + Text("应用") + } + Spacer(Modifier.padding(vertical = 4.dp)) + val whitelist = myDpm.getLockTaskPackages(myComponent).toMutableList() + var listText by remember{mutableStateOf("")} + var inputPkg by remember{mutableStateOf("")} + val refreshWhitelist = { + listText="" + var currentItem = whitelist.size + for(each in whitelist){ + currentItem-=1 + listText += each + if(currentItem>0){listText += "\n"} + } + } + refreshWhitelist() + Text(text = "白名单应用", style = typography.titleLarge) + if(listText!=""){ Text(listText) }else{ Text(("无")) } + TextField( + value = inputPkg, + onValueChange = {inputPkg=it}, + label = {Text("包名")}, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}), + modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp) + ) + Button( + onClick = { + whitelist.add(inputPkg) + myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray()) + Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() + refreshWhitelist() + }, + modifier = Modifier.fillMaxWidth() + ) { + Text("加入白名单") + } + Button( + onClick = { + if(inputPkg in whitelist){ + whitelist.remove(inputPkg) + myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray()) + Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() + }else{ + Toast.makeText(myContext, "不存在", Toast.LENGTH_SHORT).show() + } + refreshWhitelist() + }, + modifier = Modifier.fillMaxWidth() + ) { + Text("从白名单中移除") + } + } + } + if(VERSION.SDK_INT>=29&&isDeviceOwner(myDpm)){ Column(modifier = sections()){ Text(text = "私人DNS", style = typography.titleLarge) @@ -245,6 +366,8 @@ fun DeviceControl(){ Toast.makeText(myContext, operationResult[result], Toast.LENGTH_SHORT).show() }catch(e:IllegalArgumentException){ Toast.makeText(myContext, "无效主机名", Toast.LENGTH_SHORT).show() + }catch(e:SecurityException){ + Toast.makeText(myContext, "安全错误", Toast.LENGTH_SHORT).show() }finally { status = dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)] } diff --git a/app/src/main/java/com/binbin/androidowner/MainActivity.kt b/app/src/main/java/com/binbin/androidowner/MainActivity.kt index 024917f..3673779 100644 --- a/app/src/main/java/com/binbin/androidowner/MainActivity.kt +++ b/app/src/main/java/com/binbin/androidowner/MainActivity.kt @@ -4,9 +4,13 @@ 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.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -34,12 +38,21 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.binbin.androidowner.ui.theme.AndroidOwnerTheme +/*lateinit var getOtaPackage: ActivityResultLauncher +var installOta = false +lateinit var otaUri:Uri*/ @ExperimentalMaterial3Api class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, false) super.onCreate(savedInstanceState) + /*otaUri = Uri.EMPTY + getOtaPackage = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + val data = it.data?.data + installOta = true + otaUri = data ?: Uri.EMPTY + }*/ setContent { AndroidOwnerTheme { MyScaffold() diff --git a/app/src/main/java/com/binbin/androidowner/SystemUpdatePolicy.kt b/app/src/main/java/com/binbin/androidowner/SystemUpdatePolicy.kt index 6e481c6..c21545d 100644 --- a/app/src/main/java/com/binbin/androidowner/SystemUpdatePolicy.kt +++ b/app/src/main/java/com/binbin/androidowner/SystemUpdatePolicy.kt @@ -1,9 +1,12 @@ package com.binbin.androidowner import android.app.admin.DevicePolicyManager +import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback import android.app.admin.SystemUpdateInfo import android.app.admin.SystemUpdatePolicy 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 @@ -23,6 +26,7 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import java.util.Date +import java.util.concurrent.Executors @Composable fun SysUpdatePolicy(){ @@ -30,21 +34,24 @@ fun SysUpdatePolicy(){ val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java) val focusMgr = LocalFocusManager.current + val sharedPref = myContext.getSharedPreferences("data", Context.MODE_PRIVATE) + val isWear = sharedPref.getBoolean("isWear",false) + val bodyTextStyle = if(isWear){ typography.bodyMedium}else{typography.bodyLarge} Column { - if(VERSION.SDK_INT>=26){ + if(VERSION.SDK_INT>=26&&isDeviceOwner(myDpm)){ + val sysUpdateInfo = myDpm.getPendingSystemUpdate(myComponent) Column(modifier = sections()) { - val sysUpdateInfo = if(isDeviceOwner(myDpm)){myDpm.getPendingSystemUpdate(myComponent)}else{null} if(sysUpdateInfo!=null){ - Text("Update first available: ${Date(sysUpdateInfo.receivedTime)}") - Text("Hash code: ${sysUpdateInfo.hashCode()}") + Text(text = "Update first available: ${Date(sysUpdateInfo.receivedTime)}", style = bodyTextStyle) + Text(text = "Hash code: ${sysUpdateInfo.hashCode()}", style = bodyTextStyle) val securityStateDesc = when(sysUpdateInfo.securityPatchState){ SystemUpdateInfo.SECURITY_PATCH_STATE_UNKNOWN->"SECURITY_PATCH_STATE_UNKNOWN" SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE->"SECURITY_PATCH_STATE_TRUE" else->"SECURITY_PATCH_STATE_FALSE" } - Text("Security patch state: $securityStateDesc") + Text(text = "Security patch state: $securityStateDesc", style = bodyTextStyle) }else{ - Text("暂无更新信息") + Text(text = "暂无系统更新", style = bodyTextStyle) } } } @@ -80,7 +87,7 @@ fun SysUpdatePolicy(){ ) } Spacer(Modifier.padding(vertical = 3.dp)) - Text("请输入一天中的分钟(0~1440)") + Text(text = "请输入一天中的分钟(0~1440)", style = bodyTextStyle) } val policy = when(selectedPolicy){ @@ -97,5 +104,43 @@ fun SysUpdatePolicy(){ Text("应用") } }} + /*if(VERSION.SDK_INT>=29){ + Column(modifier = sections()){ + var resultUri by remember{mutableStateOf(otaUri)} + Text(text = "安装系统更新", style = typography.titleLarge) + Button( + onClick = { + val getUri = Intent(Intent.ACTION_GET_CONTENT) + getUri.setType("application/zip") + getUri.addCategory(Intent.CATEGORY_OPENABLE) + getOtaPackage.launch(getUri) + }, + modifier = Modifier.fillMaxWidth(), + enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm) + ) { + Text("选择OTA包") + } + Button( + onClick = {resultUri = otaUri}, + modifier = Modifier.fillMaxWidth(), + enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm) + ) { + Text("查看OTA包详情") + } + Text("URI: $resultUri") + if(installOta){ + Button( + onClick = { + val sysUpdateExecutor = Executors.newCachedThreadPool() + val sysUpdateCallback:InstallSystemUpdateCallback = InstallSystemUpdateCallback + myDpm.installSystemUpdate(myComponent,resultUri,sysUpdateExecutor,sysUpdateCallback) + }, + enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm) + ){ + Text("安装") + } + } + } + }*/ } }