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:
@@ -2,6 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<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
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.binbin.androidowner
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import android.net.Uri
|
||||
import android.os.Build.VERSION
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
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.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
|
||||
|
||||
@Composable
|
||||
@@ -47,32 +51,46 @@ fun ApplicationManage(myDpm:DevicePolicyManager, myComponent:ComponentName,myCon
|
||||
},
|
||||
label = { Text("包名") }
|
||||
)
|
||||
val isSuspended = {
|
||||
try{
|
||||
myDpm.isPackageSuspended(myComponent,pkgName)
|
||||
}catch(e:NameNotFoundException){
|
||||
false
|
||||
if(VERSION.SDK_INT>=24){
|
||||
val isSuspended = {
|
||||
try{
|
||||
myDpm.isPackageSuspended(myComponent,pkgName)
|
||||
}catch(e:NameNotFoundException){
|
||||
false
|
||||
}
|
||||
}
|
||||
AppManageItem(R.string.suspend,R.string.place_holder,myDpm, isSuspended,
|
||||
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
|
||||
}
|
||||
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,
|
||||
{b -> myDpm.setPackagesSuspended(myComponent, arrayOf(pkgName) ,b)})
|
||||
/*AppManageItem(R.string.block_unins,R.string.sometimes_not_avaliable,myDpm, {myDpm.isUninstallBlocked(myComponent,pkgName)},
|
||||
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)})*/
|
||||
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)}) {
|
||||
Text("取消防卸载")
|
||||
}
|
||||
Spacer(Modifier.padding(horizontal = 2.dp))
|
||||
Button(onClick = {myDpm.setUninstallBlocked(myComponent,pkgName,true)}) {
|
||||
Text("防卸载")
|
||||
}
|
||||
}
|
||||
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}))})
|
||||
Button(
|
||||
onClick = {
|
||||
uninstallApp(myContext,pkgName)
|
||||
}) {
|
||||
Text("卸载")
|
||||
}
|
||||
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)
|
||||
@Composable
|
||||
fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
||||
val wifimac = try {
|
||||
myDpm.getWifiMacAddress(myComponent).toString()
|
||||
}catch(e:SecurityException){
|
||||
"没有权限"
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.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.master_mute,R.string.place_holder,myDpm,{myDpm.isMasterVolumeMuted(myComponent)},{b -> myDpm.setMasterVolumeMuted(myComponent,b) })
|
||||
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
|
||||
Text("隐藏状态栏需要API34")
|
||||
Text("自动设置时间和自动设置时区需要API30")
|
||||
Button(onClick = {myDpm.reboot(myComponent)}) {
|
||||
Text("重启")
|
||||
if(VERSION.SDK_INT>=26){
|
||||
DeviceCtrlItem(R.string.backup_service,R.string.place_holder,myDpm,{myDpm.isBackupServiceEnabled(myComponent)},{b -> myDpm.setBackupServiceEnabled(myComponent,b) })
|
||||
}
|
||||
if(VERSION.SDK_INT>=24){
|
||||
Button(onClick = {myDpm.reboot(myComponent)}) {
|
||||
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()}) {
|
||||
Text("锁屏")
|
||||
}
|
||||
Text("WiFi MAC: $wifimac")
|
||||
Text("以下功能需要长按按钮,作者并未测试")
|
||||
Button(
|
||||
onClick = {},
|
||||
@@ -76,7 +90,7 @@ fun DeviceControl(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
||||
) {
|
||||
Text("WipeData")
|
||||
}
|
||||
if (VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
if (VERSION.SDK_INT >= 34) {
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.combinedClickable(onClick = {}, onLongClick = {myDpm.wipeDevice(0)}),
|
||||
|
||||
@@ -85,7 +85,8 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
|
||||
"Permissions" to R.string.permission,
|
||||
"UIControl" to R.string.ui_ctrl,
|
||||
"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
|
||||
Scaffold(
|
||||
@@ -125,13 +126,16 @@ fun MyScaffold(mainDpm:DevicePolicyManager, mainComponent:ComponentName, mainCon
|
||||
NavHost(
|
||||
navController = navCtrl,
|
||||
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 = "DeviceControl", content = { DeviceControl(mainDpm,mainComponent)})
|
||||
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)})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
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.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -30,7 +30,6 @@ 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.app.ActivityCompat.startActivityForResult
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
@@ -130,16 +129,15 @@ fun DpmPermissions(myDpm: DevicePolicyManager, myComponent: ComponentName, myCon
|
||||
Text("使用此命令也会激活Device Admin")
|
||||
}
|
||||
}
|
||||
if(isdo){
|
||||
var lockScrInfo by remember { mutableStateOf("") }
|
||||
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
|
||||
Spacer(Modifier.padding(5.dp))
|
||||
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
|
||||
Text("设置锁屏DeviceOwner信息")
|
||||
}
|
||||
}
|
||||
if(isdo&&VERSION.SDK_INT>=24){
|
||||
var lockScrInfo by remember { mutableStateOf("") }
|
||||
TextField(value = lockScrInfo, onValueChange = { lockScrInfo= it}, label = { Text("锁屏信息") })
|
||||
Spacer(Modifier.padding(5.dp))
|
||||
Button(onClick = {myDpm.setDeviceOwnerLockScreenInfo(myComponent,lockScrInfo)}) {
|
||||
Text("设置锁屏DeviceOwner信息")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,185 @@
|
||||
package com.binbin.androidowner
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.app.admin.DevicePolicyManager
|
||||
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.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.ButtonDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
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
|
||||
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName){
|
||||
Column {
|
||||
Button(onClick = {myDpm.clearResetPasswordToken(myComponent)}) {
|
||||
Text("清除重置密码令牌")
|
||||
fun Security(myDpm:DevicePolicyManager,myComponent:ComponentName,myContext:Context){
|
||||
var newPwd by remember{ mutableStateOf("") }
|
||||
var confirmed by remember{ mutableStateOf(false) }
|
||||
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()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
) {
|
||||
Text("清除")
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
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("没有密码时会自动激活令牌")
|
||||
}
|
||||
}
|
||||
Button(onClick = {myDpm.setResetPasswordToken(myComponent, byteArrayOf(32))}) {
|
||||
Text("设置重置密码令牌")
|
||||
}
|
||||
Text("不知道上面两个东西干啥用的")
|
||||
Button(onClick = {myDpm.resetPassword(null,0)}) {
|
||||
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.content.ComponentName
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION
|
||||
import android.os.UserManager
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -34,15 +34,19 @@ import androidx.compose.ui.unit.dp
|
||||
fun UserRestriction(myDpm: DevicePolicyManager, myComponent: ComponentName){
|
||||
val verticalScrolling = rememberScrollState()
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.verticalScroll(verticalScrolling)
|
||||
.padding(bottom = 20.dp)
|
||||
) {
|
||||
Text("打开开关后会禁用对应的功能")
|
||||
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_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
|
||||
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
|
||||
if(Build.VERSION.SDK_INT>=28){
|
||||
if(VERSION.SDK_INT>=26){
|
||||
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH,R.string.bluetooth,"",myComponent, myDpm)
|
||||
UserRestrictionItem(UserManager.DISALLOW_BLUETOOTH_SHARING,R.string.bt_share,"",myComponent, myDpm)
|
||||
}
|
||||
if(VERSION.SDK_INT>=28){
|
||||
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_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_ADJUST_VOLUME,R.string.adjust_volume,"",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_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_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
|
||||
if(Build.VERSION.SDK_INT<28){
|
||||
if(VERSION.SDK_INT>=26){
|
||||
UserRestrictionItem(UserManager.DISALLOW_AUTOFILL,R.string.autofill, "",myComponent, myDpm)
|
||||
}
|
||||
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或以上:飞行模式、位置信息、调整亮度")
|
||||
}
|
||||
if(Build.VERSION.SDK_INT<31){
|
||||
Text("以下功能需要安卓12或以上:相机切换")
|
||||
if(VERSION.SDK_INT<31){
|
||||
Text("以下功能需要安卓12或以上:切换相机")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,21 +108,26 @@ private fun UserRestrictionItem(restriction:String, itemName:Int, restrictionDes
|
||||
if(restrictionDescription!=""){Text(restrictionDescription)}
|
||||
}
|
||||
}
|
||||
if(isdo){
|
||||
if(isdo&&VERSION.SDK_INT>=24){
|
||||
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
||||
}
|
||||
Switch(
|
||||
checked = strictState,
|
||||
onCheckedChange = {
|
||||
strictState=it
|
||||
if(strictState){
|
||||
myDpm.addUserRestriction(myComponent,restriction)
|
||||
}else{
|
||||
myDpm.clearUserRestriction(myComponent,restriction)
|
||||
}
|
||||
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
||||
},
|
||||
enabled = isdo
|
||||
)
|
||||
if(VERSION.SDK_INT>=24){
|
||||
Switch(
|
||||
checked = strictState,
|
||||
onCheckedChange = {
|
||||
strictState=it
|
||||
if(strictState){
|
||||
myDpm.addUserRestriction(myComponent,restriction)
|
||||
}else{
|
||||
myDpm.clearUserRestriction(myComponent,restriction)
|
||||
}
|
||||
strictState = myDpm.getUserRestrictions(myComponent).getBoolean(restriction)
|
||||
|
||||
},
|
||||
enabled = isdo
|
||||
)
|
||||
}else{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@
|
||||
<string name="suspend">停用</string>
|
||||
<string name="block_unins">防卸载</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_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>
|
||||
Reference in New Issue
Block a user