Optimize UI for Device info, User info and Password info

Change USB signal to Disable USB signal
Hide Master volume mute in work profile
This commit is contained in:
BinTianqi
2024-10-26 10:54:39 +08:00
parent 3a19b1acf9
commit 5e8ea061ca
11 changed files with 130 additions and 141 deletions

View File

@@ -14,6 +14,7 @@ import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import com.bintianqi.owndroid.dpm.addDeviceAdmin
import com.bintianqi.owndroid.dpm.createManagedProfile
import kotlinx.coroutines.flow.MutableStateFlow
@@ -121,3 +122,8 @@ fun formatFileSize(bytes: Long): String {
else -> "$bytes bytes"
}
}
@StringRes
fun Boolean.yesOrNo(): Int {
return if(this) R.string.yes else R.string.no
}

View File

@@ -192,7 +192,7 @@ private fun CreateWorkProfile() {
if(VERSION.SDK_INT >= 24) { intent.putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncrypt) }
if(VERSION.SDK_INT >= 33) { intent.putExtra(EXTRA_PROVISIONING_ALLOW_OFFLINE, offlineProvisioning) }
createManagedProfile.launch(intent)
} catch(e:ActivityNotFoundException) {
} catch(_:ActivityNotFoundException) {
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show()
}
},

View File

