mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
545 lines
26 KiB
Kotlin
545 lines
26 KiB
Kotlin
package com.bintianqi.owndroid.dpm
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.app.admin.DevicePolicyManager
|
|
import android.content.ComponentName
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.graphics.BitmapFactory
|
|
import android.os.Binder
|
|
import android.os.Build.VERSION
|
|
import android.os.Process
|
|
import android.os.UserHandle
|
|
import android.os.UserManager
|
|
import android.provider.MediaStore
|
|
import android.widget.Toast
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.compose.animation.AnimatedVisibility
|
|
import androidx.compose.foundation.*
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
|
import androidx.compose.material3.Button
|
|
import androidx.compose.material3.MaterialTheme.typography
|
|
import androidx.compose.material3.OutlinedTextField
|
|
import androidx.compose.material3.Scaffold
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.draw.alpha
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.core.os.UserManagerCompat
|
|
import androidx.navigation.NavHostController
|
|
import androidx.navigation.compose.NavHost
|
|
import androidx.navigation.compose.composable
|
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
import androidx.navigation.compose.rememberNavController
|
|
import com.bintianqi.owndroid.*
|
|
import com.bintianqi.owndroid.R
|
|
import com.bintianqi.owndroid.ui.*
|
|
import kotlinx.coroutines.delay
|
|
|
|
var affiliationID = mutableSetOf<String>()
|
|
@Composable
|
|
fun UserManage(navCtrl:NavHostController) {
|
|
val localNavCtrl = rememberNavController()
|
|
val backStackEntry by localNavCtrl.currentBackStackEntryAsState()
|
|
val scrollState = rememberScrollState()
|
|
/*val titleMap = mapOf(
|
|
"UserInfo" to R.string.user_info,
|
|
"UserOperation" to R.string.user_operation,
|
|
"CreateUser" to R.string.create_user,
|
|
"EditUsername" to R.string.edit_username,
|
|
"ChangeUserIcon" to R.string.change_user_icon,
|
|
"UserSessionMessage" to R.string.user_session_msg,
|
|
"AffiliationID" to R.string.affiliation_id,
|
|
)*/
|
|
Scaffold(
|
|
topBar = {
|
|
/*TopAppBar(
|
|
title = {Text(text = stringResource(titleMap[backStackEntry?.destination?.route]?:R.string.user_manage))},
|
|
navigationIcon = {NavIcon{if(backStackEntry?.destination?.route=="Home"){navCtrl.navigateUp()}else{localNavCtrl.navigateUp()}}},
|
|
colors = TopAppBarDefaults.topAppBarColors(containerColor = colorScheme.surfaceVariant)
|
|
)*/
|
|
TopBar(backStackEntry,navCtrl,localNavCtrl){
|
|
if(backStackEntry?.destination?.route=="Home"&&scrollState.maxValue>80){
|
|
Text(
|
|
text = stringResource(R.string.user_manager),
|
|
modifier = Modifier.alpha((maxOf(scrollState.value-30,0)).toFloat()/80)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
){
|
|
NavHost(
|
|
navController = localNavCtrl, startDestination = "Home",
|
|
enterTransition = Animations.navHostEnterTransition,
|
|
exitTransition = Animations.navHostExitTransition,
|
|
popEnterTransition = Animations.navHostPopEnterTransition,
|
|
popExitTransition = Animations.navHostPopExitTransition,
|
|
modifier = Modifier.padding(top = it.calculateTopPadding())
|
|
){
|
|
composable(route = "Home"){Home(localNavCtrl,scrollState)}
|
|
composable(route = "UserInfo"){CurrentUserInfo()}
|
|
composable(route = "UserOperation"){UserOperation()}
|
|
composable(route = "CreateUser"){CreateUser()}
|
|
composable(route = "EditUsername"){Username()}
|
|
composable(route = "ChangeUserIcon"){UserIcon()}
|
|
composable(route = "UserSessionMessage"){UserSessionMessage()}
|
|
composable(route = "AffiliationID"){AffiliationID()}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Home(navCtrl: NavHostController,scrollState: ScrollState){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(scrollState)){
|
|
Text(text = stringResource(R.string.user_manager), style = typography.headlineLarge, modifier = Modifier.padding(top = 8.dp, bottom = 5.dp, start = 15.dp))
|
|
SubPageItem(R.string.user_info,"",R.drawable.person_fill0){navCtrl.navigate("UserInfo")}
|
|
SubPageItem(R.string.user_operation,"",R.drawable.sync_alt_fill0){navCtrl.navigate("UserOperation")}
|
|
if(VERSION.SDK_INT>=24&&isDeviceOwner(dpm)){
|
|
SubPageItem(R.string.create_user,"",R.drawable.person_add_fill0){navCtrl.navigate("CreateUser")}
|
|
}
|
|
SubPageItem(R.string.edit_username,"",R.drawable.edit_fill0){navCtrl.navigate("EditUsername")}
|
|
if(VERSION.SDK_INT>=23&&(isDeviceOwner(dpm)||isProfileOwner(dpm))){
|
|
SubPageItem(R.string.change_user_icon,"",R.drawable.account_circle_fill0){navCtrl.navigate("ChangeUserIcon")}
|
|
}
|
|
if(VERSION.SDK_INT>=28&&isDeviceOwner(dpm)){
|
|
SubPageItem(R.string.user_session_msg,"",R.drawable.notifications_fill0){navCtrl.navigate("UserSessionMessage")}
|
|
}
|
|
if(VERSION.SDK_INT>=26&&(isDeviceOwner(dpm)||isProfileOwner(dpm))){
|
|
SubPageItem(R.string.affiliation_id,"",R.drawable.id_card_fill0){navCtrl.navigate("AffiliationID")}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
LaunchedEffect(Unit) {
|
|
fileUri = null
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun CurrentUserInfo(){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context, Receiver::class.java)
|
|
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.user_info), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Text(stringResource(R.string.is_user_unlocked, UserManagerCompat.isUserUnlocked(context)))
|
|
if(VERSION.SDK_INT>=24){ Text(stringResource(R.string.is_support_multi_user, UserManager.supportsMultipleUsers())) }
|
|
if(VERSION.SDK_INT>=23){ Text(text = stringResource(R.string.is_system_user, userManager.isSystemUser)) }
|
|
if(VERSION.SDK_INT>=34){ Text(text = stringResource(R.string.is_admin_user, userManager.isAdminUser)) }
|
|
if(VERSION.SDK_INT>=31){ Text(text = stringResource(R.string.is_headless_system_user, UserManager.isHeadlessSystemUserMode())) }
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if (VERSION.SDK_INT >= 28) {
|
|
val logoutable = dpm.isLogoutEnabled
|
|
Text(text = stringResource(R.string.user_can_logout, logoutable))
|
|
if(isDeviceOwner(dpm)|| isProfileOwner(dpm)){
|
|
val ephemeralUser = dpm.isEphemeralUser(receiver)
|
|
Text(text = stringResource(R.string.is_ephemeral_user, ephemeralUser))
|
|
}
|
|
Text(text = stringResource(R.string.is_affiliated_user, dpm.isAffiliatedUser))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Text(text = stringResource(R.string.user_id_is, Binder.getCallingUid()/100000))
|
|
Text(text = stringResource(R.string.user_serial_number_is, userManager.getSerialNumberForUser(Process.myUserHandle())))
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun UserOperation(){
|
|
val context = LocalContext.current
|
|
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.user_operation), style = typography.headlineLarge)
|
|
var idInput by remember{ mutableStateOf("") }
|
|
var userHandleById:UserHandle by remember{ mutableStateOf(Process.myUserHandle()) }
|
|
var useUid by remember{ mutableStateOf(false) }
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = idInput,
|
|
onValueChange = {
|
|
idInput=it
|
|
if(useUid){
|
|
if(idInput!=""&&VERSION.SDK_INT>=24){
|
|
userHandleById = UserHandle.getUserHandleForUid(idInput.toInt())
|
|
}
|
|
}else{
|
|
val userHandleBySerial = userManager.getUserForSerialNumber(idInput.toLong())
|
|
userHandleById = userHandleBySerial ?: Process.myUserHandle()
|
|
}
|
|
},
|
|
label = {Text(if(useUid){"UID"}else{ stringResource(R.string.serial_number) })},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.focusable().fillMaxWidth(),
|
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
|
|
)
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
if(VERSION.SDK_INT>=24){
|
|
CheckBoxItem(text = stringResource(R.string.use_uid), checked = {useUid}, operation = {idInput=""; useUid = !useUid})
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(VERSION.SDK_INT>28){
|
|
if(isProfileOwner(dpm)&&dpm.isAffiliatedUser){
|
|
Button(
|
|
onClick = {
|
|
val result = dpm.logoutUser(receiver)
|
|
Toast.makeText(context, userOperationResultCode(result,context), Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isProfileOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.logout_current_user))
|
|
}
|
|
}
|
|
}
|
|
if(VERSION.SDK_INT>=28){
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
val result = dpm.startUserInBackground(receiver,userHandleById)
|
|
Toast.makeText(context, userOperationResultCode(result,context), Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
){
|
|
Text(stringResource(R.string.start_in_background))
|
|
}
|
|
}
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
Toast.makeText(context, if(dpm.switchUser(receiver,userHandleById)) { R.string.success }else{ R.string.fail }, Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.user_operation_switch))
|
|
}
|
|
if(VERSION.SDK_INT>=28){
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
try{
|
|
val result = dpm.stopUser(receiver,userHandleById)
|
|
Toast.makeText(context, userOperationResultCode(result,context), Toast.LENGTH_SHORT).show()
|
|
}catch(e:IllegalArgumentException){
|
|
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.user_operation_stop))
|
|
}
|
|
}
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
if(dpm.removeUser(receiver,userHandleById)){
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
idInput=""
|
|
}else{
|
|
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.user_operation_remove))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun CreateUser(){
|
|
val context = LocalContext.current
|
|
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
var userName by remember{ mutableStateOf("") }
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.create_user), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = userName,
|
|
onValueChange = {userName=it},
|
|
label = {Text(stringResource(R.string.username))},
|
|
modifier = Modifier.focusable().fillMaxWidth(),
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
|
|
)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
var selectedFlag by remember{ mutableIntStateOf(0) }
|
|
RadioButtonItem(stringResource(R.string.none),{selectedFlag==0},{selectedFlag=0})
|
|
RadioButtonItem(stringResource(R.string.create_user_skip_wizard),{selectedFlag==DevicePolicyManager.SKIP_SETUP_WIZARD},{selectedFlag=DevicePolicyManager.SKIP_SETUP_WIZARD})
|
|
if(VERSION.SDK_INT>=28){
|
|
RadioButtonItem(stringResource(R.string.create_user_ephemeral_user),{selectedFlag==DevicePolicyManager.MAKE_USER_EPHEMERAL},{selectedFlag=DevicePolicyManager.MAKE_USER_EPHEMERAL})
|
|
RadioButtonItem(stringResource(R.string.create_user_enable_all_system_app),{selectedFlag==DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED},{selectedFlag=DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED})
|
|
}
|
|
var newUserHandle: UserHandle? by remember{ mutableStateOf(null) }
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
newUserHandle=dpm.createAndManageUser(receiver,userName,receiver,null,selectedFlag)
|
|
focusMgr.clearFocus()
|
|
Toast.makeText(context, if(newUserHandle!=null){R.string.success}else{R.string.fail}, Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.create))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(newUserHandle!=null){ Text(text = stringResource(R.string.serial_number_of_new_user_is, userManager.getSerialNumberForUser(newUserHandle))) }
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun AffiliationID(){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
var input by remember{mutableStateOf("")}
|
|
var list by remember{mutableStateOf("")}
|
|
LaunchedEffect(Unit){
|
|
affiliationID = dpm.getAffiliationIds(receiver)
|
|
list = affiliationID.toText()
|
|
}
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.affiliation_id), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(list!=""){
|
|
SelectionContainer {
|
|
Text(text = list)
|
|
}
|
|
}else{
|
|
Text(text = stringResource(R.string.none))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = input,
|
|
onValueChange = {input = it},
|
|
label = {Text("ID")},
|
|
modifier = Modifier.focusable().fillMaxWidth().padding(vertical = 2.dp),
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
|
|
)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
|
|
Button(
|
|
onClick = { affiliationID.add(input); list = affiliationID.toText() },
|
|
modifier = Modifier.fillMaxWidth(0.49F)
|
|
){
|
|
Text(stringResource(R.string.add))
|
|
}
|
|
Button(
|
|
onClick = { affiliationID.remove(input); list = affiliationID.toText() },
|
|
modifier = Modifier.fillMaxWidth(0.96F)
|
|
){
|
|
Text(stringResource(R.string.remove))
|
|
}
|
|
}
|
|
Button(
|
|
onClick = {
|
|
if("" in affiliationID) {
|
|
Toast.makeText(context, R.string.include_empty_string, Toast.LENGTH_SHORT).show()
|
|
}else if(affiliationID.isEmpty()){
|
|
Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
|
|
}else{
|
|
dpm.setAffiliationIds(receiver, affiliationID)
|
|
affiliationID = dpm.getAffiliationIds(receiver)
|
|
list = affiliationID.toText()
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Username(){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
var inputUsername by remember{mutableStateOf("")}
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.edit_username), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = inputUsername,
|
|
onValueChange = {inputUsername=it},
|
|
label = {Text(stringResource(R.string.username))},
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth(),
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm)
|
|
)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
dpm.setProfileName(receiver,inputUsername)
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
dpm.setProfileName(receiver,null)
|
|
},
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.reset))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun UserSessionMessage(){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
val getStart = dpm.getStartUserSessionMessage(receiver)?:""
|
|
val getEnd = dpm.getEndUserSessionMessage(receiver)?:""
|
|
var start by remember{mutableStateOf(getStart.toString())}
|
|
var end by remember{mutableStateOf(getEnd.toString())}
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.user_session_msg), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = start,
|
|
onValueChange = {start=it},
|
|
label = {Text(stringResource(R.string.start_user_session_msg))},
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth(),
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm)
|
|
)
|
|
Spacer(Modifier.padding(vertical = 2.dp))
|
|
OutlinedTextField(
|
|
value = end,
|
|
onValueChange = {end=it},
|
|
label = {Text(stringResource(R.string.end_user_session_msg))},
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth(),
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm)
|
|
)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
dpm.setStartUserSessionMessage(receiver,start)
|
|
dpm.setEndUserSessionMessage(receiver,end)
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
dpm.setStartUserSessionMessage(receiver,null)
|
|
dpm.setEndUserSessionMessage(receiver,null)
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(dpm)||isProfileOwner(dpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.reset))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun UserIcon(){
|
|
val context = LocalContext.current
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val receiver = ComponentName(context,Receiver::class.java)
|
|
var getContent by remember{mutableStateOf(false)}
|
|
var canApply by remember{mutableStateOf(false)}
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.change_user_icon), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Text(text = stringResource(R.string.pick_a_square_image))
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
CheckBoxItem(stringResource(R.string.file_picker_instead_gallery),{getContent},{getContent=!getContent})
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
val intent = Intent(if(getContent){Intent.ACTION_GET_CONTENT}else{Intent.ACTION_PICK})
|
|
if(getContent){intent.addCategory(Intent.CATEGORY_OPENABLE)}
|
|
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
|
|
getFile.launch(intent)
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.select_picture))
|
|
}
|
|
LaunchedEffect(Unit){ delay(600); canApply = fileUri!=null }
|
|
AnimatedVisibility(canApply) {
|
|
Button(
|
|
onClick = {
|
|
uriToStream(context, fileUri){stream ->
|
|
val bitmap = BitmapFactory.decodeStream(stream)
|
|
dpm.setUserIcon(receiver,bitmap)
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun userOperationResultCode(result:Int, context: Context): String {
|
|
return when(result){
|
|
UserManager.USER_OPERATION_SUCCESS->context.getString(R.string.success)
|
|
UserManager.USER_OPERATION_ERROR_UNKNOWN-> context.getString(R.string.unknown_result)
|
|
UserManager.USER_OPERATION_ERROR_MANAGED_PROFILE-> context.getString(R.string.fail_managed_profile)
|
|
UserManager.USER_OPERATION_ERROR_CURRENT_USER-> context.getString(R.string.fail_current_user)
|
|
else->"未知"
|
|
}
|
|
}
|