Show preview when changing user icon

Refresh activate status when ownership transferred to OwnDroid
Set Start user session message and End user session message separately
Set Long support message and Short support message separately
Simplify code
This commit is contained in:
BinTianqi
2024-09-28 10:45:48 +08:00
parent 47a965e6c0
commit 0788634049
13 changed files with 180 additions and 143 deletions

View File

@@ -1,7 +1,7 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.cc)
alias(libs.plugins.compose)
kotlin("plugin.serialization") version "2.0.0"
}
@@ -76,8 +76,6 @@ gradle.taskGraph.whenReady {
dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.accompanist.drawablepainter)
implementation(libs.androidx.material3)
implementation(libs.androidx.navigation.compose)

View File

@@ -16,8 +16,8 @@ class AutomationReceiver: BroadcastReceiver() {
@SuppressLint("NewApi")
fun handleTask(context: Context, intent: Intent): String {
val sharedPrefs = context.getSharedPreferences("data", Context.MODE_PRIVATE)
val key = sharedPrefs.getString("automation_key", "") ?: ""
if(key != intent.getStringExtra("key")) {
val key = sharedPrefs.getString("automation_key", "")
if(key == null || key != intent.getStringExtra("key")) {
return "Wrong key"
}
val operation = intent.getStringExtra("operation")

View File

@@ -18,6 +18,7 @@ import android.content.pm.PackageInstaller.STATUS_FAILURE_TIMEOUT
import android.content.pm.PackageInstaller.STATUS_PENDING_USER_ACTION
import android.content.pm.PackageInstaller.STATUS_SUCCESS
import android.os.Build.VERSION
import android.os.PersistableBundle
import android.util.Log
import android.widget.Toast
import com.bintianqi.owndroid.dpm.getDPM
@@ -68,6 +69,13 @@ class Receiver : DeviceAdminReceiver() {
handleSecurityLogs(context)
}
}
override fun onTransferOwnershipComplete(context: Context, bundle: PersistableBundle?) {
super.onTransferOwnershipComplete(context, bundle)
val sp = context.getSharedPreferences("data", Context.MODE_PRIVATE)
sp.edit().putBoolean("dhizuku", false).apply()
context.toggleInstallAppActivity()
}
}
val installAppDone = MutableStateFlow(false)

View File

@@ -34,7 +34,7 @@ fun uriToStream(
operation: (stream: InputStream)->Unit
){
if(uri!=null){
try{
try {
val stream = context.contentResolver.openInputStream(uri)
if(stream != null) { operation(stream) }
stream?.close()
@@ -44,26 +44,6 @@ fun uriToStream(
}
}
fun List<Any>.toText():String{
var output = ""
var isFirst = true
for(each in listIterator()){
if(isFirst) { isFirst = false } else { output+="\n" }
output+=each
}
return output
}
fun Set<Any>.toText(): String{
var output = ""
var isFirst = true
for(each in iterator()){
if(isFirst) { isFirst = false } else { output+="\n" }
output += each
}
return output
}
fun MutableList<Int>.toggle(status: Boolean, element: Int) {
if(status) add(element) else remove(element)
}

View File

@@ -85,7 +85,6 @@ import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.fileUriFlow
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.toText
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.Information
import com.bintianqi.owndroid.ui.NavIcon
@@ -358,7 +357,7 @@ private fun UserCtrlDisabledPkg(pkgName:String) {
Spacer(Modifier.padding(vertical = 5.dp))
Text(text = stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.toText())
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.joinToString(separator = "\n"))
}
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
@@ -510,7 +509,7 @@ private fun CrossProfilePkg(pkgName: String) {
Text(text = stringResource(R.string.cross_profile_package), style = typography.headlineLarge)
Text(text = stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(crossProfilePkg.isEmpty()) stringResource(R.string.none) else crossProfilePkg.toText())
Text(text = if(crossProfilePkg.isEmpty()) stringResource(R.string.none) else crossProfilePkg.joinToString(separator = "\n"))
}
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
@@ -567,7 +566,7 @@ private fun CrossProfileWidget(pkgName: String) {
Spacer(Modifier.padding(vertical = 5.dp))
Text(text = stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.toText())
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.joinToString(separator = "\n"))
}
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
@@ -660,7 +659,7 @@ private fun CredentialManagePolicy(pkgName: String) {
Column {
Text(stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(credentialList.isEmpty()) stringResource(R.string.none) else credentialList.toText())
Text(text = if(credentialList.isEmpty()) stringResource(R.string.none) else credentialList.joinToString(separator = "\n"))
}
Spacer(Modifier.padding(vertical = 10.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
@@ -739,7 +738,7 @@ private fun PermittedAccessibility(pkgName: String) {
if (pkgList.isEmpty()) {
Text(stringResource(R.string.only_system_accessibility_allowed))
} else {
Text(stringResource(R.string.permitted_packages_is) + pkgList.toText())
Text(stringResource(R.string.permitted_packages_is) + pkgList.joinToString(separator = "\n"))
}
}
Spacer(Modifier.padding(vertical = 5.dp))
@@ -819,7 +818,7 @@ private fun PermittedIME(pkgName: String) {
if(permittedIme.isEmpty()) {
Text(stringResource(R.string.only_system_ime_allowed))
} else {
Text(stringResource(R.string.permitted_packages_is) + permittedIme.toText())
Text(stringResource(R.string.permitted_packages_is) + permittedIme.joinToString(separator = "\n"))
}
}
Spacer(Modifier.padding(vertical = 5.dp))
@@ -882,7 +881,7 @@ private fun KeepUninstalledApp(pkgName: String) {
Spacer(Modifier.padding(vertical = 5.dp))
Text(text = stringResource(R.string.app_list_is))
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState()).animateContentSize()) {
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.toText())
Text(text = if(pkgList.isEmpty()) stringResource(R.string.none) else pkgList.joinToString(separator = "\n"))
}
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {

View File

@@ -183,7 +183,7 @@ val dhizukuErrorStatus = MutableStateFlow(0)
fun Context.resetDevicePolicy() {
val dpm = getDPM()
val receiver = getReceiver()
RestrictionData.getAllRestrictions(this).forEach {
RestrictionData.getAllRestrictions().forEach {
dpm.clearUserRestriction(receiver, it)
}
dpm.accountTypesWithManagementDisabled?.forEach {

View File

@@ -12,7 +12,6 @@ import android.app.admin.DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED
import android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT
import android.app.admin.DevicePolicyManager.WIPE_EUICC
import android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE
import android.app.admin.DevicePolicyManager.WIPE_SILENTLY
import android.content.*
import android.os.Binder
import android.os.Build.VERSION

View File

@@ -104,7 +104,6 @@ import com.bintianqi.owndroid.exportFile
import com.bintianqi.owndroid.exportFilePath
import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.toText
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.RadioButtonItem
@@ -332,7 +331,7 @@ private fun WifiSsidPolicy() {
Spacer(Modifier.padding(vertical = 5.dp))
Text(stringResource(R.string.ssid_list_is))
SelectionContainer(modifier = Modifier.animateContentSize().horizontalScroll(rememberScrollState())) {
Text(if(ssidList.isEmpty()) stringResource(R.string.none) else ssidList.toText())
Text(if(ssidList.isEmpty()) stringResource(R.string.none) else ssidList.joinToString(separator = "\n"))
}
}
Spacer(Modifier.padding(vertical = 5.dp))

View File

@@ -559,9 +559,13 @@ private fun SupportMsg() {
val context = LocalContext.current
val dpm = context.getDPM()
val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current
var shortMsg by remember { mutableStateOf(dpm.getShortSupportMessage(receiver)?.toString() ?: "") }
var longMsg by remember { mutableStateOf(dpm.getLongSupportMessage(receiver)?.toString() ?: "") }
var shortMsg by remember { mutableStateOf("") }
var longMsg by remember { mutableStateOf("") }
val refreshMsg = {
shortMsg = dpm.getShortSupportMessage(receiver)?.toString() ?: ""
longMsg = dpm.getLongSupportMessage(receiver)?.toString() ?: ""
}
LaunchedEffect(Unit) { refreshMsg() }
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 8.dp)) {
Spacer(Modifier.padding(vertical = 10.dp))
Text(text = stringResource(R.string.support_msg), style = typography.headlineLarge)
@@ -570,45 +574,59 @@ private fun SupportMsg() {
value = shortMsg,
label = { Text(stringResource(R.string.short_support_msg)) },
onValueChange = { shortMsg = it },
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().padding(bottom = 2.dp)
)
Spacer(Modifier.padding(vertical = 2.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = {
dpm.setShortSupportMessage(receiver, shortMsg)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(text = stringResource(R.string.apply))
}
Button(
onClick = {
dpm.setShortSupportMessage(receiver, null)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(text = stringResource(R.string.reset))
}
}
Spacer(Modifier.padding(vertical = 8.dp))
OutlinedTextField(
value = longMsg,
label = { Text(stringResource(R.string.long_support_msg)) },
onValueChange = { longMsg = it },
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().padding(bottom = 2.dp)
)
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = {
focusMgr.clearFocus()
dpm.setShortSupportMessage(receiver, shortMsg)
dpm.setLongSupportMessage(receiver, longMsg)
shortMsg = dpm.getShortSupportMessage(receiver)?.toString() ?: ""
longMsg = dpm.getLongSupportMessage(receiver)?.toString() ?: ""
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(text = stringResource(R.string.apply))
}
Spacer(Modifier.padding(vertical = 1.dp))
Button(
onClick = {
focusMgr.clearFocus()
dpm.setShortSupportMessage(receiver, null)
dpm.setLongSupportMessage(receiver, null)
shortMsg = dpm.getShortSupportMessage(receiver)?.toString() ?: ""
longMsg = dpm.getLongSupportMessage(receiver)?.toString() ?: ""
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(text = stringResource(R.string.reset))
}
Spacer(Modifier.padding(vertical = 5.dp))
Information{ Text(text = stringResource(R.string.support_msg_desc)) }
}
Spacer(Modifier.padding(vertical = 30.dp))
}
}

View File

@@ -110,7 +110,6 @@ import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.prepareForNotification
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.toText
import com.bintianqi.owndroid.toggle
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CheckBoxItem
@@ -1115,7 +1114,7 @@ fun FactoryResetProtection() {
CheckBoxItem(R.string.enable_frp, enabled, { enabled = it })
Text(stringResource(R.string.account_list_is))
Text(
text = if(accountList.isEmpty()) stringResource(R.string.none) else accountList.toText(),
text = if(accountList.isEmpty()) stringResource(R.string.none) else accountList.joinToString(separator = "\n"),
modifier = Modifier.animateContentSize()
)
OutlinedTextField(

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Binder
@@ -14,6 +15,7 @@ import android.os.UserManager
import android.provider.MediaStore
import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -22,12 +24,15 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
@@ -37,11 +42,15 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf
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.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
@@ -57,7 +66,6 @@ import androidx.navigation.compose.rememberNavController
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.fileUriFlow
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.toText
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.RadioButtonItem
@@ -65,7 +73,6 @@ import com.bintianqi.owndroid.ui.SubPageItem
import com.bintianqi.owndroid.ui.TopBar
import com.bintianqi.owndroid.uriToStream
var affiliationID = mutableSetOf<String>()
@Composable
fun UserManage(navCtrl: NavHostController) {
val localNavCtrl = rememberNavController()
@@ -341,11 +348,13 @@ private fun AffiliationID() {
val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current
var input by remember { mutableStateOf("") }
var list by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
affiliationID = dpm.getAffiliationIds(receiver)
list = affiliationID.toText()
val affiliationID = remember { mutableStateListOf<String>() }
val list = affiliationID.joinToString(separator = "\n")
val refreshIds = {
affiliationID.clear()
affiliationID.addAll(dpm.getAffiliationIds(receiver))
}
LaunchedEffect(Unit) { refreshIds() }
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)
@@ -367,13 +376,13 @@ private fun AffiliationID() {
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = { affiliationID.add(input); list = affiliationID.toText() },
onClick = { affiliationID.add(input) },
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(stringResource(R.string.add))
}
Button(
onClick = { affiliationID.remove(input); list = affiliationID.toText() },
onClick = { affiliationID.remove(input) },
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(stringResource(R.string.remove))
@@ -383,12 +392,11 @@ private fun AffiliationID() {
onClick = {
if("" in affiliationID) {
Toast.makeText(context, R.string.include_empty_string, Toast.LENGTH_SHORT).show()
}else if(affiliationID.isEmpty()) {
} 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()
} else {
dpm.setAffiliationIds(receiver, affiliationID.toSet())
refreshIds()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}
},
@@ -445,10 +453,13 @@ private fun UserSessionMessage() {
val dpm = context.getDPM()
val receiver = context.getReceiver()
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()) }
var start by remember { mutableStateOf("") }
var end by remember { mutableStateOf("") }
val refreshMsg = {
start = dpm.getStartUserSessionMessage(receiver)?.toString() ?: ""
end = dpm.getEndUserSessionMessage(receiver)?.toString() ?: ""
}
LaunchedEffect(Unit) { refreshMsg() }
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)
@@ -459,38 +470,61 @@ private fun UserSessionMessage() {
label = { Text(stringResource(R.string.start_user_session_msg)) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus() }),
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().padding(bottom = 2.dp)
)
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.fillMaxWidth()
)
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = {
dpm.setStartUserSessionMessage(receiver,start)
dpm.setEndUserSessionMessage(receiver,end)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(stringResource(R.string.apply))
}
Button(
onClick = {
dpm.setStartUserSessionMessage(receiver,null)
dpm.setEndUserSessionMessage(receiver,null)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(stringResource(R.string.reset))
}
}
Spacer(Modifier.padding(vertical = 8.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.fillMaxWidth().padding(bottom = 2.dp)
)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = {
dpm.setEndUserSessionMessage(receiver,end)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(stringResource(R.string.apply))
}
Button(
onClick = {
dpm.setEndUserSessionMessage(receiver,null)
refreshMsg()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(stringResource(R.string.reset))
}
}
Spacer(Modifier.padding(vertical = 30.dp))
}
}
@@ -502,13 +536,18 @@ private fun UserIcon() {
val dpm = context.getDPM()
val receiver = context.getReceiver()
var getContent by remember { mutableStateOf(false) }
val canApply = fileUriFlow.collectAsState().value != Uri.parse("")
var bitmap by remember { mutableStateOf<Bitmap?>(null) }
val uriState by fileUriFlow.collectAsState()
LaunchedEffect(uriState) {
if(uriState == Uri.parse("")) return@LaunchedEffect
uriToStream(context, fileUriFlow.value) { stream ->
bitmap = BitmapFactory.decodeStream(stream)
}
}
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(R.string.file_picker_instead_gallery, getContent, { getContent = it })
Spacer(Modifier.padding(vertical = 5.dp))
Button(
@@ -522,21 +561,25 @@ private fun UserIcon() {
) {
Text(stringResource(R.string.select_picture))
}
AnimatedVisibility(canApply) {
AnimatedVisibility(visible = bitmap != null, modifier = Modifier.align(Alignment.CenterHorizontally)) {
Card(modifier = Modifier.padding(top = 8.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(10.dp)) {
Image(
bitmap = bitmap!!.asImageBitmap(), contentDescription = "User icon",
modifier = Modifier.padding(end = 12.dp).size(80.dp).clip(RoundedCornerShape(50))
)
Button(
onClick = {
uriToStream(context, fileUriFlow.value) {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 {

View File

@@ -1,7 +1,6 @@
package com.bintianqi.owndroid.dpm
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build.VERSION
import android.os.UserManager
import android.widget.Toast
@@ -12,7 +11,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -143,9 +141,8 @@ private fun Connectivity() {
@Composable
fun Application() {
val context = LocalContext.current
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
for(applicationItem in RestrictionData.application(context)) {
for(applicationItem in RestrictionData.application()) {
UserRestrictionItem(applicationItem.restriction, applicationItem.name, applicationItem.desc, applicationItem.ico)
}
Spacer(Modifier.padding(vertical = 30.dp))
@@ -174,9 +171,8 @@ private fun Media() {
@Composable
private fun Other() {
val context = LocalContext.current
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
for(otherItem in RestrictionData.other(context)) {
for(otherItem in RestrictionData.other()) {
UserRestrictionItem(otherItem.restriction, otherItem.name, otherItem.desc, otherItem.ico)
}
Spacer(Modifier.padding(vertical = 30.dp))
@@ -255,7 +251,7 @@ object RestrictionData {
if(VERSION.SDK_INT>=28) { list += Restriction(UserManager.DISALLOW_PRINTING, R.string.printing, "", R.drawable.print_fill0) }
return list
}
fun application(context: Context): List<Restriction>{
fun application(): List<Restriction>{
val list:MutableList<Restriction> = mutableListOf()
list += Restriction(UserManager.DISALLOW_INSTALL_APPS, R.string.install_app, "", R.drawable.android_fill0)
if(VERSION.SDK_INT>=29) { list += Restriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, R.string.install_unknown_src_globally, "", R.drawable.android_fill0) }
@@ -293,7 +289,7 @@ object RestrictionData {
}
return list
}
fun other(context: Context): List<Restriction>{
fun other(): List<Restriction>{
val list:MutableList<Restriction> = mutableListOf()
if(VERSION.SDK_INT>=26) { list += Restriction(UserManager.DISALLOW_AUTOFILL, R.string.autofill, "", R.drawable.password_fill0) }
list += Restriction(UserManager.DISALLOW_CONFIG_CREDENTIALS, R.string.config_credentials, "", R.drawable.android_fill0)
@@ -316,14 +312,14 @@ object RestrictionData {
list += Restriction(UserManager.DISALLOW_DEBUGGING_FEATURES, R.string.debug_features, "", R.drawable.adb_fill0)
return list
}
fun getAllRestrictions(context: Context): List<String> {
fun getAllRestrictions(): List<String> {
val result = mutableListOf<String>()
internet().forEach { result.add(it.restriction) }
connectivity().forEach { result.add(it.restriction) }
media().forEach { result.add(it.restriction) }
application(context).forEach { result.add(it.restriction) }
application().forEach { result.add(it.restriction) }
user().forEach { result.add(it.restriction) }
other(context).forEach { result.add(it.restriction) }
other().forEach { result.add(it.restriction) }
return result
}
}

View File

@@ -17,8 +17,6 @@ serialization = "1.7.1"
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
androidx-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
androidx-ui = { module = "androidx.compose.ui:ui" }
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "biometric" }
@@ -34,4 +32,4 @@ serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
cc = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }