Optimize code

Pop a toast instead of crash when creating user failed
Add popToast function
Update READMEs
This commit is contained in:
BinTianqi
2025-08-21 09:11:36 +08:00
parent b3d746083f
commit c745eb25a9
13 changed files with 97 additions and 81 deletions

View File

@@ -57,7 +57,7 @@ Solutions:
> [!NOTE]
> Some systems have features such as app cloning and children space, which are usually users.
### MIUI
### MIUI & HyperOS
```text
java.lang.SecurityException: Neither user 2000 nor current process has android.permission.MANAGE_DEVICE_ADMINS.
@@ -65,7 +65,7 @@ java.lang.SecurityException: Neither user 2000 nor current process has android.p
Solutions:
- Enable `USB debugging (Security setting)` in developer options.
- Execute activating command in root shell.
- Or execute activating command in root shell.
### ColorOS
@@ -75,6 +75,14 @@ java.lang.IllegalStateException: Unexpected @ProvisioningPreCondition
Solution: Use OwnDroid testkey version
### Samsung
```text
user limit reached
```
Samsung restricts Android's multiple users feature. There is currently no solution.
## API
| ID | Extras | Minimum Android version |

View File

@@ -57,15 +57,13 @@ java.lang.IllegalStateException: Not allowed to set the device owner because the
> [!NOTE]
> 一些系统有应用克隆、儿童空间等功能,它们通常是用户。
### MIUI
### MIUI & HyperOS
```text
java.lang.SecurityException: Neither user 2000 nor current process has android.permission.MANAGE_DEVICE_ADMINS.
```
解决办法:
- 在开发者设置中打开`USB调试安全设置`
- 在root命令行中执行激活命令
解决办法: 在开发者设置中打开`USB调试安全设置`或在root命令行中执行激活命令。
### ColorOS
@@ -75,6 +73,14 @@ java.lang.IllegalStateException: Unexpected @ProvisioningPreCondition
解决办法:使用 OwnDroid testkey 版本
### 三星
```text
user limit reached
```
三星限制了多用户功能,暂无解决办法。
## API
| ID | Extra | 最小安卓版本 |

View File

@@ -2,7 +2,6 @@ package com.bintianqi.owndroid
import android.os.Build.VERSION
import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
@@ -481,7 +480,7 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
if(profileNotActivated) {
dpm.setProfileEnabled(receiver)
sp.managedProfileActivated = true
Toast.makeText(context, R.string.work_profile_activated, Toast.LENGTH_SHORT).show()
context.popToast(R.string.work_profile_activated)
}
}
DhizukuErrorDialog {

View File

@@ -7,7 +7,6 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -132,7 +131,7 @@ fun AppChooserScreen(params: ApplicationsList, onChoosePackage: (String?) -> Uni
}
IconButton({
system = !system
Toast.makeText(context, if(system) R.string.show_system_app else R.string.show_user_app, Toast.LENGTH_SHORT).show()
context.popToast(if(system) R.string.show_system_app else R.string.show_user_app)
}) {
Icon(painter = painterResource(R.drawable.filter_alt_fill0), contentDescription = null)
}

View File

@@ -10,7 +10,6 @@ import android.os.Build.VERSION
import android.os.PersistableBundle
import android.os.UserHandle
import android.os.UserManager
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.bintianqi.owndroid.dpm.handleNetworkLogs
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
@@ -48,7 +47,7 @@ class Receiver : DeviceAdminReceiver() {
override fun onProfileProvisioningComplete(context: Context, intent: Intent) {
super.onProfileProvisioningComplete(context, intent)
Toast.makeText(context, R.string.create_work_profile_success, Toast.LENGTH_SHORT).show()
context.popToast(R.string.create_work_profile_success)
}
override fun onNetworkLogsAvailable(context: Context, intent: Intent, batchToken: Long, networkLogsCount: Int) {

View File

@@ -6,7 +6,6 @@ import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.IBinder
import android.widget.Toast
import androidx.annotation.Keep
import rikka.shizuku.Shizuku
import rikka.sui.Sui
@@ -54,12 +53,12 @@ fun useShizuku(context: Context, action: (IBinder?) -> Unit) {
if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
Shizuku.bindUserService(getShizukuArgs(context), connection)
} else if(Shizuku.shouldShowRequestPermissionRationale()) {
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
context.popToast(R.string.permission_denied)
} else {
Sui.init(context.packageName)
fun requestPermissionResultListener(requestCode: Int, grantResult: Int) {
if(grantResult != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show()
context.popToast(R.string.permission_denied)
}
Shizuku.removeRequestPermissionResultListener(::requestPermissionResultListener)
}

View File

@@ -43,8 +43,8 @@ fun uriToStream(
operation(it)
}
}
catch(_: FileNotFoundException) { Toast.makeText(context, R.string.file_not_exist, Toast.LENGTH_SHORT).show() }
catch(_: IOException) { Toast.makeText(context, R.string.io_exception, Toast.LENGTH_SHORT).show() }
catch(_: FileNotFoundException) { context.popToast(R.string.file_not_exist) }
catch(_: IOException) { context.popToast(R.string.io_exception) }
}
fun writeClipBoard(context: Context, string: String):Boolean{
@@ -88,7 +88,7 @@ fun formatDate(pattern: String, value: Long): String
= SimpleDateFormat(pattern, Locale.getDefault()).format(Date(value))
fun Context.showOperationResultToast(success: Boolean) {
Toast.makeText(this, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
popToast(if(success) R.string.success else R.string.failed)
}
const val APK_MIME = "application/vnd.android.package-archive"
@@ -143,3 +143,11 @@ fun getPackageSignature(info: PackageInfo): String? {
return signatures?.firstOrNull()?.toByteArray()
?.let { MessageDigest.getInstance("SHA-256").digest(it) }?.toHexString()
}
fun Context.popToast(resId: Int) {
Toast.makeText(this, resId, Toast.LENGTH_SHORT).show()
}
fun Context.popToast(str: String) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show()
}

View File

@@ -32,7 +32,6 @@ import android.net.wifi.WifiSsid
import android.os.Build.VERSION
import android.os.Bundle
import android.telephony.data.ApnSetting
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
@@ -135,6 +134,7 @@ import com.bintianqi.owndroid.formatDate
import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog
@@ -1396,27 +1396,29 @@ fun PrivateDnsScreen(onNavigateUp: () -> Unit) {
val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current
MyScaffold(R.string.private_dns, onNavigateUp) {
val dnsStatus = mapOf(
PRIVATE_DNS_MODE_UNKNOWN to stringResource(R.string.unknown),
PRIVATE_DNS_MODE_OFF to stringResource(R.string.disabled),
PRIVATE_DNS_MODE_OPPORTUNISTIC to stringResource(R.string.auto),
PRIVATE_DNS_MODE_PROVIDER_HOSTNAME to stringResource(R.string.dns_provide_hostname)
)
val operationResult = mapOf(
PRIVATE_DNS_SET_NO_ERROR to stringResource(R.string.success),
PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING to stringResource(R.string.host_not_serving_dns_tls),
PRIVATE_DNS_SET_ERROR_FAILURE_SETTING to stringResource(R.string.failed)
)
var status by remember { mutableStateOf(dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)]) }
fun getDnsStatus(code: Int) = when (code) {
PRIVATE_DNS_MODE_UNKNOWN -> R.string.unknown
PRIVATE_DNS_MODE_OFF -> R.string.disabled
PRIVATE_DNS_MODE_OPPORTUNISTIC -> R.string.auto
PRIVATE_DNS_MODE_PROVIDER_HOSTNAME -> R.string.dns_provide_hostname
else -> R.string.place_holder
}
fun getOperationResult(code: Int) = when (code) {
PRIVATE_DNS_SET_NO_ERROR -> R.string.success
PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING -> R.string.host_not_serving_dns_tls
PRIVATE_DNS_SET_ERROR_FAILURE_SETTING -> R.string.failed
else -> R.string.place_holder
}
var dnsMode by remember { mutableIntStateOf(dpm.getGlobalPrivateDnsMode(receiver)) }
Spacer(Modifier.padding(vertical = 5.dp))
Text(text = stringResource(R.string.current_state, status?:stringResource(R.string.unknown)))
Text(stringResource(R.string.current_state, stringResource(getDnsStatus(dnsMode))))
AnimatedVisibility(visible = dpm.getGlobalPrivateDnsMode(receiver)!=PRIVATE_DNS_MODE_OPPORTUNISTIC) {
Spacer(Modifier.padding(vertical = 5.dp))
Button(
onClick = {
val result = dpm.setGlobalPrivateDnsModeOpportunistic(receiver)
Toast.makeText(context, operationResult[result], Toast.LENGTH_SHORT).show()
status = dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)]
context.popToast(getOperationResult(result))
dnsMode = dpm.getGlobalPrivateDnsMode(receiver)
},
modifier = Modifier.fillMaxWidth()
) {
@@ -1438,18 +1440,17 @@ fun PrivateDnsScreen(onNavigateUp: () -> Unit) {
Button(
onClick = {
focusMgr.clearFocus()
val result: Int
try {
result = dpm.setGlobalPrivateDnsModeSpecifiedHost(receiver,inputHost)
Toast.makeText(context, operationResult[result], Toast.LENGTH_SHORT).show()
val result = dpm.setGlobalPrivateDnsModeSpecifiedHost(receiver,inputHost)
context.popToast(getOperationResult(result))
} catch(e: IllegalArgumentException) {
e.printStackTrace()
Toast.makeText(context, R.string.invalid_hostname, Toast.LENGTH_SHORT).show()
context.popToast(R.string.invalid_hostname)
} catch(e: SecurityException) {
e.printStackTrace()
Toast.makeText(context, R.string.security_exception, Toast.LENGTH_SHORT).show()
context.popToast(R.string.security_exception)
} finally {
status = dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)]
dnsMode = dpm.getGlobalPrivateDnsMode(receiver)
}
},
modifier = Modifier.fillMaxWidth()
@@ -1483,11 +1484,11 @@ fun AlwaysOnVpnPackageScreen(onNavigateUp: () -> Unit) {
true
} catch(e: UnsupportedOperationException) {
e.printStackTrace()
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show()
context.popToast(R.string.unsupported)
false
} catch(e: NameNotFoundException) {
e.printStackTrace()
Toast.makeText(context, R.string.not_installed, Toast.LENGTH_SHORT).show()
context.popToast(R.string.not_installed)
false
}
}
@@ -1588,7 +1589,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
return@Button
}
if(proxyUri == "") {
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show()
context.popToast(R.string.invalid_config)
return@Button
}
val uri = proxyUri.toUri()
@@ -1597,7 +1598,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
port = proxyPort.toInt()
} catch(e: NumberFormatException) {
e.printStackTrace()
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show()
context.popToast(R.string.invalid_config)
return@Button
}
val proxyInfo =
@@ -1611,7 +1612,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
ProxyInfo.buildDirectProxy(proxyUri, port, exclList.lines())
}
if(VERSION.SDK_INT >= 30 && !proxyInfo.isValid) {
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show()
context.popToast(R.string.invalid_config)
return@Button
}
dpm.setRecommendedGlobalProxy(receiver, proxyInfo)

View File

@@ -30,7 +30,6 @@ import android.app.admin.DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY
import android.content.Context
import android.os.Build.VERSION
import android.os.UserManager
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
@@ -70,6 +69,7 @@ import com.bintianqi.owndroid.HorizontalPadding
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.SharedPrefs
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
@@ -269,7 +269,7 @@ fun ResetPasswordTokenScreen(onNavigateUp: () -> Unit) {
try {
context.showOperationResultToast(dpm.setResetPasswordToken(receiver, tokenByteArray))
} catch(_:SecurityException) {
Toast.makeText(context, R.string.security_exception, Toast.LENGTH_SHORT).show()
context.popToast(R.string.security_exception)
}
},
modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
@@ -285,8 +285,8 @@ fun ResetPasswordTokenScreen(onNavigateUp: () -> Unit) {
onClick = {
if(!dpm.isResetPasswordTokenActive(receiver)) {
try { activateToken(context) }
catch(_:NullPointerException) { Toast.makeText(context, R.string.please_set_a_token, Toast.LENGTH_SHORT).show() }
} else { Toast.makeText(context, R.string.token_already_activated, Toast.LENGTH_SHORT).show() }
catch(_:NullPointerException) { context.popToast(R.string.please_set_a_token) }
} else { context.popToast(R.string.token_already_activated) }
},
modifier = Modifier.fillMaxWidth(0.49F)
) {
@@ -560,6 +560,6 @@ private fun activateToken(context: Context) {
if (confirmIntent != null) {
startActivity(context,confirmIntent, null)
} else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
context.showOperationResultToast(false)
}
}

View File

@@ -32,7 +32,6 @@ import android.net.Uri
import android.os.Build.VERSION
import android.os.HardwarePropertiesManager
import android.os.UserManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
@@ -129,6 +128,7 @@ import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.parseDate
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog
@@ -313,7 +313,7 @@ fun SystemManagerScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
}
dialog = 0
} catch(_: IllegalStateException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
context.showOperationResultToast(false)
}
},
enabled = dialog != 4 || input.length in 6..64
@@ -362,7 +362,7 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
getState = { dpm.autoTimeRequired }, onCheckedChange = { dpm.setAutoTimeRequired(receiver,it) }, padding = false)
}
}
SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
if (!privilege.work) SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = {
dpm.setMasterVolumeMuted(receiver,it)
createShortcuts(context)
@@ -1056,7 +1056,7 @@ fun MtePolicyScreen(onNavigateUp: () -> Unit) {
dpm.mtePolicy = selectedMtePolicy
context.showOperationResultToast(true)
} catch(_: java.lang.UnsupportedOperationException) {
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show()
context.popToast(R.string.unsupported)
}
selectedMtePolicy = dpm.mtePolicy
},
@@ -1257,7 +1257,7 @@ private fun ColumnScope.StartLockTaskMode() {
onClick = {
if(!NotificationUtils.checkPermission(context)) return@Button
if(!dpm.isLockTaskPermitted(startLockTaskApp)) {
Toast.makeText(context, R.string.app_not_allowed, Toast.LENGTH_SHORT).show()
context.popToast(R.string.app_not_allowed)
return@Button
}
val options = ActivityOptions.makeBasic().setLockTaskEnabled(true)
@@ -1267,7 +1267,7 @@ private fun ColumnScope.StartLockTaskMode() {
if (launchIntent != null) {
context.startActivity(launchIntent, options.toBundle())
} else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
context.showOperationResultToast(false)
}
},
enabled = startLockTaskApp.isNotBlank() && (!specifyActivity || startLockTaskActivity.isNotBlank())
@@ -1457,7 +1457,7 @@ fun CaCertScreen(onNavigateUp: () -> Unit) {
},
floatingActionButton = {
FloatingActionButton({
Toast.makeText(context, R.string.select_ca_cert, Toast.LENGTH_SHORT).show()
context.popToast(R.string.select_ca_cert)
getCertLauncher.launch(arrayOf("*/*"))
}) {
Icon(Icons.Default.Add, stringResource(R.string.install))
@@ -1628,7 +1628,7 @@ fun SecurityLoggingScreen(onNavigateUp: () -> Unit) {
onClick = {
val logs = dpm.retrievePreRebootSecurityLogs(receiver)
if(logs == null) {
Toast.makeText(context, R.string.no_logs, Toast.LENGTH_SHORT).show()
context.popToast(R.string.no_logs)
return@Button
} else {
val outputStream = ByteArrayOutputStream()
@@ -2021,7 +2021,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
else -> R.string.unknown
}
val errMsg = context.getString(R.string.install_system_update_failed) + context.getString(errDetail)
Toast.makeText(context, errMsg, Toast.LENGTH_SHORT).show()
context.popToast(errMsg)
}
}
var uri by remember { mutableStateOf<Uri?>(null) }
@@ -2044,7 +2044,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
val executor = Executors.newCachedThreadPool()
try {
dpm.installSystemUpdate(receiver, uri!!, executor, callback)
Toast.makeText(context, R.string.start_install_system_update, Toast.LENGTH_SHORT).show()
context.popToast(R.string.start_install_system_update)
} catch(e: Exception) {
errorMessage = e.message
}

View File

@@ -1,14 +1,11 @@
package com.bintianqi.owndroid.dpm
import android.os.Build
import android.os.Bundle
import android.os.UserManager
import androidx.annotation.DrawableRes
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -16,8 +13,6 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@@ -27,14 +22,12 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.OutlinedTextField
@@ -66,10 +59,7 @@ import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.MyLazyScaffold
import com.bintianqi.owndroid.ui.MyScaffold
import com.bintianqi.owndroid.ui.NavIcon
import com.bintianqi.owndroid.ui.SwitchItem
import com.bintianqi.owndroid.zhCN
import kotlinx.serialization.Serializable
@Serializable

View File

@@ -9,7 +9,6 @@ import android.os.Build.VERSION
import android.os.Process
import android.os.UserHandle
import android.os.UserManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
@@ -66,6 +65,7 @@ import com.bintianqi.owndroid.HorizontalPadding
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.parseTimestamp
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CircularProgressDialog
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
@@ -117,7 +117,7 @@ fun UsersScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
}
}
FunctionItem(R.string.change_user_icon, icon = R.drawable.account_circle_fill0) {
Toast.makeText(context, R.string.select_an_image, Toast.LENGTH_SHORT).show()
context.popToast(R.string.select_an_image)
launcher.launch("image/*")
}
if(changeUserIconDialog) ChangeUserIconDialog(bitmap!!) { changeUserIconDialog = false }
@@ -149,7 +149,7 @@ fun UsersScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
onClick = {
if(dialog == 2) {
val result = dpm.logoutUser(receiver)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show()
context.popToast(userOperationResultCode(result))
}
dialog = 0
}
@@ -238,7 +238,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
userManager.getUserForSerialNumber(input.toLong())
}
if(userHandle == null) {
Toast.makeText(context, R.string.user_not_exist, Toast.LENGTH_SHORT).show()
context.popToast(R.string.user_not_exist)
} else {
operation(userHandle)
}
@@ -267,7 +267,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
focusMgr.clearFocus()
withUserHandle {
val result = dpm.startUserInBackground(receiver, it)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show()
context.popToast(userOperationResultCode(result))
}
},
enabled = legalInput,
@@ -294,7 +294,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
focusMgr.clearFocus()
withUserHandle {
val result = dpm.stopUser(receiver, it)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show()
context.popToast(userOperationResultCode(result))
}
},
enabled = legalInput,
@@ -312,7 +312,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
context.showOperationResultToast(true)
input = ""
} else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
context.showOperationResultToast(false)
}
}
},
@@ -373,9 +373,16 @@ fun CreateUserScreen(onNavigateUp: () -> Unit) {
withContext(Dispatchers.Main) {
createdUserSerialNumber = userManager.getSerialNumberForUser(uh)
}
} catch(_: Exception) {
} catch(e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
if (VERSION.SDK_INT >= 28 && e is UserManager.UserOperationException) {
context.popToast(e.message ?: context.getString(R.string.error))
} else {
context.showOperationResultToast(false)
}
}
}
withContext(Dispatchers.Main) { creating = false }
}
},

View File

@@ -19,7 +19,6 @@ import android.content.Intent
import android.content.IntentFilter
import android.os.Binder
import android.os.Build.VERSION
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
@@ -59,6 +58,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bintianqi.owndroid.IUserService
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FunctionItem
@@ -147,7 +147,7 @@ fun CreateWorkProfileScreen(onNavigateUp: () -> Unit) {
if(VERSION.SDK_INT >= 33) { intent.putExtra(EXTRA_PROVISIONING_ALLOW_OFFLINE, offlineProvisioning) }
launcher.launch(intent)
} catch(_: ActivityNotFoundException) {
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show()
context.popToast(R.string.unsupported)
}
},
modifier = Modifier.fillMaxWidth()