mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 02:56:01 +00:00
@@ -255,6 +255,9 @@ class MainActivity : FragmentActivity() {
|
||||
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {}
|
||||
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
registerPackageRemovedReceiver(this) {
|
||||
vm.onPackageRemoved(it)
|
||||
}
|
||||
setContent {
|
||||
var appLockDialog by rememberSaveable { mutableStateOf(false) }
|
||||
val theme by vm.theme.collectAsStateWithLifecycle()
|
||||
|
||||
@@ -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) =
|
||||
AppInfo(info.packageName, info.loadLabel(PM).toString(), info.loadIcon(PM), info.flags)
|
||||
fun getAppInfo(name: String): AppInfo {
|
||||
@@ -361,9 +366,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
context.unregisterReceiver(this)
|
||||
if (statusExtra == PackageInstaller.STATUS_SUCCESS) {
|
||||
onComplete(null)
|
||||
installedPackages.update { pkg ->
|
||||
pkg.filter { it.name != packageName }
|
||||
}
|
||||
} else {
|
||||
onComplete(parsePackageInstallerMessage(context, intent))
|
||||
}
|
||||
@@ -464,14 +466,18 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
DPM.isUninstallBlocked(DAR, name),
|
||||
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) 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
|
||||
@RequiresApi(24)
|
||||
fun adSetPackageSuspended(name: String, status: Boolean) {
|
||||
DPM.setPackagesSuspended(DAR, arrayOf(name), status)
|
||||
appStatus.update { it.copy(suspend = DPM.isPackageSuspended(DAR, name)) }
|
||||
try {
|
||||
DPM.setPackagesSuspended(DAR, arrayOf(name), status)
|
||||
appStatus.update { it.copy(suspend = DPM.isPackageSuspended(DAR, name)) }
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
fun adSetPackageHidden(name: String, status: Boolean) {
|
||||
DPM.setApplicationHidden(DAR, name, status)
|
||||
@@ -522,21 +528,25 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
@RequiresApi(23)
|
||||
fun getAppRestrictions(name: String) {
|
||||
val rm = application.getSystemService(RestrictionsManager::class.java)
|
||||
val bundle = DPM.getApplicationRestrictions(DAR, name)
|
||||
appRestrictions.value = rm.getManifestRestrictions(name)?.mapNotNull {
|
||||
transformRestrictionEntry(it)
|
||||
}?.map {
|
||||
if (bundle.containsKey(it.key)) {
|
||||
when (it) {
|
||||
is AppRestriction.BooleanItem -> it.value = bundle.getBoolean(it.key)
|
||||
is AppRestriction.StringItem -> it.value = bundle.getString(it.key)
|
||||
is AppRestriction.IntItem -> it.value = bundle.getInt(it.key)
|
||||
is AppRestriction.ChoiceItem -> it.value = bundle.getString(it.key)
|
||||
is AppRestriction.MultiSelectItem -> it.value = bundle.getStringArray(it.key)
|
||||
try {
|
||||
val bundle = DPM.getApplicationRestrictions(DAR, name)
|
||||
appRestrictions.value = rm.getManifestRestrictions(name)?.mapNotNull {
|
||||
transformRestrictionEntry(it)
|
||||
}?.map {
|
||||
if (bundle.containsKey(it.key)) {
|
||||
when (it) {
|
||||
is AppRestriction.BooleanItem -> it.value = bundle.getBoolean(it.key)
|
||||
is AppRestriction.StringItem -> it.value = bundle.getString(it.key)
|
||||
is AppRestriction.IntItem -> it.value = bundle.getInt(it.key)
|
||||
is AppRestriction.ChoiceItem -> it.value = bundle.getString(it.key)
|
||||
is AppRestriction.MultiSelectItem -> it.value = bundle.getStringArray(it.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
it
|
||||
} ?: emptyList()
|
||||
it
|
||||
} ?: emptyList()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(23)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageInfo
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
@@ -159,4 +162,18 @@ fun Modifier.clickableTextField(onClick: () -> Unit) =
|
||||
fun adaptiveInsets(): WindowInsets {
|
||||
val navbar = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ 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.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
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.RadioButton
|
||||
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.Switch
|
||||
import androidx.compose.material3.Text
|
||||
@@ -121,7 +123,6 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||
import kotlin.collections.indexOf
|
||||
|
||||
val String.isValidPackageName
|
||||
get() = Regex("""^(?:[a-zA-Z]\w*\.)+[a-zA-Z]\w*$""").matches(this)
|
||||
@@ -540,20 +541,23 @@ private fun UninstallAppDialog(
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
{
|
||||
uninstalling = true
|
||||
onUninstall(packageName) {
|
||||
uninstalling = false
|
||||
if (it == null) onClose(true) else errorMessage = it
|
||||
if (errorMessage == null) {
|
||||
uninstalling = true
|
||||
onUninstall(packageName) {
|
||||
uninstalling = false
|
||||
if (it == null) onClose(true) else errorMessage = it
|
||||
}
|
||||
} else {
|
||||
onClose(false)
|
||||
}
|
||||
},
|
||||
enabled = !uninstalling,
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
||||
enabled = !uninstalling
|
||||
) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton({
|
||||
if (errorMessage == null) TextButton({
|
||||
onClose(false)
|
||||
}, enabled = !uninstalling) { Text(stringResource(R.string.cancel)) }
|
||||
},
|
||||
@@ -1254,7 +1258,20 @@ fun ManagedConfigurationDialog(
|
||||
)
|
||||
}
|
||||
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 ->
|
||||
val label = restriction.entries.getOrNull(index)
|
||||
|
||||
Reference in New Issue
Block a user