Fix bugs of application functions (#205, #206, #207)

This commit is contained in:
BinTianqi
2025-11-26 22:20:26 +08:00
parent ed6908a5cd
commit 001d013b0c
4 changed files with 78 additions and 31 deletions

View File

@@ -255,6 +255,9 @@ class MainActivity : FragmentActivity() {
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {} val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {}
launcher.launch(Manifest.permission.POST_NOTIFICATIONS) launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
} }
registerPackageRemovedReceiver(this) {
vm.onPackageRemoved(it)
}
setContent { setContent {
var appLockDialog by rememberSaveable { mutableStateOf(false) } var appLockDialog by rememberSaveable { mutableStateOf(false) }
val theme by vm.theme.collectAsStateWithLifecycle() val theme by vm.theme.collectAsStateWithLifecycle()

View File

@@ -200,6 +200,11 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
} }
} }
} }
fun onPackageRemoved(name: String) {
installedPackages.update { list ->
list.filter { it.name != name }
}
}
fun getAppInfo(info: ApplicationInfo) = fun getAppInfo(info: ApplicationInfo) =
AppInfo(info.packageName, info.loadLabel(PM).toString(), info.loadIcon(PM), info.flags) AppInfo(info.packageName, info.loadLabel(PM).toString(), info.loadIcon(PM), info.flags)
fun getAppInfo(name: String): AppInfo { fun getAppInfo(name: String): AppInfo {
@@ -361,9 +366,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
context.unregisterReceiver(this) context.unregisterReceiver(this)
if (statusExtra == PackageInstaller.STATUS_SUCCESS) { if (statusExtra == PackageInstaller.STATUS_SUCCESS) {
onComplete(null) onComplete(null)
installedPackages.update { pkg ->
pkg.filter { it.name != packageName }
}
} else { } else {
onComplete(parsePackageInstallerMessage(context, intent)) onComplete(parsePackageInstallerMessage(context, intent))
} }
@@ -464,14 +466,18 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
DPM.isUninstallBlocked(DAR, name), DPM.isUninstallBlocked(DAR, name),
if (VERSION.SDK_INT >= 30) name in DPM.getUserControlDisabledPackages(DAR) else false, if (VERSION.SDK_INT >= 30) name in DPM.getUserControlDisabledPackages(DAR) else false,
if (VERSION.SDK_INT >= 28) name in DPM.getMeteredDataDisabledPackages(DAR) else false, if (VERSION.SDK_INT >= 28) name in DPM.getMeteredDataDisabledPackages(DAR) else false,
if (VERSION.SDK_INT >= 28) DPM.getKeepUninstalledPackages(DAR)?.contains(name) == true else false if (VERSION.SDK_INT >= 28 && Privilege.status.value.device)
DPM.getKeepUninstalledPackages(DAR)?.contains(name) == true
else false
) )
} }
// Application details // Application details
@RequiresApi(24) @RequiresApi(24)
fun adSetPackageSuspended(name: String, status: Boolean) { fun adSetPackageSuspended(name: String, status: Boolean) {
try {
DPM.setPackagesSuspended(DAR, arrayOf(name), status) DPM.setPackagesSuspended(DAR, arrayOf(name), status)
appStatus.update { it.copy(suspend = DPM.isPackageSuspended(DAR, name)) } appStatus.update { it.copy(suspend = DPM.isPackageSuspended(DAR, name)) }
} catch (_: Exception) {}
} }
fun adSetPackageHidden(name: String, status: Boolean) { fun adSetPackageHidden(name: String, status: Boolean) {
DPM.setApplicationHidden(DAR, name, status) DPM.setApplicationHidden(DAR, name, status)
@@ -522,6 +528,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
@RequiresApi(23) @RequiresApi(23)
fun getAppRestrictions(name: String) { fun getAppRestrictions(name: String) {
val rm = application.getSystemService(RestrictionsManager::class.java) val rm = application.getSystemService(RestrictionsManager::class.java)
try {
val bundle = DPM.getApplicationRestrictions(DAR, name) val bundle = DPM.getApplicationRestrictions(DAR, name)
appRestrictions.value = rm.getManifestRestrictions(name)?.mapNotNull { appRestrictions.value = rm.getManifestRestrictions(name)?.mapNotNull {
transformRestrictionEntry(it) transformRestrictionEntry(it)
@@ -537,6 +544,9 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
} }
it it
} ?: emptyList() } ?: emptyList()
} catch (e: Exception) {
e.printStackTrace()
}
} }
@RequiresApi(23) @RequiresApi(23)

View File

@@ -1,9 +1,12 @@
package com.bintianqi.owndroid package com.bintianqi.owndroid
import android.content.BroadcastReceiver
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
@@ -160,3 +163,17 @@ fun adaptiveInsets(): WindowInsets {
val navbar = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal) val navbar = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
return WindowInsets.ime.union(navbar).union(WindowInsets.displayCutout) return WindowInsets.ime.union(navbar).union(WindowInsets.displayCutout)
} }
fun registerPackageRemovedReceiver(
ctx: Context, callback: (String) -> Unit
) {
val br = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
callback(intent.data!!.schemeSpecificPart)
}
}
val filter = IntentFilter()
filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
filter.addDataScheme("package")
ctx.registerReceiver(br, filter)
}

View File

@@ -14,7 +14,6 @@ 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.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -63,6 +62,9 @@ import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -121,7 +123,6 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState import sh.calvin.reorderable.rememberReorderableLazyListState
import kotlin.collections.indexOf
val String.isValidPackageName val String.isValidPackageName
get() = Regex("""^(?:[a-zA-Z]\w*\.)+[a-zA-Z]\w*$""").matches(this) get() = Regex("""^(?:[a-zA-Z]\w*\.)+[a-zA-Z]\w*$""").matches(this)
@@ -540,20 +541,23 @@ private fun UninstallAppDialog(
confirmButton = { confirmButton = {
TextButton( TextButton(
{ {
if (errorMessage == null) {
uninstalling = true uninstalling = true
onUninstall(packageName) { onUninstall(packageName) {
uninstalling = false uninstalling = false
if (it == null) onClose(true) else errorMessage = it if (it == null) onClose(true) else errorMessage = it
} }
} else {
onClose(false)
}
}, },
enabled = !uninstalling, enabled = !uninstalling
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
) { ) {
Text(stringResource(R.string.confirm)) Text(stringResource(R.string.confirm))
} }
}, },
dismissButton = { dismissButton = {
TextButton({ if (errorMessage == null) TextButton({
onClose(false) onClose(false)
}, enabled = !uninstalling) { Text(stringResource(R.string.cancel)) } }, enabled = !uninstalling) { Text(stringResource(R.string.cancel)) }
}, },
@@ -1254,7 +1258,20 @@ fun ManagedConfigurationDialog(
) )
} }
is AppRestriction.BooleanItem -> item { is AppRestriction.BooleanItem -> item {
Switch(inputState, { inputState = it }) SingleChoiceSegmentedButtonRow(Modifier.fillMaxWidth()) {
SegmentedButton(
inputState, { inputState = true },
SegmentedButtonDefaults.itemShape(0, 2)
) {
Text("true")
}
SegmentedButton(
!inputState, { inputState = false },
SegmentedButtonDefaults.itemShape(1, 2)
) {
Text("false")
}
}
} }
is AppRestriction.ChoiceItem -> itemsIndexed(restriction.entryValues) { index, value -> is AppRestriction.ChoiceItem -> itemsIndexed(restriction.entryValues) { index, value ->
val label = restriction.entries.getOrNull(index) val label = restriction.entries.getOrNull(index)