Removed the again showing the notification if user cancels it, and improved the setting of foreground notification when all other downloads are paused.

This commit is contained in:
MohitMaliFtechiz 2025-02-05 18:35:32 +05:30
parent 0646a782ab
commit 6d407fcfa8
2 changed files with 37 additions and 74 deletions

View File

@ -118,20 +118,7 @@ class DownloadMonitorService : Service() {
it.status == Status.QUEUED || it.status == Status.QUEUED ||
it.status == Status.DOWNLOADING || it.status == Status.DOWNLOADING ||
it.isPaused() it.isPaused()
}?.let { }?.let(::setForegroundNotificationForDownload) ?: kotlin.run {
val notificationBuilder =
fetchDownloadNotificationManager.getNotificationBuilder(it.id, it.id)
var foreGroundServiceNotification = notificationBuilder.build()
if (it.isPaused()) {
// Clear any pending actions on this notification builder.
notificationBuilder.clearActions()
// If a download is paused that means there is no notification for it, so we have to
// show our custom cancel notification.
foreGroundServiceNotification =
fetchDownloadNotificationManager.getCancelNotification(fetch, it, notificationBuilder)
}
startForeground(it.id, foreGroundServiceNotification)
} ?: kotlin.run {
stopForegroundServiceForDownloads() stopForegroundServiceForDownloads()
// Cancel the last ongoing notification after detaching it from // Cancel the last ongoing notification after detaching it from
// the foreground service if no active downloads are found. // the foreground service if no active downloads are found.
@ -141,6 +128,21 @@ class DownloadMonitorService : Service() {
} }
} }
private fun setForegroundNotificationForDownload(it: Download) {
val notificationBuilder =
fetchDownloadNotificationManager.getNotificationBuilder(it.id, it.id)
var foreGroundServiceNotification = notificationBuilder.build()
if (it.isPaused()) {
// Clear any pending actions on this notification builder.
notificationBuilder.clearActions()
// If a download is paused that means there is no notification for it, so we have to
// show our custom cancel notification.
foreGroundServiceNotification =
fetchDownloadNotificationManager.getCancelNotification(fetch, it, notificationBuilder)
}
startForeground(it.id, foreGroundServiceNotification)
}
private fun cancelNotificationForId(downloadId: Int) { private fun cancelNotificationForId(downloadId: Int) {
notificationManager.cancel(downloadId) notificationManager.cancel(downloadId)
} }
@ -226,7 +228,9 @@ class DownloadMonitorService : Service() {
// If someone pause the Download then post a notification since fetch removes the // If someone pause the Download then post a notification since fetch removes the
// notification for ongoing download when pause so we needs to show our custom notification. // notification for ongoing download when pause so we needs to show our custom notification.
if (download.isPaused()) { if (download.isPaused()) {
fetchDownloadNotificationManager.showDownloadPauseNotification(fetch, download) fetchDownloadNotificationManager.showDownloadPauseNotification(fetch, download).also {
setForeGroundServiceNotificationIfNoActiveDownloads(fetch, download)
}
} }
if (shouldSetForegroundNotification) { if (shouldSetForegroundNotification) {
setForegroundNotification(download.id) setForegroundNotification(download.id)
@ -242,6 +246,24 @@ class DownloadMonitorService : Service() {
} }
} }
private fun setForeGroundServiceNotificationIfNoActiveDownloads(
fetch: Fetch,
download: Download
) {
updater.onNext {
// Check if there are any ongoing downloads.
// If the list is empty, it means no other downloads are running,
// so we need to promote this download to a foreground service.
fetch.getDownloadsWithStatus(
listOf(Status.NONE, Status.ADDED, Status.QUEUED, Status.DOWNLOADING)
) { activeDownloads ->
if (activeDownloads.isEmpty()) {
setForegroundNotificationForDownload(download)
}
}
}
}
@Suppress("MagicNumber") @Suppress("MagicNumber")
private fun showDownloadCompletedNotification(download: Download) { private fun showDownloadCompletedNotification(download: Download) {
downloadNotificationChannel() downloadNotificationChannel()

View File

@ -26,7 +26,6 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE import android.app.PendingIntent.FLAG_IMMUTABLE
import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.app.PendingIntent.getActivity import android.app.PendingIntent.getActivity
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
@ -40,7 +39,6 @@ import com.tonyodev.fetch2.ACTION_TYPE_INVALID
import com.tonyodev.fetch2.ACTION_TYPE_PAUSE import com.tonyodev.fetch2.ACTION_TYPE_PAUSE
import com.tonyodev.fetch2.ACTION_TYPE_RESUME import com.tonyodev.fetch2.ACTION_TYPE_RESUME
import com.tonyodev.fetch2.ACTION_TYPE_RETRY import com.tonyodev.fetch2.ACTION_TYPE_RETRY
import com.tonyodev.fetch2.DOWNLOAD_ID_INVALID
import com.tonyodev.fetch2.DefaultFetchNotificationManager import com.tonyodev.fetch2.DefaultFetchNotificationManager
import com.tonyodev.fetch2.Download import com.tonyodev.fetch2.Download
import com.tonyodev.fetch2.DownloadNotification import com.tonyodev.fetch2.DownloadNotification
@ -81,28 +79,6 @@ class FetchDownloadNotificationManager @Inject constructor(
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
} }
private val notificationDismissAction = "NOTIFICATION_DISMISS_ACTION"
init {
registerDismissNotificationBroadcastReceiver()
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
private fun registerDismissNotificationBroadcastReceiver() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.registerReceiver(
notificationDismissBroadcastReceiver,
IntentFilter(notificationDismissAction),
Context.RECEIVER_EXPORTED
)
} else {
context.registerReceiver(
notificationDismissBroadcastReceiver,
IntentFilter(notificationDismissAction)
)
}
}
override fun getFetchInstanceForNamespace(namespace: String): Fetch = Fetch.getDefaultInstance() override fun getFetchInstanceForNamespace(namespace: String): Fetch = Fetch.getDefaultInstance()
override fun registerBroadcastReceiver() { override fun registerBroadcastReceiver() {
@ -271,44 +247,9 @@ class FetchDownloadNotificationManager @Inject constructor(
context.getString(R.string.notification_resume_button_text), context.getString(R.string.notification_resume_button_text),
getActionPendingIntent(fetch, download, DownloadNotification.ActionType.RESUME) getActionPendingIntent(fetch, download, DownloadNotification.ActionType.RESUME)
) )
// Set the delete intent so that we can know that user dismiss the paused notification.
.setDeleteIntent(getDeletePendingIntent(download, fetch))
.build() .build()
} }
/**
* This pending intent will use in the "Pause" notifications when a user removes the paused
* notification this pending intent will trigger and will re-enable the paused notification.
* So that user can see that a download is paused and he can perform the necessary actions.
*/
private fun getDeletePendingIntent(download: Download, fetch: Fetch): PendingIntent {
val intent = Intent(notificationDismissAction).apply {
putExtra(EXTRA_DOWNLOAD_ID, download.id)
putExtra(EXTRA_NAMESPACE, fetch.namespace)
}
return PendingIntent.getBroadcast(
context,
download.id,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
}
private val notificationDismissBroadcastReceiver: BroadcastReceiver
get() = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val namespace = intent?.getStringExtra(EXTRA_NAMESPACE) ?: return
val downloadId = intent.getIntExtra(EXTRA_DOWNLOAD_ID, DOWNLOAD_ID_INVALID)
if (namespace.isEmpty() || downloadId == DOWNLOAD_ID_INVALID) return
val fetch = getFetchInstanceForNamespace(namespace)
if (!fetch.isClosed) {
fetch.getDownload(downloadId) { download ->
download?.takeIf(Download::isPaused)?.let { showDownloadPauseNotification(fetch, it) }
}
}
}
}
private fun getActionPendingIntent( private fun getActionPendingIntent(
fetch: Fetch, fetch: Fetch,
download: Download, download: Download,