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

View File

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

View File

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

View File

@@ -7,7 +7,6 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
@@ -132,7 +131,7 @@ fun AppChooserScreen(params: ApplicationsList, onChoosePackage: (String?) -> Uni
} }
IconButton({ IconButton({
system = !system 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) 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.PersistableBundle
import android.os.UserHandle import android.os.UserHandle
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.bintianqi.owndroid.dpm.handleNetworkLogs import com.bintianqi.owndroid.dpm.handleNetworkLogs
import com.bintianqi.owndroid.dpm.handlePrivilegeChange import com.bintianqi.owndroid.dpm.handlePrivilegeChange
@@ -48,7 +47,7 @@ class Receiver : DeviceAdminReceiver() {
override fun onProfileProvisioningComplete(context: Context, intent: Intent) { override fun onProfileProvisioningComplete(context: Context, intent: Intent) {
super.onProfileProvisioningComplete(context, 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) { 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.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.widget.Toast
import androidx.annotation.Keep import androidx.annotation.Keep
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
import rikka.sui.Sui import rikka.sui.Sui
@@ -54,12 +53,12 @@ fun useShizuku(context: Context, action: (IBinder?) -> Unit) {
if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
Shizuku.bindUserService(getShizukuArgs(context), connection) Shizuku.bindUserService(getShizukuArgs(context), connection)
} else if(Shizuku.shouldShowRequestPermissionRationale()) { } else if(Shizuku.shouldShowRequestPermissionRationale()) {
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_SHORT).show() context.popToast(R.string.permission_denied)
} else { } else {
Sui.init(context.packageName) Sui.init(context.packageName)
fun requestPermissionResultListener(requestCode: Int, grantResult: Int) { fun requestPermissionResultListener(requestCode: Int, grantResult: Int) {
if(grantResult != PackageManager.PERMISSION_GRANTED) { 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) Shizuku.removeRequestPermissionResultListener(::requestPermissionResultListener)
} }

View File

@@ -43,8 +43,8 @@ fun uriToStream(
operation(it) operation(it)
} }
} }
catch(_: FileNotFoundException) { Toast.makeText(context, R.string.file_not_exist, Toast.LENGTH_SHORT).show() } catch(_: FileNotFoundException) { context.popToast(R.string.file_not_exist) }
catch(_: IOException) { Toast.makeText(context, R.string.io_exception, Toast.LENGTH_SHORT).show() } catch(_: IOException) { context.popToast(R.string.io_exception) }
} }
fun writeClipBoard(context: Context, string: String):Boolean{ 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)) = SimpleDateFormat(pattern, Locale.getDefault()).format(Date(value))
fun Context.showOperationResultToast(success: Boolean) { 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" const val APK_MIME = "application/vnd.android.package-archive"
@@ -143,3 +143,11 @@ fun getPackageSignature(info: PackageInfo): String? {
return signatures?.firstOrNull()?.toByteArray() return signatures?.firstOrNull()?.toByteArray()
?.let { MessageDigest.getInstance("SHA-256").digest(it) }?.toHexString() ?.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.Build.VERSION
import android.os.Bundle import android.os.Bundle
import android.telephony.data.ApnSetting import android.telephony.data.ApnSetting
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@@ -135,6 +134,7 @@ import com.bintianqi.owndroid.formatDate
import com.bintianqi.owndroid.formatFileSize import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.humanReadableDate import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.myPrivilege import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog import com.bintianqi.owndroid.ui.ErrorDialog
@@ -1396,27 +1396,29 @@ fun PrivateDnsScreen(onNavigateUp: () -> Unit) {
val receiver = context.getReceiver() val receiver = context.getReceiver()
val focusMgr = LocalFocusManager.current val focusMgr = LocalFocusManager.current
MyScaffold(R.string.private_dns, onNavigateUp) { MyScaffold(R.string.private_dns, onNavigateUp) {
val dnsStatus = mapOf( fun getDnsStatus(code: Int) = when (code) {
PRIVATE_DNS_MODE_UNKNOWN to stringResource(R.string.unknown), PRIVATE_DNS_MODE_UNKNOWN -> R.string.unknown
PRIVATE_DNS_MODE_OFF to stringResource(R.string.disabled), PRIVATE_DNS_MODE_OFF -> R.string.disabled
PRIVATE_DNS_MODE_OPPORTUNISTIC to stringResource(R.string.auto), PRIVATE_DNS_MODE_OPPORTUNISTIC -> R.string.auto
PRIVATE_DNS_MODE_PROVIDER_HOSTNAME to stringResource(R.string.dns_provide_hostname) PRIVATE_DNS_MODE_PROVIDER_HOSTNAME -> R.string.dns_provide_hostname
) else -> R.string.place_holder
val operationResult = mapOf( }
PRIVATE_DNS_SET_NO_ERROR to stringResource(R.string.success), fun getOperationResult(code: Int) = when (code) {
PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING to stringResource(R.string.host_not_serving_dns_tls), PRIVATE_DNS_SET_NO_ERROR -> R.string.success
PRIVATE_DNS_SET_ERROR_FAILURE_SETTING to stringResource(R.string.failed) PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING -> R.string.host_not_serving_dns_tls
) PRIVATE_DNS_SET_ERROR_FAILURE_SETTING -> R.string.failed
var status by remember { mutableStateOf(dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)]) } else -> R.string.place_holder
}
var dnsMode by remember { mutableIntStateOf(dpm.getGlobalPrivateDnsMode(receiver)) }
Spacer(Modifier.padding(vertical = 5.dp)) 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) { AnimatedVisibility(visible = dpm.getGlobalPrivateDnsMode(receiver)!=PRIVATE_DNS_MODE_OPPORTUNISTIC) {
Spacer(Modifier.padding(vertical = 5.dp)) Spacer(Modifier.padding(vertical = 5.dp))
Button( Button(
onClick = { onClick = {
val result = dpm.setGlobalPrivateDnsModeOpportunistic(receiver) val result = dpm.setGlobalPrivateDnsModeOpportunistic(receiver)
Toast.makeText(context, operationResult[result], Toast.LENGTH_SHORT).show() context.popToast(getOperationResult(result))
status = dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)] dnsMode = dpm.getGlobalPrivateDnsMode(receiver)
}, },
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
@@ -1438,18 +1440,17 @@ fun PrivateDnsScreen(onNavigateUp: () -> Unit) {
Button( Button(
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
val result: Int
try { try {
result = dpm.setGlobalPrivateDnsModeSpecifiedHost(receiver,inputHost) val result = dpm.setGlobalPrivateDnsModeSpecifiedHost(receiver,inputHost)
Toast.makeText(context, operationResult[result], Toast.LENGTH_SHORT).show() context.popToast(getOperationResult(result))
} catch(e: IllegalArgumentException) { } catch(e: IllegalArgumentException) {
e.printStackTrace() e.printStackTrace()
Toast.makeText(context, R.string.invalid_hostname, Toast.LENGTH_SHORT).show() context.popToast(R.string.invalid_hostname)
} catch(e: SecurityException) { } catch(e: SecurityException) {
e.printStackTrace() e.printStackTrace()
Toast.makeText(context, R.string.security_exception, Toast.LENGTH_SHORT).show() context.popToast(R.string.security_exception)
} finally { } finally {
status = dnsStatus[dpm.getGlobalPrivateDnsMode(receiver)] dnsMode = dpm.getGlobalPrivateDnsMode(receiver)
} }
}, },
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
@@ -1483,11 +1484,11 @@ fun AlwaysOnVpnPackageScreen(onNavigateUp: () -> Unit) {
true true
} catch(e: UnsupportedOperationException) { } catch(e: UnsupportedOperationException) {
e.printStackTrace() e.printStackTrace()
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show() context.popToast(R.string.unsupported)
false false
} catch(e: NameNotFoundException) { } catch(e: NameNotFoundException) {
e.printStackTrace() e.printStackTrace()
Toast.makeText(context, R.string.not_installed, Toast.LENGTH_SHORT).show() context.popToast(R.string.not_installed)
false false
} }
} }
@@ -1588,7 +1589,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
return@Button return@Button
} }
if(proxyUri == "") { if(proxyUri == "") {
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show() context.popToast(R.string.invalid_config)
return@Button return@Button
} }
val uri = proxyUri.toUri() val uri = proxyUri.toUri()
@@ -1597,7 +1598,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
port = proxyPort.toInt() port = proxyPort.toInt()
} catch(e: NumberFormatException) { } catch(e: NumberFormatException) {
e.printStackTrace() e.printStackTrace()
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show() context.popToast(R.string.invalid_config)
return@Button return@Button
} }
val proxyInfo = val proxyInfo =
@@ -1611,7 +1612,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
ProxyInfo.buildDirectProxy(proxyUri, port, exclList.lines()) ProxyInfo.buildDirectProxy(proxyUri, port, exclList.lines())
} }
if(VERSION.SDK_INT >= 30 && !proxyInfo.isValid) { 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 return@Button
} }
dpm.setRecommendedGlobalProxy(receiver, proxyInfo) 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.content.Context
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@@ -70,6 +69,7 @@ import com.bintianqi.owndroid.HorizontalPadding
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.SharedPrefs import com.bintianqi.owndroid.SharedPrefs
import com.bintianqi.owndroid.myPrivilege import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
@@ -269,7 +269,7 @@ fun ResetPasswordTokenScreen(onNavigateUp: () -> Unit) {
try { try {
context.showOperationResultToast(dpm.setResetPasswordToken(receiver, tokenByteArray)) context.showOperationResultToast(dpm.setResetPasswordToken(receiver, tokenByteArray))
} catch(_:SecurityException) { } 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), modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
@@ -285,8 +285,8 @@ fun ResetPasswordTokenScreen(onNavigateUp: () -> Unit) {
onClick = { onClick = {
if(!dpm.isResetPasswordTokenActive(receiver)) { if(!dpm.isResetPasswordTokenActive(receiver)) {
try { activateToken(context) } try { activateToken(context) }
catch(_:NullPointerException) { Toast.makeText(context, R.string.please_set_a_token, Toast.LENGTH_SHORT).show() } catch(_:NullPointerException) { context.popToast(R.string.please_set_a_token) }
} else { Toast.makeText(context, R.string.token_already_activated, Toast.LENGTH_SHORT).show() } } else { context.popToast(R.string.token_already_activated) }
}, },
modifier = Modifier.fillMaxWidth(0.49F) modifier = Modifier.fillMaxWidth(0.49F)
) { ) {
@@ -560,6 +560,6 @@ private fun activateToken(context: Context) {
if (confirmIntent != null) { if (confirmIntent != null) {
startActivity(context,confirmIntent, null) startActivity(context,confirmIntent, null)
} else { } 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.Build.VERSION
import android.os.HardwarePropertiesManager import android.os.HardwarePropertiesManager
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@@ -129,6 +128,7 @@ import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.humanReadableDate import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.myPrivilege import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.parseDate import com.bintianqi.owndroid.parseDate
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog import com.bintianqi.owndroid.ui.ErrorDialog
@@ -313,7 +313,7 @@ fun SystemManagerScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
} }
dialog = 0 dialog = 0
} catch(_: IllegalStateException) { } catch(_: IllegalStateException) {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show() context.showOperationResultToast(false)
} }
}, },
enabled = dialog != 4 || input.length in 6..64 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) 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 = { getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = {
dpm.setMasterVolumeMuted(receiver,it) dpm.setMasterVolumeMuted(receiver,it)
createShortcuts(context) createShortcuts(context)
@@ -1056,7 +1056,7 @@ fun MtePolicyScreen(onNavigateUp: () -> Unit) {
dpm.mtePolicy = selectedMtePolicy dpm.mtePolicy = selectedMtePolicy
context.showOperationResultToast(true) context.showOperationResultToast(true)
} catch(_: java.lang.UnsupportedOperationException) { } catch(_: java.lang.UnsupportedOperationException) {
Toast.makeText(context, R.string.unsupported, Toast.LENGTH_SHORT).show() context.popToast(R.string.unsupported)
} }
selectedMtePolicy = dpm.mtePolicy selectedMtePolicy = dpm.mtePolicy
}, },
@@ -1257,7 +1257,7 @@ private fun ColumnScope.StartLockTaskMode() {
onClick = { onClick = {
if(!NotificationUtils.checkPermission(context)) return@Button if(!NotificationUtils.checkPermission(context)) return@Button
if(!dpm.isLockTaskPermitted(startLockTaskApp)) { 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 return@Button
} }
val options = ActivityOptions.makeBasic().setLockTaskEnabled(true) val options = ActivityOptions.makeBasic().setLockTaskEnabled(true)
@@ -1267,7 +1267,7 @@ private fun ColumnScope.StartLockTaskMode() {
if (launchIntent != null) { if (launchIntent != null) {
context.startActivity(launchIntent, options.toBundle()) context.startActivity(launchIntent, options.toBundle())
} else { } else {
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show() context.showOperationResultToast(false)
} }
}, },
enabled = startLockTaskApp.isNotBlank() && (!specifyActivity || startLockTaskActivity.isNotBlank()) enabled = startLockTaskApp.isNotBlank() && (!specifyActivity || startLockTaskActivity.isNotBlank())
@@ -1457,7 +1457,7 @@ fun CaCertScreen(onNavigateUp: () -> Unit) {
}, },
floatingActionButton = { floatingActionButton = {
FloatingActionButton({ FloatingActionButton({
Toast.makeText(context, R.string.select_ca_cert, Toast.LENGTH_SHORT).show() context.popToast(R.string.select_ca_cert)
getCertLauncher.launch(arrayOf("*/*")) getCertLauncher.launch(arrayOf("*/*"))
}) { }) {
Icon(Icons.Default.Add, stringResource(R.string.install)) Icon(Icons.Default.Add, stringResource(R.string.install))
@@ -1628,7 +1628,7 @@ fun SecurityLoggingScreen(onNavigateUp: () -> Unit) {
onClick = { onClick = {
val logs = dpm.retrievePreRebootSecurityLogs(receiver) val logs = dpm.retrievePreRebootSecurityLogs(receiver)
if(logs == null) { if(logs == null) {
Toast.makeText(context, R.string.no_logs, Toast.LENGTH_SHORT).show() context.popToast(R.string.no_logs)
return@Button return@Button
} else { } else {
val outputStream = ByteArrayOutputStream() val outputStream = ByteArrayOutputStream()
@@ -2021,7 +2021,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
else -> R.string.unknown else -> R.string.unknown
} }
val errMsg = context.getString(R.string.install_system_update_failed) + context.getString(errDetail) 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) } var uri by remember { mutableStateOf<Uri?>(null) }
@@ -2044,7 +2044,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
val executor = Executors.newCachedThreadPool() val executor = Executors.newCachedThreadPool()
try { try {
dpm.installSystemUpdate(receiver, uri!!, executor, callback) 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) { } catch(e: Exception) {
errorMessage = e.message errorMessage = e.message
} }

View File

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

View File

@@ -9,7 +9,6 @@ import android.os.Build.VERSION
import android.os.Process import android.os.Process
import android.os.UserHandle import android.os.UserHandle
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@@ -66,6 +65,7 @@ import com.bintianqi.owndroid.HorizontalPadding
import com.bintianqi.owndroid.R import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.myPrivilege import com.bintianqi.owndroid.myPrivilege
import com.bintianqi.owndroid.parseTimestamp import com.bintianqi.owndroid.parseTimestamp
import com.bintianqi.owndroid.popToast
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CircularProgressDialog import com.bintianqi.owndroid.ui.CircularProgressDialog
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem 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) { 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/*") launcher.launch("image/*")
} }
if(changeUserIconDialog) ChangeUserIconDialog(bitmap!!) { changeUserIconDialog = false } if(changeUserIconDialog) ChangeUserIconDialog(bitmap!!) { changeUserIconDialog = false }
@@ -149,7 +149,7 @@ fun UsersScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
onClick = { onClick = {
if(dialog == 2) { if(dialog == 2) {
val result = dpm.logoutUser(receiver) val result = dpm.logoutUser(receiver)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show() context.popToast(userOperationResultCode(result))
} }
dialog = 0 dialog = 0
} }
@@ -238,7 +238,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
userManager.getUserForSerialNumber(input.toLong()) userManager.getUserForSerialNumber(input.toLong())
} }
if(userHandle == null) { if(userHandle == null) {
Toast.makeText(context, R.string.user_not_exist, Toast.LENGTH_SHORT).show() context.popToast(R.string.user_not_exist)
} else { } else {
operation(userHandle) operation(userHandle)
} }
@@ -267,7 +267,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
focusMgr.clearFocus() focusMgr.clearFocus()
withUserHandle { withUserHandle {
val result = dpm.startUserInBackground(receiver, it) val result = dpm.startUserInBackground(receiver, it)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show() context.popToast(userOperationResultCode(result))
} }
}, },
enabled = legalInput, enabled = legalInput,
@@ -294,7 +294,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
focusMgr.clearFocus() focusMgr.clearFocus()
withUserHandle { withUserHandle {
val result = dpm.stopUser(receiver, it) val result = dpm.stopUser(receiver, it)
Toast.makeText(context, userOperationResultCode(result), Toast.LENGTH_SHORT).show() context.popToast(userOperationResultCode(result))
} }
}, },
enabled = legalInput, enabled = legalInput,
@@ -312,7 +312,7 @@ fun UserOperationScreen(onNavigateUp: () -> Unit) {
context.showOperationResultToast(true) context.showOperationResultToast(true)
input = "" input = ""
} else { } 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) { withContext(Dispatchers.Main) {
createdUserSerialNumber = userManager.getSerialNumberForUser(uh) 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) context.showOperationResultToast(false)
} }
}
}
withContext(Dispatchers.Main) { creating = false } withContext(Dispatchers.Main) { creating = false }
} }
}, },

View File

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