mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 18:56:44 -04:00
Fixed: The ZIM file was not opening when clicking on the download notification while the application was not running in the background.
This commit is contained in:
parent
d5943856cd
commit
a48f90422a
@ -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
|
||||
}
|
||||
private val downloadNotificationsBuilderMap = mutableMapOf<Int, NotificationCompat.Builder>()
|
||||
|
||||
@Inject
|
||||
lateinit var fetch: Fetch
|
||||
@ -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() },
|
||||
@ -203,8 +185,19 @@ class DownloadMonitorService : Service() {
|
||||
update(download)
|
||||
}
|
||||
|
||||
private fun update(download: Download, shouldSetForegroundNotification: Boolean = false) {
|
||||
updater.onNext { downloadRoomDao.update(download) }.also {
|
||||
private fun update(
|
||||
download: Download,
|
||||
shouldSetForegroundNotification: Boolean = false
|
||||
) {
|
||||
updater.onNext {
|
||||
downloadRoomDao.update(download)
|
||||
if (download.status == Status.COMPLETED) {
|
||||
downloadRoomDao.getEntityForDownloadId(download.id.toLong())?.let {
|
||||
showDownloadCompletedNotification(download)
|
||||
// to move these downloads in NewBookDao.
|
||||
downloadRoomDao.downloads().blockingFirst()
|
||||
}
|
||||
}
|
||||
if (shouldSetForegroundNotification) {
|
||||
setForegroundNotification()
|
||||
}
|
||||
@ -212,12 +205,91 @@ class DownloadMonitorService : Service() {
|
||||
}
|
||||
|
||||
private fun delete(download: Download) {
|
||||
updater.onNext { downloadRoomDao.delete(download) }.also {
|
||||
updater.onNext {
|
||||
downloadRoomDao.delete(download)
|
||||
setForegroundNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDownloadCompletedNotification(download: Download) {
|
||||
downloadNotificationChannel()
|
||||
val notificationBuilder = getNotificationBuilder(download.id)
|
||||
val notificationTitle =
|
||||
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())
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
private fun downloadNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (notificationManager.getNotificationChannel(DOWNLOAD_NOTIFICATION_CHANNEL_ID) == null) {
|
||||
notificationManager.createNotificationChannel(createChannel())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private fun getNotificationBuilder(notificationId: Int): NotificationCompat.Builder {
|
||||
synchronized(downloadNotificationsBuilderMap) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDownloadNotificationTitle(download: Download): String =
|
||||
fetchDownloadNotificationManager.getDownloadNotificationTitle(download)
|
||||
|
||||
/**
|
||||
* Stops the foreground service, disposes of resources, and removes the Fetch listener.
|
||||
*/
|
||||
@ -225,7 +297,7 @@ class DownloadMonitorService : Service() {
|
||||
monitoringDisposable?.dispose()
|
||||
updaterDisposable?.dispose()
|
||||
fetch.removeListener(fetchListener)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopForeground(STOP_FOREGROUND_DETACH)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user