mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
Fixed: the download notification controls was not working.
* Refactored/cleanup code. * Added foreground permission in core module so that it can be used in both modules.
This commit is contained in:
parent
1f62caebbe
commit
da9528b8ff
@ -8,9 +8,6 @@
|
||||
tools:ignore="CoarseFineLocation" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="${permission}" />
|
||||
<!-- Device with versions >= Pie need this permission -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission
|
||||
android:name="android.permission.NEARBY_WIFI_DEVICES"
|
||||
android:usesPermissionFlags="neverForLocation"
|
||||
|
@ -23,9 +23,7 @@ import android.app.Service
|
||||
import android.content.Context
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationActionsBroadcastReceiver
|
||||
import org.kiwix.kiwixmobile.core.qr.GenerateQR
|
||||
import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudNotificationManger
|
||||
import org.kiwix.kiwixmobile.di.ServiceScope
|
||||
import org.kiwix.kiwixmobile.webserver.KiwixServer
|
||||
import org.kiwix.kiwixmobile.webserver.WebServerHelper
|
||||
@ -35,12 +33,6 @@ import org.kiwix.kiwixmobile.webserver.wifi_hotspot.IpAddressCallbacks
|
||||
|
||||
@Module
|
||||
class ServiceModule {
|
||||
@Provides
|
||||
@ServiceScope
|
||||
fun providesReadAloudNotificationManager(
|
||||
notificationManager: NotificationManager,
|
||||
context: Context
|
||||
): ReadAloudNotificationManger = ReadAloudNotificationManger(notificationManager, context)
|
||||
|
||||
@Provides
|
||||
@ServiceScope
|
||||
@ -76,17 +68,4 @@ class ServiceModule {
|
||||
@Provides
|
||||
@ServiceScope
|
||||
fun providesGenerateQr(): GenerateQR = GenerateQR()
|
||||
|
||||
@Provides
|
||||
@ServiceScope
|
||||
fun providesDownloadNotificationActionsBroadcastReceiverCallback(service: Service):
|
||||
DownloadNotificationActionsBroadcastReceiver.Callback =
|
||||
service as DownloadNotificationActionsBroadcastReceiver.Callback
|
||||
|
||||
@Provides
|
||||
@ServiceScope
|
||||
fun providesDownloadNotificationActionsBroadcastReceiver(
|
||||
callBack: DownloadNotificationActionsBroadcastReceiver.Callback
|
||||
): DownloadNotificationActionsBroadcastReceiver =
|
||||
DownloadNotificationActionsBroadcastReceiver(callBack)
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
|
||||
<!-- Device with versions >= Pie need this permission -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.TTS_SERVICE" />
|
||||
|
@ -35,8 +35,8 @@ const val CONNECTION_TIMEOUT = 10L
|
||||
// increase the read and call timeout since the content is 19MB large so it takes
|
||||
// more time to read on slow internet connection, and due to less read timeout
|
||||
// the request is canceled.
|
||||
const val READ_TIMEOUT = 180L
|
||||
const val CALL_TIMEOUT = 180L
|
||||
const val READ_TIMEOUT = 300L
|
||||
const val CALL_TIMEOUT = 300L
|
||||
const val USER_AGENT = "kiwix-android-version:${BuildConfig.VERSION_CODE}"
|
||||
const val KIWIX_DOWNLOAD_URL = "https://mirror.download.kiwix.org/"
|
||||
|
||||
|
@ -19,94 +19,82 @@
|
||||
package org.kiwix.kiwixmobile.core.downloader.downloadManager
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import androidx.core.content.ContextCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
||||
import org.kiwix.kiwixmobile.core.downloader.DownloadMonitor
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_CANCEL
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_PAUSE
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_QUERY_DOWNLOAD_STATUS
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_RESUME
|
||||
import javax.inject.Inject
|
||||
|
||||
class DownloadManagerMonitor @Inject constructor(
|
||||
val downloadRoomDao: DownloadRoomDao,
|
||||
private val context: Context
|
||||
) : DownloadMonitor, DownloadManagerBroadcastReceiver.Callback, DownloadMonitorServiceCallback {
|
||||
) : DownloadMonitor, DownloadManagerBroadcastReceiver.Callback {
|
||||
private val lock = Any()
|
||||
private var downloadMonitorService: DownloadMonitorService? = null
|
||||
private val serviceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
|
||||
downloadMonitorService =
|
||||
(binder as? DownloadMonitorService.DownloadMonitorBinder)?.downloadMonitorService?.get()
|
||||
downloadMonitorService?.registerCallback(this@DownloadManagerMonitor)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
if (downloadRoomDao.downloads().blockingFirst().isNotEmpty()) {
|
||||
startService()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
downloadMonitorService = null
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
bindService()
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
if (getActiveDownloads().isNotEmpty()) {
|
||||
startService()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindService() {
|
||||
val serviceIntent = Intent(context, DownloadMonitorService::class.java)
|
||||
context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
private suspend fun getActiveDownloads(): List<DownloadRoomEntity> =
|
||||
downloadRoomDao.downloadRoomEntity().blockingFirst().filter {
|
||||
it.status != Status.PAUSED && it.status != Status.CANCELLED
|
||||
}
|
||||
|
||||
override fun downloadCompleteOrCancelled(intent: Intent) {
|
||||
synchronized(lock) {
|
||||
intent.extras?.let {
|
||||
val downloadId = it.getLong(DownloadManager.EXTRA_DOWNLOAD_ID, -1L)
|
||||
if (downloadId != -1L) {
|
||||
downloadMonitorService?.queryDownloadStatus(downloadId)
|
||||
context.startService(
|
||||
getDownloadMonitorIntent(
|
||||
ACTION_QUERY_DOWNLOAD_STATUS,
|
||||
downloadId.toInt()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startMonitoringDownloads() {
|
||||
bindService()
|
||||
startService()
|
||||
downloadMonitorService?.startMonitoringDownloads()
|
||||
}
|
||||
|
||||
private fun startService() {
|
||||
ContextCompat.startForegroundService(
|
||||
context,
|
||||
Intent(context, DownloadMonitorService::class.java)
|
||||
)
|
||||
context.startService(Intent(context, DownloadMonitorService::class.java))
|
||||
}
|
||||
|
||||
fun pauseDownload(downloadId: Long) {
|
||||
downloadMonitorService?.pauseDownload(downloadId)
|
||||
context.startService(getDownloadMonitorIntent(ACTION_PAUSE, downloadId.toInt()))
|
||||
}
|
||||
|
||||
fun resumeDownload(downloadId: Long) {
|
||||
downloadMonitorService?.resumeDownload(downloadId)
|
||||
context.startService(getDownloadMonitorIntent(ACTION_RESUME, downloadId.toInt()))
|
||||
}
|
||||
|
||||
fun cancelDownload(downloadId: Long) {
|
||||
downloadMonitorService?.cancelDownload(downloadId)
|
||||
context.startService(getDownloadMonitorIntent(ACTION_CANCEL, downloadId.toInt()))
|
||||
}
|
||||
|
||||
private fun getDownloadMonitorIntent(action: String, downloadId: Int): Intent =
|
||||
Intent(context, DownloadMonitorService::class.java).apply {
|
||||
putExtra(DownloadNotificationManager.NOTIFICATION_ACTION, action)
|
||||
putExtra(DownloadNotificationManager.EXTRA_DOWNLOAD_ID, downloadId)
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
// empty method to so class does not get reported unused
|
||||
}
|
||||
|
||||
override fun onServiceDestroyed() {
|
||||
downloadMonitorService?.registerCallback(null)
|
||||
context.unbindService(serviceConnection)
|
||||
downloadMonitorService = null
|
||||
}
|
||||
}
|
||||
|
@ -41,12 +41,7 @@ class DownloadManagerRequester @Inject constructor(
|
||||
private val downloadManagerMonitor: DownloadManagerMonitor
|
||||
) : DownloadRequester {
|
||||
override fun enqueue(downloadRequest: DownloadRequest): Long =
|
||||
downloadManager.enqueue(downloadRequest.toDownloadManagerRequest(sharedPreferenceUtil)).also {
|
||||
Log.e(
|
||||
"DOWNLOADING_STEP",
|
||||
"enqueue: ${downloadRequest.toDownloadManagerRequest(sharedPreferenceUtil)}"
|
||||
)
|
||||
}
|
||||
downloadManager.enqueue(downloadRequest.toDownloadManagerRequest(sharedPreferenceUtil))
|
||||
|
||||
override fun onDownloadAdded() {
|
||||
// Start monitoring downloads after enqueuing a new download request.
|
||||
|
@ -26,7 +26,6 @@ import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.disposables.Disposable
|
||||
@ -35,10 +34,13 @@ import io.reactivex.subjects.PublishSubject
|
||||
import org.kiwix.kiwixmobile.core.CoreApp
|
||||
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_CANCEL
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_PAUSE
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_QUERY_DOWNLOAD_STATUS
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_RESUME
|
||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadState
|
||||
import org.kiwix.kiwixmobile.core.utils.files.Log
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -59,7 +61,7 @@ const val STATUS_PAUSED_BY_APP = 193
|
||||
const val COLUMN_CONTROL = "control"
|
||||
val downloadBaseUri: Uri = Uri.parse("content://downloads/my_downloads")
|
||||
|
||||
class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastReceiver.Callback {
|
||||
class DownloadMonitorService : Service() {
|
||||
|
||||
@Inject
|
||||
lateinit var downloadManager: DownloadManager
|
||||
@ -73,19 +75,9 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
private var monitoringDisposable: Disposable? = null
|
||||
private val downloadInfoMap = mutableMapOf<Long, DownloadInfo>()
|
||||
private val updater = PublishSubject.create<() -> Unit>()
|
||||
private val downloadMonitorBinder: IBinder = DownloadMonitorBinder(this)
|
||||
private var downloadMonitorServiceCallback: DownloadMonitorServiceCallback? = null
|
||||
private var isForeGroundServiceNotification: Boolean = true
|
||||
private var foreGroundServiceInformation: Pair<Boolean, Int> = true to DEFAULT_INT_VALUE
|
||||
|
||||
// @set:Inject
|
||||
// var downloadNotificationBroadcastReceiver: DownloadNotificationActionsBroadcastReceiver? = null
|
||||
|
||||
class DownloadMonitorBinder(downloadMonitorService: DownloadMonitorService) : Binder() {
|
||||
val downloadMonitorService: WeakReference<DownloadMonitorService> =
|
||||
WeakReference<DownloadMonitorService>(downloadMonitorService)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder = downloadMonitorBinder
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
CoreApp.coreComponent
|
||||
@ -96,13 +88,22 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
super.onCreate()
|
||||
setupUpdater()
|
||||
startMonitoringDownloads()
|
||||
// downloadNotificationBroadcastReceiver?.let(this::registerReceiver)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int = START_NOT_STICKY
|
||||
|
||||
fun registerCallback(downloadMonitorServiceCallback: DownloadMonitorServiceCallback?) {
|
||||
this.downloadMonitorServiceCallback = downloadMonitorServiceCallback
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
val downloadId =
|
||||
intent?.getIntExtra(DownloadNotificationManager.EXTRA_DOWNLOAD_ID, DEFAULT_INT_VALUE)
|
||||
?: DEFAULT_INT_VALUE
|
||||
val notificationAction = intent?.getStringExtra(DownloadNotificationManager.NOTIFICATION_ACTION)
|
||||
if (downloadId != DEFAULT_INT_VALUE) {
|
||||
when (notificationAction) {
|
||||
ACTION_PAUSE -> pauseDownload(downloadId.toLong())
|
||||
ACTION_RESUME -> resumeDownload(downloadId.toLong())
|
||||
ACTION_CANCEL -> cancelDownload(downloadId.toLong())
|
||||
ACTION_QUERY_DOWNLOAD_STATUS -> queryDownloadStatus(downloadId.toLong())
|
||||
}
|
||||
}
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
@Suppress("CheckResult")
|
||||
@ -122,8 +123,7 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
* when there are no ongoing downloads to avoid unnecessary resource usage.
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
fun startMonitoringDownloads() {
|
||||
Log.e("DOWNLOADING_STEP", "startMonitoringDownloads:")
|
||||
private fun startMonitoringDownloads() {
|
||||
// Check if monitoring is already active. If it is, do nothing.
|
||||
if (monitoringDisposable?.isDisposed == false) return
|
||||
monitoringDisposable = Observable.interval(ZERO.toLong(), 5, TimeUnit.SECONDS)
|
||||
@ -142,7 +142,7 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
}
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
Log.i(
|
||||
Log.e(
|
||||
"DOWNLOAD_MONITOR",
|
||||
"Couldn't get the downloads update. Original exception = $ignore"
|
||||
)
|
||||
@ -155,7 +155,6 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
@SuppressLint("Range")
|
||||
private fun checkDownloads() {
|
||||
synchronized(lock) {
|
||||
Log.e("DOWNLOADING_STEP", "checkDownloads: lock")
|
||||
val query = DownloadManager.Query().setFilterByStatus(
|
||||
DownloadManager.STATUS_RUNNING or
|
||||
DownloadManager.STATUS_PAUSED or
|
||||
@ -163,7 +162,6 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
DownloadManager.STATUS_SUCCESSFUL
|
||||
)
|
||||
downloadManager.query(query).use { cursor ->
|
||||
Log.e("DOWNLOADING_STEP", "checkDownloads:")
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
val downloadId = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID))
|
||||
@ -385,10 +383,8 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
) {
|
||||
synchronized(lock) {
|
||||
updater.onNext {
|
||||
Log.e("DOWNLOADING_STEP", "updateDownloadStatus:")
|
||||
downloadRoomDao.getEntityForDownloadId(downloadId)?.let { downloadEntity ->
|
||||
if (shouldUpdateDownloadStatus(downloadEntity)) {
|
||||
Log.e("DOWNLOADING_STEP", "shouldUpdateDownloadStatus:")
|
||||
val downloadModel = DownloadModel(downloadEntity).apply {
|
||||
if (shouldUpdateDownloadStatus(status, error, downloadEntity)) {
|
||||
state = status
|
||||
@ -406,7 +402,6 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
}
|
||||
}
|
||||
downloadRoomDao.update(downloadModel)
|
||||
Log.e("DOWNLOADING_STEP", "updateNotification: $downloadModel")
|
||||
updateNotification(downloadModel, downloadEntity.title, downloadEntity.description)
|
||||
return@let
|
||||
}
|
||||
@ -472,14 +467,63 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
|
||||
private fun cancelNotification(downloadId: Long) {
|
||||
downloadNotificationManager.cancelNotification(downloadId.toInt())
|
||||
assignNewForegroundNotification()
|
||||
}
|
||||
|
||||
private fun assignNewForegroundNotification() {
|
||||
val activeDownloads = getActiveDownloads()
|
||||
if (activeDownloads.isNotEmpty()) {
|
||||
// Promote the first active download to foreground
|
||||
val downloadRoomEntity = activeDownloads.first()
|
||||
foreGroundServiceInformation =
|
||||
foreGroundServiceInformation.first to downloadRoomEntity.downloadId.toInt()
|
||||
val downloadNotificationModel =
|
||||
getDownloadNotificationModel(
|
||||
DownloadModel(downloadRoomEntity),
|
||||
downloadRoomEntity.title,
|
||||
downloadRoomEntity.description
|
||||
)
|
||||
val notification = downloadNotificationManager.createNotification(downloadNotificationModel)
|
||||
startForeground(foreGroundServiceInformation.second, notification)
|
||||
} else {
|
||||
// Stop the service if no active downloads remain
|
||||
stopMonitoringDownloads()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActiveDownloads(): List<DownloadRoomEntity> =
|
||||
downloadRoomDao.downloadRoomEntity().blockingFirst().filter {
|
||||
it.status != Status.PAUSED && it.status != Status.CANCELLED
|
||||
}
|
||||
|
||||
private fun updateNotification(
|
||||
downloadModel: DownloadModel,
|
||||
title: String,
|
||||
description: String?
|
||||
) {
|
||||
val downloadNotificationModel = DownloadNotificationModel(
|
||||
val downloadNotificationModel = getDownloadNotificationModel(downloadModel, title, description)
|
||||
val notification = downloadNotificationManager.createNotification(downloadNotificationModel)
|
||||
if (foreGroundServiceInformation.first) {
|
||||
startForeground(downloadModel.downloadId.toInt(), notification)
|
||||
foreGroundServiceInformation = false to downloadModel.downloadId.toInt()
|
||||
} else {
|
||||
downloadNotificationManager.updateNotification(
|
||||
downloadNotificationModel,
|
||||
object : AssignNewForegroundServiceNotification {
|
||||
override fun assignNewForegroundServiceNotification(downloadId: Long) {
|
||||
cancelNotification(downloadId)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDownloadNotificationModel(
|
||||
downloadModel: DownloadModel,
|
||||
title: String,
|
||||
description: String?
|
||||
): DownloadNotificationModel =
|
||||
DownloadNotificationModel(
|
||||
downloadId = downloadModel.downloadId.toInt(),
|
||||
status = downloadModel.state,
|
||||
progress = downloadModel.progress,
|
||||
@ -493,28 +537,8 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
downloadModel.book.url
|
||||
).toReadableState(this).toString()
|
||||
)
|
||||
val notification = downloadNotificationManager.createNotification(downloadNotificationModel)
|
||||
if (isForeGroundServiceNotification) {
|
||||
startForeground(downloadModel.downloadId.toInt(), notification)
|
||||
isForeGroundServiceNotification = false
|
||||
} else {
|
||||
downloadNotificationManager.updateNotification(downloadNotificationModel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun pauseDownloads(downloadId: Long) {
|
||||
pauseDownload(downloadId)
|
||||
}
|
||||
|
||||
override fun resumeDownloads(downloadId: Long) {
|
||||
resumeDownload(downloadId)
|
||||
}
|
||||
|
||||
override fun cancelDownloads(downloadId: Long) {
|
||||
cancelNotification(downloadId)
|
||||
}
|
||||
|
||||
fun pauseDownload(downloadId: Long) {
|
||||
private fun pauseDownload(downloadId: Long) {
|
||||
synchronized(lock) {
|
||||
updater.onNext {
|
||||
if (pauseResumeDownloadInDownloadManagerContentResolver(
|
||||
@ -529,7 +553,7 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
}
|
||||
}
|
||||
|
||||
fun resumeDownload(downloadId: Long) {
|
||||
private fun resumeDownload(downloadId: Long) {
|
||||
synchronized(lock) {
|
||||
updater.onNext {
|
||||
if (pauseResumeDownloadInDownloadManagerContentResolver(
|
||||
@ -544,7 +568,7 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelDownload(downloadId: Long) {
|
||||
private fun cancelDownload(downloadId: Long) {
|
||||
synchronized(lock) {
|
||||
downloadManager.remove(downloadId)
|
||||
handleCancelledDownload(downloadId)
|
||||
@ -577,27 +601,23 @@ class DownloadMonitorService : Service(), DownloadNotificationActionsBroadcastRe
|
||||
downloadRoomEntity.status != Status.COMPLETED
|
||||
|
||||
override fun onDestroy() {
|
||||
// downloadNotificationBroadcastReceiver?.let(::unregisterReceiver)
|
||||
monitoringDisposable?.dispose()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun stopMonitoringDownloads() {
|
||||
Log.e("DOWNLOADING_STEP", "stopMonitoringDownloads: ")
|
||||
isForeGroundServiceNotification = true
|
||||
foreGroundServiceInformation = true to DEFAULT_INT_VALUE
|
||||
monitoringDisposable?.dispose()
|
||||
downloadMonitorServiceCallback?.onServiceDestroyed()
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_ID = "download_monitor_channel"
|
||||
private const val ONGOING_NOTIFICATION_ID = 1
|
||||
}
|
||||
}
|
||||
|
||||
data class DownloadInfo(
|
||||
var startTime: Long,
|
||||
var initialBytesDownloaded: Int
|
||||
)
|
||||
|
||||
interface AssignNewForegroundServiceNotification {
|
||||
fun assignNewForegroundServiceNotification(downloadId: Long)
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2024 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.kiwix.kiwixmobile.core.downloader.downloadManager
|
||||
|
||||
interface DownloadMonitorServiceCallback {
|
||||
fun onServiceDestroyed()
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2024 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.kiwix.kiwixmobile.core.downloader.downloadManager
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import org.kiwix.kiwixmobile.core.base.BaseBroadcastReceiver
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_CANCEL
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_PAUSE
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.ACTION_RESUME
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.EXTRA_DOWNLOAD_ID
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadNotificationManager.Companion.NOTIFICATION_ACTION
|
||||
import javax.inject.Inject
|
||||
|
||||
const val DOWNLOAD_NOTIFICATION_ACTION = "org.kiwix.kiwixmobile.download_notification_action"
|
||||
|
||||
class DownloadNotificationActionsBroadcastReceiver @Inject constructor(
|
||||
private val callback: Callback
|
||||
) :
|
||||
BaseBroadcastReceiver() {
|
||||
|
||||
override val action: String = DOWNLOAD_NOTIFICATION_ACTION
|
||||
override fun onIntentWithActionReceived(context: Context, intent: Intent) {
|
||||
val downloadId = intent.getIntExtra(EXTRA_DOWNLOAD_ID, -1)
|
||||
val notificationAction = intent.getStringExtra(NOTIFICATION_ACTION)
|
||||
if (downloadId != -1) {
|
||||
when (notificationAction) {
|
||||
ACTION_PAUSE -> callback.pauseDownloads(downloadId.toLong())
|
||||
ACTION_RESUME -> callback.resumeDownloads(downloadId.toLong())
|
||||
ACTION_CANCEL -> callback.cancelDownloads(downloadId.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun pauseDownloads(downloadId: Long)
|
||||
fun resumeDownloads(downloadId: Long)
|
||||
fun cancelDownloads(downloadId: Long)
|
||||
}
|
||||
}
|
@ -54,7 +54,8 @@ class DownloadNotificationManager @Inject constructor(
|
||||
}
|
||||
|
||||
fun updateNotification(
|
||||
downloadNotificationModel: DownloadNotificationModel
|
||||
downloadNotificationModel: DownloadNotificationModel,
|
||||
assignNewForegroundServiceNotification: AssignNewForegroundServiceNotification
|
||||
) {
|
||||
synchronized(downloadNotificationsBuilderMap) {
|
||||
if (shouldUpdateNotification(downloadNotificationModel)) {
|
||||
@ -64,7 +65,9 @@ class DownloadNotificationManager @Inject constructor(
|
||||
)
|
||||
} else {
|
||||
// the download is cancelled/paused so remove the notification.
|
||||
cancelNotification(downloadNotificationModel.downloadId)
|
||||
assignNewForegroundServiceNotification.assignNewForegroundServiceNotification(
|
||||
downloadNotificationModel.downloadId.toLong()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,16 +194,16 @@ class DownloadNotificationManager @Inject constructor(
|
||||
}
|
||||
|
||||
private fun getActionPendingIntent(action: String, downloadId: Int): PendingIntent {
|
||||
val intent =
|
||||
Intent(DOWNLOAD_NOTIFICATION_ACTION).apply {
|
||||
val pendingIntent =
|
||||
Intent(context, DownloadMonitorService::class.java).apply {
|
||||
putExtra(NOTIFICATION_ACTION, action)
|
||||
putExtra(EXTRA_DOWNLOAD_ID, downloadId)
|
||||
}
|
||||
val requestCode = downloadId + action.hashCode()
|
||||
return PendingIntent.getBroadcast(
|
||||
return PendingIntent.getService(
|
||||
context,
|
||||
requestCode,
|
||||
intent,
|
||||
pendingIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
@ -250,6 +253,7 @@ class DownloadNotificationManager @Inject constructor(
|
||||
const val ACTION_PAUSE = "action_pause"
|
||||
const val ACTION_RESUME = "action_resume"
|
||||
const val ACTION_CANCEL = "action_cancel"
|
||||
const val ACTION_QUERY_DOWNLOAD_STATUS = "action_query_download_status"
|
||||
const val EXTRA_DOWNLOAD_ID = "extra_download_id"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user