@@ -162,7 +162,7 @@ fun Network(navCtrl: NavHostController) {
val mac = dpm.getWifiMacAddress(receiver)
OutlinedTextField(
value = mac ?: stringResource(R.string.none),
onValueChange = {}, readOnly = true, modifier = Modifier.fillMaxWidth(), textStyle = typography.titleMedium,
onValueChange = {}, readOnly = true, modifier = Modifier.fillMaxWidth(), textStyle = typography.bodyLarge,
trailingIcon = {
if(mac != null) IconButton(onClick = { writeClipBoard(context, mac) }) {
Icon(painter = painterResource(R.drawable.content_copy_fill0), contentDescription = stringResource(R.string.copy))

View File

@@ -81,11 +81,13 @@ import androidx.navigation.compose.rememberNavController
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.toggle
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CardItem
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.Information
import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.SubPageItem
import com.bintianqi.owndroid.ui.TopBar
import com.bintianqi.owndroid.yesOrNo
@Composable
fun Password(navCtrl: NavHostController) {
@@ -265,24 +267,18 @@ private fun PasswordInfo() {
Spacer(Modifier.padding(vertical = 5.dp))
if(VERSION.SDK_INT >= 29) {
val passwordComplexity = mapOf(
PASSWORD_COMPLEXITY_NONE to stringResource(R.string.password_complexity_none),
PASSWORD_COMPLEXITY_LOW to stringResource(R.string.password_complexity_low),
PASSWORD_COMPLEXITY_MEDIUM to stringResource(R.string.password_complexity_medium),
PASSWORD_COMPLEXITY_HIGH to stringResource(R.string.password_complexity_high)
PASSWORD_COMPLEXITY_NONE to R.string.password_complexity_none,
PASSWORD_COMPLEXITY_LOW to R.string.password_complexity_low,
PASSWORD_COMPLEXITY_MEDIUM to R.string.password_complexity_medium,
PASSWORD_COMPLEXITY_HIGH to R.string.password_complexity_high
)
val pwdComplex = passwordComplexity[dpm.passwordComplexity]
Text(text = stringResource(R.string.current_password_complexity_is, pwdComplex?:stringResource(R.string.unknown)))
CardItem(R.string.current_password_complexity, passwordComplexity[dpm.passwordComplexity] ?: R.string.unknown)
}
if(deviceOwner || profileOwner) {
Text(stringResource(R.string.is_password_sufficient, dpm.isActivePasswordSufficient))
}
if(context.isDeviceAdmin) {
val pwdFailedAttempts = dpm.currentFailedPasswordAttempts
Text(text = stringResource(R.string.password_failed_attempts_is, pwdFailedAttempts))
CardItem(R.string.password_sufficient, dpm.isActivePasswordSufficient.yesOrNo())
}
if(VERSION.SDK_INT >= 28 && profileOwner && dpm.isManagedProfile(receiver)) {
val unifiedPwd = dpm.isUsingUnifiedPassword(receiver)
Text(stringResource(R.string.is_using_unified_password, unifiedPwd))
CardItem(R.string.unified_password, dpm.isUsingUnifiedPassword(receiver).yesOrNo())
}
}
}

View File

@@ -29,7 +29,6 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
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.navigation.NavHostController
import androidx.navigation.compose.NavHost
@@ -40,6 +39,7 @@ import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.backToHomeStateFlow
import com.bintianqi.owndroid.ui.*
import com.bintianqi.owndroid.writeClipBoard
import com.bintianqi.owndroid.yesOrNo
import com.rosan.dhizuku.api.Dhizuku
import com.rosan.dhizuku.api.DhizukuRequestPermissionListener
import kotlinx.coroutines.launch
@@ -480,50 +480,29 @@ fun DeviceInfo() {
Text(text = stringResource(R.string.device_info), style = typography.headlineLarge)
Spacer(Modifier.padding(vertical = 5.dp))
if(VERSION.SDK_INT>=34 && (context.isDeviceOwner || dpm.isOrgProfile(receiver))) {
val financed = dpm.isDeviceFinanced
Text(stringResource(R.string.is_device_financed, financed))
CardItem(R.string.financed_device, dpm.isDeviceFinanced.yesOrNo())
}
Spacer(Modifier.padding(vertical = 2.dp))
if(VERSION.SDK_INT >= 33) {
val dpmRole = dpm.devicePolicyManagementRoleHolderPackage
Text(stringResource(R.string.dpmrh, if(dpmRole == null) stringResource(R.string.none) else ""))
if(dpmRole!=null) {
SelectionContainer(modifier = Modifier.horizontalScroll(rememberScrollState())) {
Text(text = dpmRole)
}
}
CardItem(R.string.dpmrh, if(dpmRole == null) stringResource(R.string.none) else dpmRole)
}
Spacer(Modifier.padding(vertical = 2.dp))
val encryptionStatus = mutableMapOf(
DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE to stringResource(R.string.es_inactive),
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE to stringResource(R.string.es_active),
DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED to stringResource(R.string.es_unsupported)
DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE to R.string.es_inactive,
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE to R.string.es_active,
DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED to R.string.es_unsupported
)
if(VERSION.SDK_INT >= 23) { encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY] = stringResource(R.string.es_active_default_key) }
if(VERSION.SDK_INT >= 24) { encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER] = stringResource(R.string.es_active_per_user) }
Text(stringResource(R.string.encrypt_status_is, encryptionStatus[dpm.storageEncryptionStatus] ?: ""))
Spacer(Modifier.padding(vertical = 2.dp))
if(VERSION.SDK_INT >= 23) { encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY] = R.string.es_active_default_key }
if(VERSION.SDK_INT >= 24) { encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER] = R.string.es_active_per_user }
CardItem(R.string.encryption_status, encryptionStatus[dpm.storageEncryptionStatus] ?: R.string.unknown)
if(VERSION.SDK_INT >= 28) {
Text(stringResource(R.string.support_device_id_attestation, dpm.isDeviceIdAttestationSupported))
CardItem(R.string.support_device_id_attestation, dpm.isDeviceIdAttestationSupported.yesOrNo())
}
Spacer(Modifier.padding(vertical = 2.dp))
if (VERSION.SDK_INT >= 30) {
Text(stringResource(R.string.support_unique_device_attestation, dpm.isUniqueDeviceAttestationSupported))
CardItem(R.string.support_unique_device_attestation, dpm.isUniqueDeviceAttestationSupported.yesOrNo())
}
Spacer(Modifier.padding(vertical = 2.dp))
val adminList = dpm.activeAdmins
if(adminList!=null) {
var adminListText = ""
Text(text = stringResource(R.string.activated_device_admin, adminList.size))
var count = adminList.size
for(each in adminList) {
count -= 1
adminListText += "${each.packageName}/${each.className}"
if(count>0) {adminListText += "\n"}
}
SelectionContainer(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp).horizontalScroll(rememberScrollState())) {
Text(text = adminListText)
}
if(adminList != null) {
CardItem(R.string.activated_device_admin, adminList.map { it.flattenToShortString() }.joinToString("\n"))
}
}
}
@@ -692,9 +671,9 @@ private fun TransformOwnership() {
Button(
onClick = {
try {
dpm.transferOwnership(receiver,ComponentName(pkg, cls),null)
dpm.transferOwnership(receiver, ComponentName(pkg, cls),null)
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}catch(e:IllegalArgumentException) {
} catch(_:IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
},
@@ -712,7 +691,7 @@ private fun activateDeviceAdmin(inputContext:Context,inputComponent:ComponentNam
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, inputComponent)
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, inputContext.getString(R.string.activate_device_admin_here))
addDeviceAdmin.launch(intent)
}catch(e:ActivityNotFoundException) {
} catch(_:ActivityNotFoundException) {
Toast.makeText(inputContext, R.string.unsupported, Toast.LENGTH_SHORT).show()
}
}

View File

