mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
Add security section, backward compatible to API23
This commit is contained in:
@@ -9,10 +9,10 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.binbin.androidowner"
|
applicationId = "com.binbin.androidowner"
|
||||||
minSdk = 26
|
minSdk = 23
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 2
|
versionCode = 3
|
||||||
versionName = "1.1"
|
versionName = "1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ package com.binbin.androidowner
|
|||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager.NameNotFoundException
|
import android.content.pm.PackageManager.NameNotFoundException
|
||||||
|
import android.net.Uri
|
||||||
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
|
||||||
@@ -28,6 +31,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -47,6 +51,7 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
|
|||||||
},
|
},
|
||||||
label = { Text("包名") }
|
label = { Text("包名") }
|
||||||
)
|
)
|
||||||
|
if(VERSION.SDK_INT>=24){
|
||||||
val isSuspended = {
|
val isSuspended = {
|
||||||
try{
|
try{
|
||||||
myDpm.isPackageSuspended(myComponent,pkgName)
|
myDpm.isPackageSuspended(myComponent,pkgName)
|
||||||
@@ -54,25 +59,38 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppManageItem(R.string.hide,R.string.isapphidden_desc,myDpm, {myDpm.isApplicationHidden(myComponent,pkgName)},
|
|
||||||
{b -> myDpm.setApplicationHidden(myComponent,pkgName,b)})
|
|
||||||
AppManageItem(R.string.suspend,R.string.place_holder,myDpm, isSuspended,
|
AppManageItem(R.string.suspend,R.string.place_holder,myDpm, isSuspended,
|
||||||
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
|
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
|
||||||
/*AppManageItem(R.string.block_unins,R.string.sometimes_not_avaliable,myDpm, {myDpm.isUninstallBlocked(myComponent,pkgName)},
|
}
|
||||||
|
AppManageItem(R.string.hide,R.string.isapphidden_desc,myDpm, {myDpm.isApplicationHidden(myComponent,pkgName)},
|
||||||
|
{b -> myDpm.setApplicationHidden(myComponent,pkgName,b)})
|
||||||
|
if(VERSION.SDK_INT>=30){
|
||||||
|
AppManageItem(R.string.user_ctrl_disabled,R.string.user_ctrl_disabled_desc,myDpm, {pkgName in myDpm.getUserControlDisabledPackages(myComponent)},
|
||||||
|
{b->myDpm.setUserControlDisabledPackages(myComponent, mutableListOf(if(b){pkgName}else{null}))})
|
||||||
|
}
|
||||||
|
/*AppManageItem(R.string.block_unins,R.string.sometimes_not_available,myDpm, {myDpm.isUninstallBlocked(myComponent,pkgName)},
|
||||||
{b -> myDpm.setUninstallBlocked(myComponent,pkgName,b)})*/
|
{b -> myDpm.setUninstallBlocked(myComponent,pkgName,b)})*/
|
||||||
Text("因为无法获取某个应用是否防卸载,无法使用开关控制防卸载")
|
Row(
|
||||||
Row {
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(5.dp)
|
||||||
|
.clip(RoundedCornerShape(15))
|
||||||
|
.background(color = MaterialTheme.colorScheme.primaryContainer)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceAround
|
||||||
|
) {
|
||||||
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,false)}) {
|
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,false)}) {
|
||||||
Text("取消防卸载")
|
Text("取消防卸载")
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(horizontal = 2.dp))
|
|
||||||
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}) {
|
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}) {
|
||||||
Text("防卸载")
|
Text("防卸载")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT>=30){
|
Button(
|
||||||
AppManageItem(R.string.user_ctrl_disabled,R.string.user_ctrl_disabled_desc,myDpm, {pkgName in myDpm.getUserControlDisabledPackages(myComponent)},
|
onClick = {
|
||||||
{b->myDpm.setUserControlDisabledPackages(myComponent, mutableListOf(if(b){pkgName}else{null}))})
|
uninstallApp(myContext,pkgName)
|
||||||
|
}) {
|
||||||
|
Text("卸载")
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(5.dp))
|
Spacer(Modifier.padding(5.dp))
|
||||||
}
|
}
|
||||||
@@ -119,3 +137,22 @@ private fun AppManageItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun uninstallPkg(pkgName:String,myContext:Context){
|
||||||
|
val packageManager = myContext.packageManager
|
||||||
|
try {
|
||||||
|
val packageInfo = packageManager.getPackageInfo(pkgName, 0)
|
||||||
|
val intent = Intent(Intent.ACTION_DELETE)
|
||||||
|
intent.setData(Uri.parse("package:" + packageInfo.packageName))
|
||||||
|
startActivity(myContext,intent,null)
|
||||||
|
} catch (e: NameNotFoundException) {
|
||||||
|
Toast.makeText(myContext, "应用未安装", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uninstallApp(context: Context, packageName: String) {
|
||||||
|
val packageUri = Uri.parse("package:$packageName")
|
||||||
|
val uninstallIntent = Intent(Intent.ACTION_DELETE, packageUri)
|
||||||
|
uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
context.startActivity(uninstallIntent)
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
||||||
val wifimac = try {
|
|
||||||
myDpm.getWifiMacAddress(myComponent).toString()
|
|
||||||
}catch(e:SecurityException){
|
|
||||||
"没有权限"
|
|
||||||
}
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
@@ -54,16 +49,35 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
|||||||
DeviceCtrlItem(R.string.auto_timezone,R.string.place_holder,myDpm,{myDpm.getAutoTimeZoneEnabled(myComponent)},{b -> myDpm.setAutoTimeZoneEnabled(myComponent,b) })
|
DeviceCtrlItem(R.string.auto_timezone,R.string.place_holder,myDpm,{myDpm.getAutoTimeZoneEnabled(myComponent)},{b -> myDpm.setAutoTimeZoneEnabled(myComponent,b) })
|
||||||
}
|
}
|
||||||
DeviceCtrlItem(R.string.master_mute,R.string.place_holder,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) })
|
DeviceCtrlItem(R.string.master_mute,R.string.place_holder,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) })
|
||||||
|
if(VERSION.SDK_INT>=26){
|
||||||
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
|
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
|
||||||
Text("隐藏状态栏需要API34")
|
}
|
||||||
Text("自动设置时间和自动设置时区需要API30")
|
if(VERSION.SDK_INT>=24){
|
||||||
Button(onClick = {myDpm.reboot(myComponent)}) {
|
Button(onClick = {myDpm.reboot(myComponent)}) {
|
||||||
Text("重启")
|
Text("重启")
|
||||||
}
|
}
|
||||||
|
val wifimac = try {
|
||||||
|
myDpm.getWifiMacAddress(myComponent).toString()
|
||||||
|
}catch(e:SecurityException){
|
||||||
|
"没有权限"
|
||||||
|
}
|
||||||
|
Text("WiFi MAC: $wifimac")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT<24){
|
||||||
|
Text("重启和WiFi Mac需要API24")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT<26){
|
||||||
|
Text("备份服务需要API26")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT<30){
|
||||||
|
Text("自动设置时间和自动设置时区需要API30")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT<34){
|
||||||
|
Text("隐藏状态栏需要API34")
|
||||||
|
}
|
||||||
Button(onClick = {myDpm.lockNow()}) {
|
Button(onClick = {myDpm.lockNow()}) {
|
||||||
Text("锁屏")
|
Text("锁屏")
|
||||||
}
|
}
|
||||||
Text("WiFi MAC: $wifimac")
|
|
||||||
Text("以下功能需要长按按钮,作者并未测试")
|
Text("以下功能需要长按按钮,作者并未测试")
|
||||||
Button(
|
Button(
|
||||||
onClick = {},
|
onClick = {},
|
||||||
@@ -76,7 +90,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
|||||||
) {
|
) {
|
||||||
Text("WipeData")
|
Text("WipeData")
|
||||||
}
|
}
|
||||||
if (VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
if (VERSION.SDK_INT >= 34) {
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeDevice(0)}),
|
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeDevice(0)}),
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
|
|||||||
"Permissions" to R.string.permission,
|
"Permissions" to R.string.permission,
|
||||||
"UIControl" to R.string.ui_ctrl,
|
"UIControl" to R.string.ui_ctrl,
|
||||||
"ApplicationManage" to R.string.app_manage,
|
"ApplicationManage" to R.string.app_manage,
|
||||||
"UserRestriction" to R.string.user_restrict
|
"UserRestriction" to R.string.user_restrict,
|
||||||
|
"Security" to R.string.security
|
||||||
)
|
)
|
||||||
val topBarName = topBarNameMap[backStackEntry?.destination?.route]?: R.string.app_name
|
val topBarName = topBarNameMap[backStackEntry?.destination?.route]?: R.string.app_name
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -125,13 +126,16 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
|
|||||||
NavHost(
|
NavHost(
|
||||||
navController = navCtrl,
|
navController = navCtrl,
|
||||||
startDestination = "HomePage",
|
startDestination = "HomePage",
|
||||||
modifier = Modifier.padding(top = it.calculateTopPadding()).navigationBarsPadding()
|
modifier = Modifier
|
||||||
|
.padding(top = it.calculateTopPadding())
|
||||||
|
.navigationBarsPadding()
|
||||||
){
|
){
|
||||||
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)})
|
||||||
composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)})
|
composable(route = "Permissions", content = { DpmPermissions(mainDpm,mainComponent,mainContext,navCtrl)})
|
||||||
composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)})
|
composable(route = "ApplicationManage", content = { ApplicationManage(mainDpm,mainComponent,mainContext)})
|
||||||
composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent)})
|
composable(route = "UserRestriction", content = { UserRestriction(mainDpm,mainComponent)})
|
||||||
|
composable(route = "Security", content = { Security(mainDpm,mainComponent,mainContext)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,10 +178,10 @@ fun HomePage(navCtrl:NavHostController,myDpm:DevicePolicyManager,myComponent:Com
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//HomePageItem(R.string.permission, R.drawable.security_fill0, R.string.permission_desc, "Permissions", navCtrl)
|
|
||||||
HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, R.string.device_ctrl_desc, "DeviceControl", navCtrl)
|
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.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.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
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.provider.Settings.Global
|
import android.os.Build.VERSION
|
||||||
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
|
||||||
@@ -30,7 +30,6 @@ 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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.app.ActivityCompat.startActivityForResult
|
|
||||||
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
|
||||||
@@ -130,7 +129,8 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
|
|||||||
Text("使用此命令也会激活Device Admin")
|
Text("使用此命令也会激活Device Admin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isdo){
|
}
|
||||||
|
if(isdo&&VERSION.SDK_INT>=24){
|
||||||
var lockScrInfo by remember { mutableStateOf("") }
|
var lockScrInfo by remember { mutableStateOf("") }
|
||||||
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
|
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
|
||||||
Spacer(Modifier.padding(5.dp))
|
Spacer(Modifier.padding(5.dp))
|
||||||
@@ -139,8 +139,6 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ActivateDeviceAdmin(myDpm: DevicePolicyManager,myComponent: ComponentName,myContext: Context){
|
fun ActivateDeviceAdmin(myDpm: DevicePolicyManager,myComponent: ComponentName,myContext: Context){
|
||||||
|
|||||||
@@ -1,25 +1,185 @@
|
|||||||
package com.binbin.androidowner
|
package com.binbin.androidowner
|
||||||
|
|
||||||
|
import android.app.KeyguardManager
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
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.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
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.unit.dp
|
||||||
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName){
|
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Context){
|
||||||
Column {
|
var newPwd by remember{ mutableStateOf("") }
|
||||||
Button(onClick = {myDpm.clearResetPasswordToken(myComponent)}) {
|
var confirmed by remember{ mutableStateOf(false) }
|
||||||
Text("清除重置密码令牌")
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
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)) }
|
||||||
|
if(VERSION.SDK_INT>=26){
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.Start,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
.clip(RoundedCornerShape(10))
|
||||||
|
.background(color = MaterialTheme.colorScheme.primaryContainer)
|
||||||
|
.padding(8.dp)
|
||||||
|
) {
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
Button(onClick = {myDpm.setResetPasswordToken(myComponent, byteArrayOf(32))}) {
|
},
|
||||||
Text("设置重置密码令牌")
|
modifier = Modifier.padding(end = 8.dp)
|
||||||
|
) {
|
||||||
|
Text("清除")
|
||||||
}
|
}
|
||||||
Text("不知道上面两个东西干啥用的")
|
Button(
|
||||||
Button(onClick = {myDpm.resetPassword(null,0)}) {
|
onClick = {
|
||||||
Text("清除密码")
|
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)
|
||||||
|
) {
|
||||||
|
Text("设置")
|
||||||
|
}
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
) {
|
||||||
|
Text("激活")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text("没有密码时会自动激活令牌")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField(
|
||||||
|
value = newPwd,
|
||||||
|
onValueChange = {newPwd=it},
|
||||||
|
enabled = !confirmed,
|
||||||
|
label = { Text("密码")}
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "(留空可以清除密码)",
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(end = 10.dp)
|
||||||
|
) {
|
||||||
|
Text("确认密码")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT>=26){
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
confirmed=false
|
||||||
|
},
|
||||||
|
enabled = confirmed,
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.error,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onError
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("设置密码")
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
confirmed=false
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.error,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onError
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("设置密码")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = "该操作可能会造成不可挽回的损失,请先备份好数据。设置密码的时候一定要谨慎!!!",
|
||||||
|
color = MaterialTheme.colorScheme.onErrorContainer,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
.clip(RoundedCornerShape(15))
|
||||||
|
.background(color = MaterialTheme.colorScheme.errorContainer)
|
||||||
|
.padding(8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun activateToken(myContext: Context){
|
||||||
|
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
|
||||||
|
val keyguardManager = myContext.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)
|
||||||
|
confirmIntent.setFlags(FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
if (confirmIntent != null) {
|
||||||
|
startActivity(myContext,confirmIntent, null)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(myContext, "激活失败", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
app/src/main/java/com/binbin/androidowner/Test.java
Normal file
46
app/src/main/java/com/binbin/androidowner/Test.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package com.binbin.androidowner;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentSender;
|
||||||
|
import android.content.pm.PackageInstaller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public static void installPackage(Context context, InputStream inputStream)
|
||||||
|
throws IOException {
|
||||||
|
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
|
||||||
|
int sessionId = packageInstaller.createSession(new PackageInstaller
|
||||||
|
.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
|
||||||
|
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
|
||||||
|
|
||||||
|
long sizeBytes = 0;
|
||||||
|
|
||||||
|
OutputStream out;
|
||||||
|
out = session.openWrite("my_app_session", 0, sizeBytes);
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
byte[] buffer = new byte[65536];
|
||||||
|
int c;
|
||||||
|
while ((c = inputStream.read(buffer)) != -1) {
|
||||||
|
total += c;
|
||||||
|
out.write(buffer, 0, c);
|
||||||
|
}
|
||||||
|
session.fsync(out);
|
||||||
|
inputStream.close();
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
// fake intent
|
||||||
|
IntentSender statusReceiver = null;
|
||||||
|
Intent intent = new Intent(context, MainActivity.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
|
||||||
|
1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
session.commit(pendingIntent.getIntentSender());
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package com.binbin.androidowner
|
|||||||
|
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.os.Build
|
import android.os.Build.VERSION
|
||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -34,15 +34,19 @@ import androidx.compose.ui.unit.dp
|
|||||||
fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
||||||
val verticalScrolling = rememberScrollState()
|
val verticalScrolling = rememberScrollState()
|
||||||
Column(
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.verticalScroll(verticalScrolling)
|
.verticalScroll(verticalScrolling)
|
||||||
.padding(bottom = 20.dp)
|
.padding(bottom = 20.dp)
|
||||||
) {
|
) {
|
||||||
|
Text("打开开关后会禁用对应的功能")
|
||||||
UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,R.string.config_mobile_network,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_CONFIG_WIFI,R.string.config_wifi,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CONFIG_WIFI,R.string.config_wifi,"",myComponent, myDpm)
|
||||||
|
if(VERSION.SDK_INT>=26){
|
||||||
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
|
||||||
if(Build.VERSION.SDK_INT>=28){
|
}
|
||||||
|
if(VERSION.SDK_INT>=28){
|
||||||
UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_AIRPLANE_MODE,R.string.airplane_mode,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CONFIG_LOCATION,R.string.config_location,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CONFIG_BRIGHTNESS,R.string.config_brightness,"",myComponent, myDpm)
|
||||||
@@ -51,17 +55,23 @@ fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
|||||||
UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CREATE_WINDOWS,R.string.create_windows, stringResource(R.string.create_windows_description),myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_ADJUST_VOLUME,R.string.adjust_volume,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_ADJUST_VOLUME,R.string.adjust_volume,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_INSTALL_APPS,R.string.install_apps,"",myComponent, myDpm)
|
||||||
if(Build.VERSION.SDK_INT>=31){
|
if(VERSION.SDK_INT>=31){
|
||||||
UserRestrictionItem(UserManager.DISALLOW_CAMERA_TOGGLE,R.string.camera_toggle,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_CAMERA_TOGGLE,R.string.camera_toggle,"",myComponent, myDpm)
|
||||||
}
|
}
|
||||||
UserRestrictionItem(UserManager.DISALLOW_SMS,R.string.sms,"",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_SMS,R.string.sms,"",myComponent, myDpm)
|
||||||
UserRestrictionItem(UserManager.DISALLOW_APPS_CONTROL,R.string.apps_ctrl, stringResource(R.string.apps_ctrl_description),myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_APPS_CONTROL,R.string.apps_ctrl, stringResource(R.string.apps_ctrl_description),myComponent, myDpm)
|
||||||
|
if(VERSION.SDK_INT>=26){
|
||||||
UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
|
UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
|
||||||
if(Build.VERSION.SDK_INT<28){
|
}
|
||||||
|
UserRestrictionItem(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,R.string.inst_unknown_src,"",myComponent, myDpm)
|
||||||
|
if(VERSION.SDK_INT<26){
|
||||||
|
Text("以下功能需要安卓8或以上:蓝牙、自动填充服务")
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT<28){
|
||||||
Text("以下功能需要安卓9或以上:飞行模式、位置信息、调整亮度")
|
Text("以下功能需要安卓9或以上:飞行模式、位置信息、调整亮度")
|
||||||
}
|
}
|
||||||
if(Build.VERSION.SDK_INT<31){
|
if(VERSION.SDK_INT<31){
|
||||||
Text("以下功能需要安卓12或以上:相机切换")
|
Text("以下功能需要安卓12或以上:切换相机")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,9 +108,10 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
|
|||||||
if(restrictionDescription!=""){Text(restrictionDescription)}
|
if(restrictionDescription!=""){Text(restrictionDescription)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isdo){
|
if(isdo&&VERSION.SDK_INT>=24){
|
||||||
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
||||||
}
|
}
|
||||||
|
if(VERSION.SDK_INT>=24){
|
||||||
Switch(
|
Switch(
|
||||||
checked = strictState,
|
checked = strictState,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
@@ -111,8 +122,12 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
|
|||||||
myDpm.clearUserRestriction(myComponent,restriction)
|
myDpm.clearUserRestriction(myComponent,restriction)
|
||||||
}
|
}
|
||||||
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
||||||
|
|
||||||
},
|
},
|
||||||
enabled = isdo
|
enabled = isdo
|
||||||
)
|
)
|
||||||
|
}else{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,10 @@
|
|||||||
<string name="suspend">停用</string>
|
<string name="suspend">停用</string>
|
||||||
<string name="block_unins">防卸载</string>
|
<string name="block_unins">防卸载</string>
|
||||||
<string name="isapphidden_desc">如果隐藏,有可能是没安装</string>
|
<string name="isapphidden_desc">如果隐藏,有可能是没安装</string>
|
||||||
<string name="sometimes_not_avaliable">有时候不能用</string>
|
<string name="sometimes_not_available">有时候不能用</string>
|
||||||
<string name="user_ctrl_disabled">禁止用户控制</string>
|
<string name="user_ctrl_disabled">禁止用户控制</string>
|
||||||
<string name="user_ctrl_disabled_desc">阻止清除应用数据和缓存</string>>
|
<string name="user_ctrl_disabled_desc">阻止清除应用数据和缓存</string>
|
||||||
|
<string name="security">安全</string>
|
||||||
|
<string name="inst_unknown_src">安装未知来源应用</string>
|
||||||
|
<string name="security_desc">修改或清除锁屏密码</string>>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user