From 13900deda0aa595ae1e8460e0e5771256189a470 Mon Sep 17 00:00:00 2001 From: dev-12 Date: Mon, 19 Jan 2026 18:03:18 +0530 Subject: [PATCH] fix: removed stalled app entry from database on app start Fixed an issue where apps could remain stuck in the installing state. Previously, users could not exit this state without clearing app data. This new validation now identifies and removes outdated or stalled installation entries from the database. --- .../foundation/e/apps/AppLoungeApplication.kt | 40 +++++++++++++++++++ .../e/apps/data/install/AppInstallDAO.kt | 3 ++ .../installProcessor/FakeAppInstallDAO.kt | 4 ++ 3 files changed, 47 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt index 6adbcb225..b13c12c69 100644 --- a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt +++ b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt @@ -28,8 +28,11 @@ import androidx.work.ExistingPeriodicWorkPolicy import dagger.hilt.android.HiltAndroidApp import foundation.e.apps.data.Constants.TAG_APP_INSTALL_STATE import foundation.e.apps.data.Constants.TAG_AUTHDATA_DUMP +import foundation.e.apps.data.enums.Status +import foundation.e.apps.data.install.AppInstallDAO import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.data.preference.AppLoungePreference +import foundation.e.apps.di.qualifiers.IoCoroutineScope import foundation.e.apps.install.pkg.AppLoungePackageManager import foundation.e.apps.install.pkg.PkgManagerBR import foundation.e.apps.install.updates.UpdatesWorkManager @@ -37,6 +40,7 @@ import foundation.e.apps.install.workmanager.InstallWorkManager import foundation.e.apps.ui.setup.tos.TOS_VERSION import foundation.e.apps.utils.CustomUncaughtExceptionHandler import foundation.e.lib.telemetry.Telemetry +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.first @@ -63,9 +67,16 @@ class AppLoungeApplication : Application(), Configuration.Provider { @Inject lateinit var appLoungePreference: AppLoungePreference + @Inject + lateinit var appInstallDao: AppInstallDAO + @Inject lateinit var uncaughtExceptionHandler: CustomUncaughtExceptionHandler + @Inject + @IoCoroutineScope + lateinit var coroutineScope: CoroutineScope + @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate() { super.onCreate() @@ -109,6 +120,35 @@ class AppLoungeApplication : Application(), Configuration.Provider { appLoungePreference.getUpdateInterval(), ExistingPeriodicWorkPolicy.KEEP ) + + removeStalledInstallationFromDb() + } + + private fun removeStalledInstallationFromDb() = coroutineScope.launch { + val existingInstallations = appInstallDao.getItemInInstallation().toMutableList() + if (existingInstallations.isEmpty()) { + return@launch + } + val validPackageSession = packageManager.packageInstaller.allSessions + .filter { !it.isActive } + .mapNotNull { info -> info.appPackageName } + + if (validPackageSession.isNotEmpty()) { + existingInstallations.removeIf { validPackageSession.contains(it.packageName) } + } + + if (existingInstallations.isEmpty()) { + Timber.d("All packages have corresponding sessions;") + return@launch + } + + Timber.e("removing ${existingInstallations.size} app from db stuck at installing") + for (appInstall in existingInstallations) { + Timber.d("removing (${appInstall.packageName}) : (${appInstall.id}) from db") + + appInstall.status = Status.INSTALLATION_ISSUE + appInstallDao.deleteDownload(appInstall) + } } override val workManagerConfiguration: Configuration diff --git a/app/src/main/java/foundation/e/apps/data/install/AppInstallDAO.kt b/app/src/main/java/foundation/e/apps/data/install/AppInstallDAO.kt index a68090c24..f008b96b3 100644 --- a/app/src/main/java/foundation/e/apps/data/install/AppInstallDAO.kt +++ b/app/src/main/java/foundation/e/apps/data/install/AppInstallDAO.kt @@ -27,6 +27,9 @@ interface AppInstallDAO { @Query("SELECT * FROM fuseddownload where id = :id") fun getDownloadFlowById(id: String): LiveData + @Query("SELECT * FROM fuseddownload where status = 'INSTALLING'") + suspend fun getItemInInstallation(): List + @Update suspend fun updateDownload(appInstall: AppInstall) diff --git a/app/src/test/java/foundation/e/apps/installProcessor/FakeAppInstallDAO.kt b/app/src/test/java/foundation/e/apps/installProcessor/FakeAppInstallDAO.kt index a592e2688..93fc563e2 100644 --- a/app/src/test/java/foundation/e/apps/installProcessor/FakeAppInstallDAO.kt +++ b/app/src/test/java/foundation/e/apps/installProcessor/FakeAppInstallDAO.kt @@ -63,4 +63,8 @@ class FakeAppInstallDAO : AppInstallDAO { override suspend fun deleteDownload(appInstall: AppInstall) { appInstallList.remove(appInstall) } + + override suspend fun getItemInInstallation(): List { + return emptyList() + } } -- GitLab