@@ -282,7 +282,7 @@ private fun Switches() {
SwitchItem(R.string.require_auto_time, "", R.drawable.schedule_fill0, { dpm.autoTimeRequired}, { dpm.setAutoTimeRequired(receiver,it) }, padding = false)
}
}
if(deviceOwner || profileOwner) {
if(deviceOwner || (profileOwner && (VERSION.SDK_INT < 24 || (VERSION.SDK_INT >= 24 && !dpm.isManagedProfile(receiver))))) {
SwitchItem(R.string.master_mute, "", R.drawable.volume_up_fill0,
{ dpm.isMasterVolumeMuted(receiver) }, { dpm.setMasterVolumeMuted(receiver,it) }, padding = false
)
@@ -302,16 +302,10 @@ private fun Switches() {
{ dpm.isCommonCriteriaModeEnabled(receiver) }, { dpm.setCommonCriteriaModeEnabled(receiver,it) }, padding = false
)
}
if(VERSION.SDK_INT >= 31 && (deviceOwner || dpm.isOrgProfile(receiver))) {
if(VERSION.SDK_INT >= 31 && (deviceOwner || dpm.isOrgProfile(receiver)) && dpm.canUsbDataSignalingBeDisabled()) {
SwitchItem(
R.string.usb_signal, "", R.drawable.usb_fill0, { dpm.isUsbDataSignalingEnabled },
{
if(dpm.canUsbDataSignalingBeDisabled()) {
dpm.isUsbDataSignalingEnabled = it
} else {
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show()
}
}, padding = false
R.string.disable_usb_signal, "", R.drawable.usb_fill0, { !dpm.isUsbDataSignalingEnabled },
{ dpm.isUsbDataSignalingEnabled = !it }, padding = false
)
}
Spacer(Modifier.padding(vertical = 30.dp))

View File

@@ -56,7 +56,6 @@ 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
@@ -67,11 +66,13 @@ import com.bintianqi.owndroid.fileUriFlow
import com.bintianqi.owndroid.getFile
import com.bintianqi.owndroid.toggle
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CardItem
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.SubPageItem
import com.bintianqi.owndroid.ui.SwitchItem
import com.bintianqi.owndroid.ui.TopBar
import com.bintianqi.owndroid.uriToStream
import com.bintianqi.owndroid.yesOrNo
@Composable
fun UserManage(navCtrl: NavHostController) {
@@ -171,24 +172,20 @@ private fun CurrentUserInfo() {
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 >= 24) CardItem(R.string.support_multiuser, UserManager.supportsMultipleUsers().yesOrNo())
if(VERSION.SDK_INT >= 23) CardItem(R.string.system_user, userManager.isSystemUser.yesOrNo())
if(VERSION.SDK_INT >= 34) CardItem(R.string.admin_user, userManager.isAdminUser.yesOrNo())
if(VERSION.SDK_INT >= 31) CardItem(R.string.headless_system_user, UserManager.isHeadlessSystemUserMode().yesOrNo())
if (VERSION.SDK_INT >= 28) {
val logoutable = dpm.isLogoutEnabled
Text(text = stringResource(R.string.user_can_logout, logoutable))
CardItem(R.string.logout_enabled, dpm.isLogoutEnabled.yesOrNo())
if(context.isDeviceOwner || context.isProfileOwner) {
val ephemeralUser = dpm.isEphemeralUser(receiver)
Text(text = stringResource(R.string.is_ephemeral_user, ephemeralUser))
CardItem(R.string.ephemeral_user, dpm.isEphemeralUser(receiver).yesOrNo())
}
Text(text = stringResource(R.string.is_affiliated_user, dpm.isAffiliatedUser))
CardItem(R.string.affiliated_user, dpm.isAffiliatedUser.yesOrNo())
}
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())))
CardItem(R.string.user_id, (Binder.getCallingUid() / 100000).toString())
CardItem(R.string.user_serial_number, userManager.getSerialNumberForUser(Process.myUserHandle()).toString())
Spacer(Modifier.padding(vertical = 30.dp))
}
}
@@ -270,7 +267,7 @@ private fun UserOperation() {
try{
val result = dpm.stopUser(receiver,userHandleById)
Toast.makeText(context, userOperationResultCode(result,context), Toast.LENGTH_SHORT).show()
}catch(e:IllegalArgumentException) {
}catch(_: IllegalArgumentException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
}
},

View File

@@ -7,6 +7,7 @@ import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
@@ -18,6 +19,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
@@ -223,3 +225,18 @@ fun CopyTextButton(@StringRes label: Int, content: String) {
}
}
}
@Composable
fun CardItem(@StringRes title: Int, @StringRes text: Int) {
CardItem(title, stringResource(text))
}
@Composable
fun CardItem(@StringRes title: Int, text: String) {
Card(modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)) {
Text(text = stringResource(title), style = typography.titleLarge, modifier = Modifier.padding(start = 8.dp, top = 6.dp))
SelectionContainer {
Text(text = text, modifier = Modifier.padding(start = 8.dp, bottom = 6.dp))
}
}
}