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%.
This commit is contained in:
@@ -252,6 +252,10 @@ class DownloadWorker @AssistedInject constructor(
|
|||||||
private suspend fun onSuccess(): Result {
|
private suspend fun onSuccess(): Result {
|
||||||
return withContext(NonCancellable) {
|
return withContext(NonCancellable) {
|
||||||
return@withContext try {
|
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)
|
appInstaller.getPreferredInstaller(notifyOnFallback = true).install(download)
|
||||||
Result.success()
|
Result.success()
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
@@ -537,13 +541,35 @@ class DownloadWorker @AssistedInject constructor(
|
|||||||
downloadDao.updateStatus(download.packageName, status)
|
downloadDao.updateStatus(download.packageName, status)
|
||||||
|
|
||||||
when (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.VERIFYING,
|
||||||
DownloadStatus.CANCELLED -> return
|
DownloadStatus.CANCELLED -> {
|
||||||
|
notificationManager.cancel(download.packageName.hashCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
DownloadStatus.COMPLETED -> {
|
DownloadStatus.COMPLETED -> {
|
||||||
// Mark progress as 100 manually to avoid race conditions
|
// Mark progress as 100 manually to avoid race conditions
|
||||||
download.progress = 100
|
download.progress = 100
|
||||||
downloadDao.updateProgress(download.packageName, 100, 0, 0)
|
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 -> {}
|
else -> {}
|
||||||
|
|||||||
@@ -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 -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
return builder.build()
|
return builder.build()
|
||||||
|
|||||||
Reference in New Issue
Block a user