Skip to content

Commit

Permalink
Fixed: The ZIM file was not opening when clicking on the download not…
Browse files Browse the repository at this point in the history
…ification while the application was not running in the background.
  • Loading branch information
MohitMaliDeveloper committed Dec 24, 2024
1 parent d594385 commit a48f904
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,44 @@

package org.kiwix.kiwixmobile.core.downloader.downloadManager

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.tonyodev.fetch2.Download
import com.tonyodev.fetch2.Error
import com.tonyodev.fetch2.Fetch
import com.tonyodev.fetch2.FetchListener
import com.tonyodev.fetch2.R
import com.tonyodev.fetch2.Status
import com.tonyodev.fetch2.util.DEFAULT_NOTIFICATION_TIMEOUT_AFTER_RESET
import com.tonyodev.fetch2core.DownloadBlock
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.Intents
import org.kiwix.kiwixmobile.core.R.string
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.utils.files.Log
import java.util.concurrent.TimeUnit
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.utils.DOWNLOAD_NOTIFICATION_CHANNEL_ID
import javax.inject.Inject

class DownloadMonitorService : Service() {
private val updater = PublishSubject.create<() -> Unit>()
private var updaterDisposable: Disposable? = null
private var monitoringDisposable: Disposable? = null
private val lock = Any()
private val notificationManager: NotificationManager by lazy {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

Check warning on line 56 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L56

Added line #L56 was not covered by tests
}
private val downloadNotificationsBuilderMap = mutableMapOf<Int, NotificationCompat.Builder>()

@Inject
lateinit var fetch: Fetch

Check warning on line 61 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L61

Added line #L61 was not covered by tests
Expand All @@ -60,42 +74,10 @@ class DownloadMonitorService : Service() {
.inject(this)
super.onCreate()
setupUpdater()
startMonitoringDownloads()
fetch.addListener(fetchListener, true)
setForegroundNotification()
}

/**
* Periodically checks if there are active downloads.
* If no downloads are active, it stops the foreground service.
*/
private fun startMonitoringDownloads() {
// Check if monitoring is already active. If it is, do nothing.
if (monitoringDisposable?.isDisposed == false) return
monitoringDisposable = Observable.interval(ZERO.toLong(), FIVE.toLong(), TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(
{
try {
synchronized(lock) {
fetch.hasActiveDownloads(includeAddedDownloads = true) {
if (!it) {
stopForegroundServiceForDownloads()
}
}
}
} catch (ignore: Exception) {
Log.e(
"DOWNLOAD_MONITOR",
"Couldn't get the downloads update. Original exception = $ignore"
)
}
},
Throwable::printStackTrace
)
}

private fun setupUpdater() {
updaterDisposable = updater.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(
{ it.invoke() },
Expand Down Expand Up @@ -203,29 +185,119 @@ class DownloadMonitorService : Service() {
update(download)
}

Check warning on line 186 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L185-L186

Added lines #L185 - L186 were not covered by tests

private fun update(download: Download, shouldSetForegroundNotification: Boolean = false) {
updater.onNext { downloadRoomDao.update(download) }.also {
private fun update(

Check warning on line 188 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L188

Added line #L188 was not covered by tests
download: Download,
shouldSetForegroundNotification: Boolean = false

Check warning on line 190 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L190

Added line #L190 was not covered by tests
) {
updater.onNext {
downloadRoomDao.update(download)
if (download.status == Status.COMPLETED) {
downloadRoomDao.getEntityForDownloadId(download.id.toLong())?.let {
showDownloadCompletedNotification(download)

Check warning on line 196 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L196

Added line #L196 was not covered by tests
// to move these downloads in NewBookDao.
downloadRoomDao.downloads().blockingFirst()

Check warning on line 198 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L198

Added line #L198 was not covered by tests
}
}
if (shouldSetForegroundNotification) {
setForegroundNotification()
}
}
}

private fun delete(download: Download) {
updater.onNext { downloadRoomDao.delete(download) }.also {
updater.onNext {
downloadRoomDao.delete(download)
setForegroundNotification()
}
}

Check warning on line 212 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L208-L212

Added lines #L208 - L212 were not covered by tests
}

private fun showDownloadCompletedNotification(download: Download) {
downloadNotificationChannel()
val notificationBuilder = getNotificationBuilder(download.id)
val notificationTitle =

Check warning on line 218 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L216-L218

Added lines #L216 - L218 were not covered by tests
downloadRoomDao.getEntityForFileName(getDownloadNotificationTitle(download))?.title
?: download.file
notificationBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setContentTitle(notificationTitle)
.setContentText(getString(R.string.fetch_notification_download_complete))
.setOngoing(false)
.setGroup(download.id.toString())
.setGroupSummary(false)
.setProgress(ZERO, ZERO, false)
.setTimeoutAfter(DEFAULT_NOTIFICATION_TIMEOUT_AFTER_RESET)
.setContentIntent(getPendingIntentForDownloadedNotification(download))
.setAutoCancel(true)
notificationManager.notify(download.id, notificationBuilder.build())
}

Check warning on line 233 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L220-L233

Added lines #L220 - L233 were not covered by tests

private fun getPendingIntentForDownloadedNotification(download: Download): PendingIntent {
val internal = Intents.internal(CoreMainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(DOWNLOAD_NOTIFICATION_TITLE, getDownloadNotificationTitle(download))
}
return PendingIntent.getActivity(
this,
download.id,
internal,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT

Check warning on line 244 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L236-L244

Added lines #L236 - L244 were not covered by tests
)
}

private fun downloadNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (notificationManager.getNotificationChannel(DOWNLOAD_NOTIFICATION_CHANNEL_ID) == null) {
notificationManager.createNotificationChannel(createChannel())

Check warning on line 251 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L251

Added line #L251 was not covered by tests
}
}
}

Check warning on line 254 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L254

Added line #L254 was not covered by tests

@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel() =
NotificationChannel(
DOWNLOAD_NOTIFICATION_CHANNEL_ID,
getString(string.download_notification_channel_name),
NotificationManager.IMPORTANCE_HIGH
).apply {
setSound(null, null)
enableVibration(false)
}

Check warning on line 265 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L258-L265

Added lines #L258 - L265 were not covered by tests

@SuppressLint("RestrictedApi")
private fun getNotificationBuilder(notificationId: Int): NotificationCompat.Builder {
synchronized(downloadNotificationsBuilderMap) {

Check warning on line 269 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L269

Added line #L269 was not covered by tests
val notificationBuilder = downloadNotificationsBuilderMap[notificationId]
?: NotificationCompat.Builder(this, DOWNLOAD_NOTIFICATION_CHANNEL_ID)
downloadNotificationsBuilderMap[notificationId] = notificationBuilder
notificationBuilder
.setGroup("$notificationId")
.setStyle(null)
.setProgress(ZERO, ZERO, false)
.setContentTitle(null)
.setContentText(null)
.setContentIntent(null)
.setGroupSummary(false)
.setTimeoutAfter(DEFAULT_NOTIFICATION_TIMEOUT_AFTER_RESET)
.setOngoing(false)
.setOnlyAlertOnce(true)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.mActions.clear()
return@getNotificationBuilder notificationBuilder

Check warning on line 286 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L271-L286

Added lines #L271 - L286 were not covered by tests
}
}

private fun getDownloadNotificationTitle(download: Download): String =
fetchDownloadNotificationManager.getDownloadNotificationTitle(download)

Check warning on line 291 in core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/downloader/downloadManager/DownloadMonitorService.kt#L291

Added line #L291 was not covered by tests

/**
* Stops the foreground service, disposes of resources, and removes the Fetch listener.
*/
private fun stopForegroundServiceForDownloads() {
monitoringDisposable?.dispose()
updaterDisposable?.dispose()
fetch.removeListener(fetchListener)
stopForeground(STOP_FOREGROUND_REMOVE)
stopForeground(STOP_FOREGROUND_DETACH)
stopSelf()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const val EXTRA_IS_WIDGET_VOICE = "isWidgetVoice"
const val HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService"
const val OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base"
const val READ_ALOUD_SERVICE_CHANNEL_ID = "readAloudService"
const val DOWNLOAD_NOTIFICATION_CHANNEL_ID = "kiwixDownloadNotificationChannel"

// For Storage select dialog
const val INTERNAL_SELECT_POSITION = 0
Expand Down

0 comments on commit a48f904

Please sign in to comment.