From 9bd5e3f8e7ea65cbaec141d452311e0f1536d3f9 Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Sat, 30 May 2026 17:57:50 +0530 Subject: [PATCH] Stop per-app download notification chatter during installs The download worker posted a separate per-app notification for every internal phase transition, keyed by package hash and distinct from the ongoing foreground progress notification. In practice this meant: - a blank, non-dismissable notification while "purchasing" (no branch rendered it), and - a transient "download complete" notice for every app that was then immediately replaced by the install-success notification. During a bulk update this produced a burst of redundant notifications. Suppress the purchasing/verifying phases (the ongoing progress notification already conveys activity) and only surface completion when the user must act on it (apps that can't be installed silently get a tap-to-install notice). Silently-installable apps now go straight to a single "installed" notification. Also clear any stale per-app notification on these phases and on cancellation, fixing a leak where a cancelled download left its last notification behind, and refresh the foreground notification to an "Installing" state so the user sees a clean downloading -> installing progression instead of a download bar stuck at 100%. --- .../aurora/store/data/work/DownloadWorker.kt | 28 ++++++++++++++++++- .../com/aurora/store/util/NotificationUtil.kt | 9 ++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt index 260ae9de3..3a393ff9f 100644 --- a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt +++ b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt @@ -252,6 +252,10 @@ class DownloadWorker @AssistedInject constructor( private suspend fun onSuccess(): Result { return withContext(NonCancellable) { return@withContext try { + // Update the ongoing foreground notification to reflect the install phase, + // so the user sees a clean "Downloading -> Installing" progression instead of + // a stale download bar lingering at 100%. + notifyStatus(DownloadStatus.INSTALLING, isProgress = true) appInstaller.getPreferredInstaller(notifyOnFallback = true).install(download) Result.success() } catch (exception: Exception) { @@ -537,13 +541,35 @@ class DownloadWorker @AssistedInject constructor( downloadDao.updateStatus(download.packageName, status) when (status) { + // Internal phases the user doesn't need a separate notification for: the ongoing + // foreground progress notification already conveys that work is in progress. + // Clear any stale per-app notification (e.g. a prior failure being retried) so it + // doesn't linger. + DownloadStatus.PURCHASING, DownloadStatus.VERIFYING, - DownloadStatus.CANCELLED -> return + DownloadStatus.CANCELLED -> { + notificationManager.cancel(download.packageName.hashCode()) + return + } DownloadStatus.COMPLETED -> { // Mark progress as 100 manually to avoid race conditions download.progress = 100 downloadDao.updateProgress(download.packageName, 100, 0, 0) + + // Silently-installable apps install automatically and get a single + // "installed" notification afterwards, so a separate "download complete" + // notice is just noise. Only surface completion when the user must act on it + // (tap to install). + val needsUserAction = !AppInstaller.canInstallSilently( + context, + download.packageName, + download.targetSdk + ) + if (!needsUserAction) { + notificationManager.cancel(download.packageName.hashCode()) + return + } } else -> {} diff --git a/app/src/main/java/com/aurora/store/util/NotificationUtil.kt b/app/src/main/java/com/aurora/store/util/NotificationUtil.kt index a75b276d0..48085c60e 100644 --- a/app/src/main/java/com/aurora/store/util/NotificationUtil.kt +++ b/app/src/main/java/com/aurora/store/util/NotificationUtil.kt @@ -208,6 +208,15 @@ object NotificationUtil { ) } + DownloadStatus.INSTALLING -> { + builder.setSmallIcon(android.R.drawable.stat_sys_download_done) + builder.setContentText(context.getString(R.string.status_installing)) + builder.setOngoing(true) + builder.setCategory(Notification.CATEGORY_PROGRESS) + builder.setProgress(100, 100, true) + builder.foregroundServiceBehavior = NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE + } + else -> {} } return builder.build()