Add fallback for system getInstalledPackages

This commit is contained in:
世界
2026-01-11 10:35:22 +08:00
parent cd83cbfe9e
commit 5e746241b2
6 changed files with 67 additions and 108 deletions

View File

@@ -61,7 +61,13 @@ class AppChangeReceiver : BroadcastReceiver() {
PackageManager.GET_ACTIVITIES or PackageManager.GET_SERVICES or
PackageManager.GET_RECEIVERS or PackageManager.GET_PROVIDERS
}
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags)
val retryFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
PackageManager.MATCH_UNINSTALLED_PACKAGES
} else {
@Suppress("DEPRECATION")
PackageManager.GET_UNINSTALLED_PACKAGES
}
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags, retryFlags)
val chinaApps = mutableSetOf<String>()
for (packageInfo in installedPackages) {
if (PerAppProxyScanner.scanChinaPackage(packageInfo)) {

View File

@@ -20,10 +20,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.ContentPaste
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.filled.FilterList
import androidx.compose.material.icons.filled.ManageSearch
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.SelectAll
@@ -63,7 +60,6 @@ import io.nekohasekai.sfa.compose.shared.AppSelectionCard
import io.nekohasekai.sfa.compose.shared.PackageCache
import io.nekohasekai.sfa.compose.shared.SortMode
import io.nekohasekai.sfa.compose.shared.buildDisplayPackages
import io.nekohasekai.sfa.compose.screen.profileoverride.PerAppProxyScanner
import io.nekohasekai.sfa.utils.PrivilegeSettingsClient
import io.nekohasekai.sfa.vendor.PackageQueryManager
import io.nekohasekai.sfa.vendor.PrivilegedAccessRequiredException
@@ -263,49 +259,19 @@ fun PrivilegeSettingsManageScreen(onBack: () -> Unit) {
postSaveSelectedApplications(newSelected)
}
fun startScanChinaApps() {
val scanPackages = currentPackages.toList()
if (scanPackages.isEmpty() || isLoading) return
isLoading = true
coroutineScope.launch {
val foundUids =
withContext(Dispatchers.Default) {
scanPackages.mapNotNull { packageCache ->
if (PerAppProxyScanner.scanChinaPackage(packageCache.info)) {
if (getRiskCategory(packageCache) != RiskCategory.NONE) {
null
} else {
packageCache.uid
}
} else {
null
}
}.toSet()
}
if (foundUids.isNotEmpty()) {
postSaveSelectedApplications(selectedUids + foundUids)
}
isLoading = false
}
}
LaunchedEffect(Unit) {
isLoading = true
val packageManagerFlags =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
PackageManager.GET_PERMISSIONS or PackageManager.MATCH_UNINSTALLED_PACKAGES or
PackageManager.GET_ACTIVITIES or PackageManager.GET_SERVICES or
PackageManager.GET_RECEIVERS or PackageManager.GET_PROVIDERS
PackageManager.GET_PERMISSIONS or PackageManager.MATCH_UNINSTALLED_PACKAGES
} else {
@Suppress("DEPRECATION")
PackageManager.GET_PERMISSIONS or PackageManager.GET_UNINSTALLED_PACKAGES or
PackageManager.GET_ACTIVITIES or PackageManager.GET_SERVICES or
PackageManager.GET_RECEIVERS or PackageManager.GET_PROVIDERS
PackageManager.GET_PERMISSIONS or PackageManager.GET_UNINSTALLED_PACKAGES
}
val loadResult =
withContext(Dispatchers.IO) {
try {
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags)
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags, packageManagerFlags)
val packageManager = context.packageManager
val packageCaches =
installedPackages.mapNotNull { packageInfo ->
@@ -424,9 +390,6 @@ fun PrivilegeSettingsManageScreen(onBack: () -> Unit) {
hideDisabledApps = !hideDisabledApps
applyFilter()
},
onScanChinaApps = {
startScanChinaApps()
},
onSelectAll = {
val newSelected = currentPackages.map { it.uid }.toSet()
postSaveSelectedApplications(newSelected)
@@ -594,7 +557,6 @@ private fun PrivilegeSettingsMenus(
onHideSystemAppsToggle: () -> Unit,
onHideOfflineAppsToggle: () -> Unit,
onHideDisabledAppsToggle: () -> Unit,
onScanChinaApps: () -> Unit,
onSelectAll: () -> Unit,
onDeselectAll: () -> Unit,
onImport: () -> Unit,
@@ -603,7 +565,6 @@ private fun PrivilegeSettingsMenus(
var showMainMenu by remember { mutableStateOf(false) }
var showSortMenu by remember { mutableStateOf(false) }
var showFilterMenu by remember { mutableStateOf(false) }
var showScanMenu by remember { mutableStateOf(false) }
var showSelectMenu by remember { mutableStateOf(false) }
var showBackupMenu by remember { mutableStateOf(false) }
@@ -617,7 +578,6 @@ private fun PrivilegeSettingsMenus(
showMainMenu = false
showSortMenu = false
showFilterMenu = false
showScanMenu = false
showSelectMenu = false
showBackupMenu = false
},
@@ -733,48 +693,6 @@ private fun PrivilegeSettingsMenus(
)
}
DropdownMenuItem(
text = { Text(stringResource(R.string.per_app_proxy_scan)) },
onClick = { showScanMenu = !showScanMenu },
leadingIcon = {
Icon(
imageVector = Icons.Default.ManageSearch,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
)
},
trailingIcon = {
Icon(
imageVector =
if (showScanMenu) {
Icons.Default.ExpandLess
} else {
Icons.Default.ExpandMore
},
contentDescription = null,
)
},
)
if (showScanMenu) {
DropdownMenuItem(
text = { Text(stringResource(R.string.per_app_proxy_scan_china_apps)) },
onClick = {
onScanChinaApps()
showMainMenu = false
showScanMenu = false
},
leadingIcon = {
Icon(
imageVector = Icons.Default.ManageSearch,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(start = 24.dp),
)
},
)
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
}
DropdownMenuItem(
text = { Text(stringResource(R.string.per_app_proxy_filter)) },
onClick = { showFilterMenu = !showFilterMenu },

View File

@@ -242,6 +242,13 @@ fun PerAppProxyScreen(onBack: () -> Unit) {
PackageManager.GET_ACTIVITIES or PackageManager.GET_SERVICES or
PackageManager.GET_RECEIVERS or PackageManager.GET_PROVIDERS
}
val retryFlags =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
PackageManager.MATCH_UNINSTALLED_PACKAGES
} else {
@Suppress("DEPRECATION")
PackageManager.GET_UNINSTALLED_PACKAGES
}
val loadResult =
withContext(Dispatchers.IO) {
try {
@@ -251,7 +258,7 @@ fun PerAppProxyScreen(onBack: () -> Unit) {
} else {
Settings.PER_APP_PROXY_EXCLUDE
}
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags)
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags, retryFlags)
val packageManager = context.packageManager
val packageCaches =
installedPackages.mapNotNull { packageInfo ->

View File

@@ -704,8 +704,14 @@ private suspend fun scanAllChinaApps(): Set<String> = withContext(Dispatchers.De
PackageManager.GET_ACTIVITIES or PackageManager.GET_SERVICES or
PackageManager.GET_RECEIVERS or PackageManager.GET_PROVIDERS
}
val retryFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
PackageManager.MATCH_UNINSTALLED_PACKAGES
} else {
@Suppress("DEPRECATION")
PackageManager.GET_UNINSTALLED_PACKAGES
}
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags)
val installedPackages = PackageQueryManager.getInstalledPackages(packageManagerFlags, retryFlags)
val chinaApps = mutableSetOf<String>()
installedPackages.map { packageInfo ->

View File

@@ -52,16 +52,17 @@ object PackageQueryManager {
_queryMode.value = mode
}
suspend fun getInstalledPackages(flags: Int): List<PackageInfo> {
suspend fun getInstalledPackages(flags: Int, retryFlags: Int): List<PackageInfo> {
return when (val s = strategy) {
is PackageQueryStrategy.ForcedRoot -> RootClient.getInstalledPackages(flags)
is PackageQueryStrategy.UserSelected -> RootClient.getInstalledPackages(flags)
is PackageQueryStrategy.Direct -> getPackagesViaPackageManager(flags)
is PackageQueryStrategy.Direct -> getPackagesViaPackageManager(flags, retryFlags)
}
}
private fun getPackagesViaPackageManager(flags: Int): List<PackageInfo> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
private fun getPackagesViaPackageManager(flags: Int, retryFlags: Int): List<PackageInfo> {
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Application.packageManager.getInstalledPackages(
PackageManager.PackageInfoFlags.of(flags.toLong())
)
@@ -69,5 +70,15 @@ object PackageQueryManager {
@Suppress("DEPRECATION")
Application.packageManager.getInstalledPackages(flags)
}
} catch (_: RuntimeException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Application.packageManager.getInstalledPackages(
PackageManager.PackageInfoFlags.of(retryFlags.toLong())
)
} else {
@Suppress("DEPRECATION")
Application.packageManager.getInstalledPackages(retryFlags)
}
}
}
}

View File

@@ -60,19 +60,20 @@ object PackageQueryManager {
_queryMode.value = mode
}
suspend fun getInstalledPackages(flags: Int): List<PackageInfo> {
suspend fun getInstalledPackages(flags: Int, retryFlags: Int): List<PackageInfo> {
return when (val s = strategy) {
is PackageQueryStrategy.ForcedRoot -> RootClient.getInstalledPackages(flags)
is PackageQueryStrategy.UserSelected -> when (s.mode) {
Settings.PACKAGE_QUERY_MODE_ROOT -> RootClient.getInstalledPackages(flags)
else -> ShizukuPackageManager.getInstalledPackages(flags)
}
is PackageQueryStrategy.Direct -> getPackagesViaPackageManager(flags)
is PackageQueryStrategy.Direct -> getPackagesViaPackageManager(flags, retryFlags)
}
}
private fun getPackagesViaPackageManager(flags: Int): List<PackageInfo> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
private fun getPackagesViaPackageManager(flags: Int, retryFlags: Int): List<PackageInfo> {
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Application.packageManager.getInstalledPackages(
PackageManager.PackageInfoFlags.of(flags.toLong())
)
@@ -80,5 +81,15 @@ object PackageQueryManager {
@Suppress("DEPRECATION")
Application.packageManager.getInstalledPackages(flags)
}
} catch (_: RuntimeException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Application.packageManager.getInstalledPackages(
PackageManager.PackageInfoFlags.of(retryFlags.toLong())
)
} else {
@Suppress("DEPRECATION")
Application.packageManager.getInstalledPackages(retryFlags)
}
}
}
}