From 84bfecff08bfbcdd83cb9d8bf9ed634eb811697f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E5=88=BA=E8=9E=88?= Date: Mon, 18 May 2026 11:54:30 +0800 Subject: [PATCH] fix: can not receive ACTION_PACKAGE_ADDED --- app/src/main/kotlin/li/songe/gkd/App.kt | 2 + .../kotlin/li/songe/gkd/util/AppInfoState.kt | 77 +++++++++++++------ 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/app/src/main/kotlin/li/songe/gkd/App.kt b/app/src/main/kotlin/li/songe/gkd/App.kt index 953cf560..0f99c82a 100644 --- a/app/src/main/kotlin/li/songe/gkd/App.kt +++ b/app/src/main/kotlin/li/songe/gkd/App.kt @@ -9,6 +9,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.ApplicationInfo +import android.content.pm.LauncherApps import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.database.ContentObserver @@ -197,6 +198,7 @@ class App : Application() { val clipboardManager by lazy { app.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager } val powerManager by lazy { getSystemService(POWER_SERVICE) as PowerManager } val a11yManager by lazy { getSystemService(ACCESSIBILITY_SERVICE) as AccessibilityManager } + val launcherApps by lazy { getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps } val compatDisplay: Display get() = if (AndroidTarget.R) { diff --git a/app/src/main/kotlin/li/songe/gkd/util/AppInfoState.kt b/app/src/main/kotlin/li/songe/gkd/util/AppInfoState.kt index 923c3f80..4508db25 100644 --- a/app/src/main/kotlin/li/songe/gkd/util/AppInfoState.kt +++ b/app/src/main/kotlin/li/songe/gkd/util/AppInfoState.kt @@ -4,8 +4,10 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.LauncherApps import android.content.pm.PackageManager import android.graphics.drawable.Drawable +import android.os.UserHandle import androidx.core.content.ContextCompat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -60,33 +62,58 @@ val visibleAppInfosFlow by lazy { } } -private val willUpdateAppIds by lazy { MutableStateFlow(emptySet()) } +private val willUpdateAppIds = MutableStateFlow(emptySet()) -private val packageReceiver by lazy { - object : BroadcastReceiver() { - val actions = arrayOf( - Intent.ACTION_PACKAGE_ADDED, - Intent.ACTION_PACKAGE_REPLACED, - Intent.ACTION_PACKAGE_REMOVED - ) +private fun dispatchAppUpdate(appId: String) = willUpdateAppIds.update { it + appId } +private fun registerPackageListener() { + val packageReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - // PACKAGE_REMOVED->PACKAGE_ADDED->PACKAGE_REPLACED val appId = intent?.data?.schemeSpecificPart ?: return - willUpdateAppIds.update { it + appId } + dispatchAppUpdate(appId) } - }.apply { - val intentFilter = IntentFilter().apply { - actions.forEach { addAction(it) } - addDataScheme("package") - } - ContextCompat.registerReceiver( - app, - this, - intentFilter, - ContextCompat.RECEIVER_EXPORTED - ) } + ContextCompat.registerReceiver( + app, + packageReceiver, + IntentFilter().apply { + arrayOf( + Intent.ACTION_PACKAGE_ADDED, + Intent.ACTION_PACKAGE_REPLACED, + Intent.ACTION_PACKAGE_REMOVED, + ).forEach { addAction(it) } + addDataScheme("package") + }, + ContextCompat.RECEIVER_EXPORTED, + ) + + // 某些设备 ACTION_PACKAGE_ADDED 接收不到,使用 LauncherApps.Callback 作为补充 + val packageCallback = object : LauncherApps.Callback() { + override fun onPackageAdded(packageName: String, user: UserHandle) { + dispatchAppUpdate(packageName) + } + + override fun onPackageChanged(packageName: String, user: UserHandle) { + dispatchAppUpdate(packageName) + } + + override fun onPackageRemoved(packageName: String, user: UserHandle) { + dispatchAppUpdate(packageName) + } + + override fun onPackagesAvailable( + p0: Array, + p1: UserHandle, + p2: Boolean + ) = Unit + + override fun onPackagesUnavailable( + p0: Array, + p1: UserHandle, + p2: Boolean + ) = Unit + } + app.launcherApps.registerCallback(packageCallback) } const val PKG_FLAGS = PackageManager.MATCH_UNINSTALLED_PACKAGES @@ -134,6 +161,7 @@ private fun updatePartAppInfo( willUpdateAppIds.update { it - appIds } val newAppMap = HashMap(userAppInfoMapFlow.value) val newIconMap = HashMap(userAppIconMapFlow.value) + val oldMapSize = newAppMap.size appIds.forEach { appId -> val info = app.getPkgInfo(appId) if (info != null) { @@ -151,6 +179,11 @@ private fun updatePartAppInfo( updateOtherUserAppInfo(newAppMap) userAppInfoMapFlow.value = newAppMap userAppIconMapFlow.value = newIconMap + LogUtils.d( + "updatePartAppInfo", + "change=${appIds.map { (if (newAppMap.contains(it)) "+" else "-") + it }}", + "size=${oldMapSize}->${newAppMap.size}" + ) } val appListAuthAbnormalFlow = MutableStateFlow(false) @@ -224,7 +257,7 @@ fun updateAllAppInfo(): Unit = updateAppMutex.launchTry(appScope, Dispatchers.IO } fun initAppState() { - packageReceiver + registerPackageListener() updateAllAppInfo() appScope.launchTry { shizukuContextFlow.drop(1).collect {