diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt index 035e7e20b..6254d0269 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt @@ -118,20 +118,7 @@ class DownloadMonitorService : Service() { it.status == Status.QUEUED || it.status == Status.DOWNLOADING || it.isPaused() - }?.let { - 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 { + }?.let(::setForegroundNotificationForDownload) ?: kotlin.run { stopForegroundServiceForDownloads() // Cancel the last ongoing notification after detaching it from // 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) { notificationManager.cancel(downloadId) } @@ -226,7 +228,9 @@ class DownloadMonitorService : Service() { // 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. if (download.isPaused()) { - fetchDownloadNotificationManager.showDownloadPauseNotification(fetch, download) + fetchDownloadNotificationManager.showDownloadPauseNotification(fetch, download).also { + setForeGroundServiceNotificationIfNoActiveDownloads(fetch, download) + } } if (shouldSetForegroundNotification) { 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") private fun showDownloadCompletedNotification(download: Download) { downloadNotificationChannel() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/FetchDownloadNotificationManager.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/FetchDownloadNotificationManager.kt index 06edea1e8..e18abada1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/FetchDownloadNotificationManager.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/FetchDownloadNotificationManager.kt @@ -26,7 +26,6 @@ import android.app.PendingIntent import android.app.PendingIntent.FLAG_IMMUTABLE import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.app.PendingIntent.getActivity -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent 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_RESUME import com.tonyodev.fetch2.ACTION_TYPE_RETRY -import com.tonyodev.fetch2.DOWNLOAD_ID_INVALID import com.tonyodev.fetch2.DefaultFetchNotificationManager import com.tonyodev.fetch2.Download import com.tonyodev.fetch2.DownloadNotification @@ -81,28 +79,6 @@ class FetchDownloadNotificationManager @Inject constructor( 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 registerBroadcastReceiver() { @@ -271,44 +247,9 @@ class FetchDownloadNotificationManager @Inject constructor( context.getString(R.string.notification_resume_button_text), 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() } - /** - * 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( fetch: Fetch, download: Download,