mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
permission picker in AppManage
This commit is contained in:
2
Guide.md
2
Guide.md
@@ -691,7 +691,7 @@ adb shell pm list permissions
|
||||
|
||||
从允许或拒绝改为由用户决定会保持当前的状态
|
||||
|
||||
有一些权限无法修改,比如安装应用
|
||||
只能修改运行时权限(可以通过对话框授权的权限)
|
||||
|
||||
在API31或以上,Profile owner不能再修改传感器相关权限,如果能修改传感器相关权限,说明这个设备是完全受管理设备(Device owner)
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ _我正在为这个App取一个新的名字......_
|
||||
|
||||
### 正在开发的功能
|
||||
|
||||
- 应用管理:应用权限选择器(现在只能手动输入权限名称)
|
||||
- 用户管理:用户选择器(现在只能手动输入用户序列号)
|
||||
- 安全日志和网络日志
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId = "com.binbin.androidowner"
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 22
|
||||
versionName = "4.5"
|
||||
versionCode = 23
|
||||
versionName = "4.6"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
||||
@@ -108,6 +108,7 @@ fun MyScaffold(){
|
||||
composable(route = "AppSetting", content = { AppSetting(navCtrl)})
|
||||
composable(route = "Network", content = {Network(navCtrl)})
|
||||
composable(route = "PackageSelector"){PackageSelector(navCtrl)}
|
||||
composable(route = "PermissionPicker"){PermissionPicker(navCtrl)}
|
||||
}
|
||||
LaunchedEffect(Unit){
|
||||
val profileInited = sharedPref.getBoolean("ManagedProfileActivated",false)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.binbin.androidowner
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build.VERSION
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import com.binbin.androidowner.dpm.applySelectedPermission
|
||||
import com.binbin.androidowner.dpm.selectedPermission
|
||||
import com.binbin.androidowner.ui.NavIcon
|
||||
import com.binbin.androidowner.ui.theme.bgColor
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PermissionPicker(navCtrl: NavHostController){
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {Text(text = stringResource(R.string.permission_picker))},
|
||||
navigationIcon = {NavIcon{navCtrl.navigateUp()}},
|
||||
colors = TopAppBarDefaults.topAppBarColors(containerColor = bgColor)
|
||||
)
|
||||
}
|
||||
){ paddingValues->
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize().padding(top = paddingValues.calculateTopPadding()).background(bgColor)
|
||||
){
|
||||
items(permissionList()){
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable{
|
||||
selectedPermission = it.first
|
||||
applySelectedPermission = true
|
||||
navCtrl.navigateUp()
|
||||
}
|
||||
.padding(vertical = 6.dp, horizontal = 8.dp)
|
||||
){
|
||||
Text(text = it.first)
|
||||
Text(text = stringResource(it.second), modifier = Modifier.alpha(0.8F))
|
||||
}
|
||||
}
|
||||
items(1){ Spacer(Modifier.padding(vertical = 30.dp)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun permissionList():List<Pair<String,Int>>{
|
||||
val list = mutableListOf<Pair<String,Int>>()
|
||||
list.add(Pair(Manifest.permission.READ_EXTERNAL_STORAGE,R.string.permission_READ_EXTERNAL_STORAGE))
|
||||
list.add(Pair(Manifest.permission.WRITE_EXTERNAL_STORAGE,R.string.permission_WRITE_EXTERNAL_STORAGE))
|
||||
if(VERSION.SDK_INT>=33){
|
||||
list.add(Pair(Manifest.permission.READ_MEDIA_AUDIO,R.string.permission_READ_MEDIA_AUDIO))
|
||||
list.add(Pair(Manifest.permission.READ_MEDIA_VIDEO,R.string.permission_READ_MEDIA_VIDEO))
|
||||
list.add(Pair(Manifest.permission.READ_MEDIA_IMAGES,R.string.permission_READ_MEDIA_IMAGES))
|
||||
}
|
||||
list.add(Pair(Manifest.permission.CAMERA,R.string.permission_CAMERA))
|
||||
list.add(Pair(Manifest.permission.RECORD_AUDIO,R.string.permission_RECORD_AUDIO))
|
||||
list.add(Pair(Manifest.permission.ACCESS_COARSE_LOCATION,R.string.permission_ACCESS_COARSE_LOCATION))
|
||||
list.add(Pair(Manifest.permission.ACCESS_FINE_LOCATION,R.string.permission_ACCESS_FINE_LOCATION))
|
||||
if(VERSION.SDK_INT>=29){
|
||||
list.add(Pair(Manifest.permission.ACCESS_BACKGROUND_LOCATION,R.string.permission_ACCESS_BACKGROUND_LOCATION))
|
||||
}
|
||||
list.add(Pair(Manifest.permission.READ_CONTACTS,R.string.permission_READ_CONTACTS))
|
||||
list.add(Pair(Manifest.permission.WRITE_CONTACTS,R.string.permission_WRITE_CONTACTS))
|
||||
list.add(Pair(Manifest.permission.READ_CALENDAR,R.string.permission_READ_CALENDAR))
|
||||
list.add(Pair(Manifest.permission.WRITE_CALENDAR,R.string.permission_WRITE_CALENDAR))
|
||||
list.add(Pair(Manifest.permission.CALL_PHONE,R.string.permission_CALL_PHONE))
|
||||
list.add(Pair(Manifest.permission.READ_PHONE_STATE,R.string.permission_READ_PHONE_STATE))
|
||||
list.add(Pair(Manifest.permission.READ_SMS,R.string.permission_READ_SMS))
|
||||
list.add(Pair(Manifest.permission.RECEIVE_SMS,R.string.permission_RECEIVE_SMS))
|
||||
list.add(Pair(Manifest.permission.SEND_SMS,R.string.permission_SEND_SMS))
|
||||
list.add(Pair(Manifest.permission.READ_CALL_LOG,R.string.permission_READ_CALL_LOG))
|
||||
list.add(Pair(Manifest.permission.WRITE_CALL_LOG,R.string.permission_WRITE_CALL_LOG))
|
||||
list.add(Pair(Manifest.permission.BODY_SENSORS,R.string.permission_BODY_SENSORS))
|
||||
if(VERSION.SDK_INT>=33){
|
||||
list.add(Pair(Manifest.permission.BODY_SENSORS_BACKGROUND,R.string.permission_BODY_SENSORS_BACKGROUND))
|
||||
}
|
||||
if(VERSION.SDK_INT>29){
|
||||
list.add(Pair(Manifest.permission.ACTIVITY_RECOGNITION,R.string.permission_ACTIVITY_RECOGNITION))
|
||||
}
|
||||
if(VERSION.SDK_INT>=33){
|
||||
list.add(Pair(Manifest.permission.POST_NOTIFICATIONS,R.string.permission_POST_NOTIFICATIONS))
|
||||
}
|
||||
//list.add(Pair(Manifest.permission.,R.string.))
|
||||
return list
|
||||
}
|
||||
@@ -152,6 +152,7 @@ fun PackageSelector(navCtrl:NavHostController){
|
||||
PackageItem(it, navCtrl)
|
||||
}
|
||||
}
|
||||
items(1){Spacer(Modifier.padding(vertical = 30.dp))}
|
||||
}else{
|
||||
items(1){
|
||||
Spacer(Modifier.padding(top = 5.dp))
|
||||
|
||||
@@ -64,6 +64,7 @@ private var crossProfilePkg = mutableSetOf<String>()
|
||||
private var keepUninstallPkg = mutableListOf<String>()
|
||||
private var permittedIme = mutableListOf<String>()
|
||||
private var permittedAccessibility = mutableListOf<String>()
|
||||
|
||||
@Composable
|
||||
fun ApplicationManage(navCtrl:NavHostController){
|
||||
val focusMgr = LocalFocusManager.current
|
||||
@@ -98,8 +99,8 @@ fun ApplicationManage(navCtrl:NavHostController){
|
||||
Column(modifier = Modifier.fillMaxSize().padding(top = paddingValues.calculateTopPadding())){
|
||||
LaunchedEffect(Unit) {
|
||||
while(true){
|
||||
if(applySelectedPackage){pkgName = selectedPackage; applySelectedPackage = false}
|
||||
delay(200)
|
||||
if(applySelectedPackage){ pkgName = selectedPackage; applySelectedPackage = false; applySelectedPermission = true}
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
if(backStackEntry?.destination?.route!="InstallApp"){
|
||||
@@ -131,7 +132,7 @@ fun ApplicationManage(navCtrl:NavHostController){
|
||||
composable(route = "Home"){Home(localNavCtrl,pkgName)}
|
||||
composable(route = "BlockUninstall"){BlockUninstall(pkgName)}
|
||||
composable(route = "UserControlDisabled"){UserCtrlDisabledPkg(pkgName)}
|
||||
composable(route = "PermissionManage"){PermissionManage(pkgName)}
|
||||
composable(route = "PermissionManage"){PermissionManage(pkgName,navCtrl)}
|
||||
composable(route = "CrossProfilePackage"){CrossProfilePkg(pkgName)}
|
||||
composable(route = "CrossProfileWidget"){CrossProfileWidget(pkgName)}
|
||||
composable(route = "CredentialManagePolicy"){CredentialManagePolicy(pkgName)}
|
||||
@@ -155,8 +156,7 @@ private fun Home(navCtrl:NavHostController, pkgName: String){
|
||||
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
|
||||
Text(text = stringResource(R.string.scope_is_work_profile), textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp))
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Text(text = stringResource(R.string.scope_is_work_profile), textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth())
|
||||
}
|
||||
SubPageItem(R.string.app_info,"",R.drawable.open_in_new){
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
@@ -343,38 +343,57 @@ private fun BlockUninstall(pkgName: String){
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
private fun PermissionManage(pkgName: String){
|
||||
private fun PermissionManage(pkgName: String, navCtrl: NavHostController){
|
||||
val myContext = LocalContext.current
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var inputPermission by remember{mutableStateOf(selectedPermission)}
|
||||
var currentState by remember{mutableStateOf(myContext.getString(R.string.unknown))}
|
||||
val grantState = mapOf(
|
||||
PERMISSION_GRANT_STATE_DEFAULT to stringResource(R.string.decide_by_user),
|
||||
PERMISSION_GRANT_STATE_GRANTED to stringResource(R.string.granted),
|
||||
PERMISSION_GRANT_STATE_DENIED to stringResource(R.string.denied)
|
||||
)
|
||||
LaunchedEffect(Unit) {
|
||||
while(true){
|
||||
if(applySelectedPermission){inputPermission = selectedPermission; applySelectedPermission = false}
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
LaunchedEffect(pkgName) {
|
||||
if(pkgName!=""){currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]!!}
|
||||
}
|
||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
||||
var inputPermission by remember{mutableStateOf("android.permission.")}
|
||||
var currentState by remember{mutableStateOf(grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)])}
|
||||
Spacer(Modifier.padding(vertical = 10.dp))
|
||||
Text(text = stringResource(R.string.permission_manage), style = typography.headlineLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
OutlinedTextField(
|
||||
value = inputPermission,
|
||||
label = { Text(stringResource(R.string.permission))},
|
||||
onValueChange = {inputPermission = it},
|
||||
onValueChange = {
|
||||
inputPermission = it; selectedPermission = inputPermission
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]!!
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
||||
modifier = Modifier.focusable().fillMaxWidth()
|
||||
modifier = Modifier.focusable().fillMaxWidth(),
|
||||
trailingIcon = {
|
||||
Icon(painter = painterResource(R.drawable.checklist_fill0), contentDescription = null,
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(50))
|
||||
.clickable(onClick = {navCtrl.navigate("PermissionPicker")})
|
||||
.padding(3.dp))
|
||||
}
|
||||
)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Text(stringResource(R.string.current_state, currentState?:stringResource(R.string.unknown)))
|
||||
Text(stringResource(R.string.current_state, currentState))
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setPermissionGrantState(myComponent,pkgName,inputPermission, PERMISSION_GRANT_STATE_GRANTED)
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]!!
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(0.49F)
|
||||
) {
|
||||
@@ -383,7 +402,7 @@ private fun PermissionManage(pkgName: String){
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setPermissionGrantState(myComponent,pkgName,inputPermission, PERMISSION_GRANT_STATE_DENIED)
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]!!
|
||||
},
|
||||
Modifier.fillMaxWidth(0.96F)
|
||||
) {
|
||||
@@ -393,7 +412,7 @@ private fun PermissionManage(pkgName: String){
|
||||
Button(
|
||||
onClick = {
|
||||
myDpm.setPermissionGrantState(myComponent,pkgName,inputPermission, PERMISSION_GRANT_STATE_DEFAULT)
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]
|
||||
currentState = grantState[myDpm.getPermissionGrantState(myComponent,pkgName,inputPermission)]!!
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
@@ -410,6 +429,7 @@ private fun CrossProfilePkg(pkgName: String){
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
|
||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
||||
Spacer(Modifier.padding(vertical = 10.dp))
|
||||
Text(text = stringResource(R.string.cross_profile_package), style = typography.headlineLarge)
|
||||
var list by remember{mutableStateOf("")}
|
||||
val refresh = {
|
||||
|
||||
@@ -7,6 +7,8 @@ import androidx.activity.result.ActivityResultLauncher
|
||||
|
||||
var selectedPackage = ""
|
||||
var applySelectedPackage = false
|
||||
var selectedPermission = ""
|
||||
var applySelectedPermission = false
|
||||
lateinit var getCaCert: ActivityResultLauncher<Intent>
|
||||
lateinit var createManagedProfile: ActivityResultLauncher<Intent>
|
||||
lateinit var getApk: ActivityResultLauncher<Intent>
|
||||
|
||||
@@ -244,6 +244,7 @@
|
||||
<string name="show_system_app">显示系统应用</string>
|
||||
<string name="show_priv_app">显示priv-app</string>
|
||||
<string name="show_apex_app">显示apex应用</string>
|
||||
<string name="permission_picker">权限选择器</string>
|
||||
<string name="suspend">挂起</string>
|
||||
<string name="hide">隐藏</string>
|
||||
<string name="isapphidden_desc">如果隐藏,有可能是没安装</string>
|
||||
@@ -472,4 +473,31 @@
|
||||
<string name="blackTheme_desc">需要打开夜间模式</string>
|
||||
<string name="need_relaunch">需要重启应用</string>
|
||||
|
||||
<!--AndroidPermission-->
|
||||
<string name="permission_READ_EXTERNAL_STORAGE">读取外部存储</string>
|
||||
<string name="permission_WRITE_EXTERNAL_STORAGE">写入外部存储</string>
|
||||
<string name="permission_READ_MEDIA_AUDIO">读取音频</string>
|
||||
<string name="permission_READ_MEDIA_VIDEO">读取视频</string>
|
||||
<string name="permission_READ_MEDIA_IMAGES">读取图片</string>
|
||||
<string name="permission_CAMERA">相机</string>
|
||||
<string name="permission_RECORD_AUDIO">录音</string>
|
||||
<string name="permission_READ_CONTACTS">读取联系人</string>
|
||||
<string name="permission_WRITE_CONTACTS">写入联系人</string>
|
||||
<string name="permission_READ_CALENDAR">读取日历</string>
|
||||
<string name="permission_WRITE_CALENDAR">写入日历</string>
|
||||
<string name="permission_ACCESS_COARSE_LOCATION">粗略位置</string>
|
||||
<string name="permission_ACCESS_FINE_LOCATION">准确位置</string>
|
||||
<string name="permission_ACCESS_BACKGROUND_LOCATION">后台获取位置</string>
|
||||
<string name="permission_CALL_PHONE">打电话</string>
|
||||
<string name="permission_READ_PHONE_STATE">读取手机状态</string>
|
||||
<string name="permission_READ_SMS">读取短信</string>
|
||||
<string name="permission_RECEIVE_SMS">接收短信</string>
|
||||
<string name="permission_SEND_SMS">发送短信</string>
|
||||
<string name="permission_READ_CALL_LOG">读取通话记录</string>
|
||||
<string name="permission_WRITE_CALL_LOG">写入通话记录</string>
|
||||
<string name="permission_BODY_SENSORS">传感器</string>
|
||||
<string name="permission_BODY_SENSORS_BACKGROUND">后台使用传感器</string>
|
||||
<string name="permission_ACTIVITY_RECOGNITION">查看使用情况</string>
|
||||
<string name="permission_POST_NOTIFICATIONS">发送通知</string>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user