From 5e6d171675fcdc43f63b397369ea3eb5779aa5bb Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 6 Feb 2023 07:13:38 +0530 Subject: [PATCH] Convert DownloadService and BackgroundMode to lifecycle services. --- .../libretube/services/BackgroundMode.kt | 33 ++++++++----------- .../libretube/services/DownloadService.kt | 32 ++++++++---------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt index 01541746a..7d5d6c39e 100644 --- a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt +++ b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt @@ -3,7 +3,6 @@ package com.github.libretube.services import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager -import android.app.Service import android.content.Intent import android.os.Binder import android.os.Build @@ -13,10 +12,11 @@ import android.os.Looper import android.util.Log import android.widget.Toast import androidx.core.app.ServiceCompat +import androidx.lifecycle.LifecycleService +import androidx.lifecycle.lifecycleScope import com.github.libretube.R import com.github.libretube.api.JsonHelper import com.github.libretube.api.RetrofitInstance -import com.github.libretube.api.obj.Segment import com.github.libretube.api.obj.SegmentData import com.github.libretube.api.obj.Streams import com.github.libretube.constants.BACKGROUND_CHANNEL_ID @@ -37,15 +37,15 @@ import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.PlaybackException import com.google.android.exoplayer2.Player -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import kotlinx.serialization.encodeToString /** * Loads the selected videos audio in background mode with a notification area. */ -class BackgroundMode : Service() { +class BackgroundMode : LifecycleService() { /** * VideoId of the video */ @@ -171,7 +171,7 @@ class BackgroundMode : Service() { seekToPosition: Long = 0, keepQueue: Boolean = false ) { - CoroutineScope(Dispatchers.IO).launch { + lifecycleScope.launch(Dispatchers.IO) { streams = runCatching { RetrofitInstance.api.getStreams(videoId) }.getOrNull() ?: return@launch @@ -186,7 +186,7 @@ class BackgroundMode : Service() { PlayingQueue.updateCurrent(it) } - handler.post { + withContext(Dispatchers.Main) { playAudio(seekToPosition) } } @@ -292,18 +292,12 @@ class BackgroundMode : Service() { * Sets the [MediaItem] with the [streams] into the [player] */ private fun setMediaItem() { + val streams = streams streams ?: return - val uri = if (streams!!.audioStreams.orEmpty().isNotEmpty()) { - PlayerHelper.getAudioSource( - this, - streams!!.audioStreams!! - ) - } else if (streams!!.hls != null) { - streams!!.hls - } else { - return - } + val uri = if (streams.audioStreams.isNotEmpty()) { + PlayerHelper.getAudioSource(this, streams.audioStreams) + } else streams.hls ?: return val mediaItem = MediaItem.Builder() .setUri(uri) @@ -315,7 +309,7 @@ class BackgroundMode : Service() { * fetch the segments for SponsorBlock */ private fun fetchSponsorBlockSegments() { - CoroutineScope(Dispatchers.IO).launch { + lifecycleScope.launch(Dispatchers.IO) { runCatching { val categories = PlayerHelper.getSponsorBlockCategories() if (categories.isEmpty()) return@runCatching @@ -336,7 +330,7 @@ class BackgroundMode : Service() { if (segmentData == null || segmentData!!.segments.isEmpty()) return - segmentData!!.segments.forEach { segment: Segment -> + segmentData!!.segments.forEach { segment -> val segmentStart = (segment.segment[0] * 1000f).toLong() val segmentEnd = (segment.segment[1] * 1000f).toLong() val currentPosition = player?.currentPosition @@ -399,7 +393,8 @@ class BackgroundMode : Service() { fun getService(): BackgroundMode = this@BackgroundMode } - override fun onBind(p0: Intent?): IBinder { + override fun onBind(intent: Intent): IBinder { + super.onBind(intent) return binder } diff --git a/app/src/main/java/com/github/libretube/services/DownloadService.kt b/app/src/main/java/com/github/libretube/services/DownloadService.kt index eefe9affd..9fe3f4859 100644 --- a/app/src/main/java/com/github/libretube/services/DownloadService.kt +++ b/app/src/main/java/com/github/libretube/services/DownloadService.kt @@ -2,7 +2,6 @@ package com.github.libretube.services import android.app.NotificationManager import android.app.PendingIntent -import android.app.Service import android.content.Intent import android.os.Binder import android.os.IBinder @@ -11,6 +10,8 @@ import androidx.core.app.NotificationCompat import androidx.core.app.ServiceCompat import androidx.core.util.set import androidx.core.util.valueIterator +import androidx.lifecycle.LifecycleService +import androidx.lifecycle.lifecycleScope import com.github.libretube.R import com.github.libretube.api.CronetHelper import com.github.libretube.api.RetrofitInstance @@ -40,13 +41,9 @@ import java.io.File import java.net.HttpURLConnection import java.net.SocketTimeoutException import java.net.URL -import java.util.concurrent.Executors import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.launch @@ -59,12 +56,8 @@ import okio.source /** * Download service with custom implementation of downloading using [HttpURLConnection]. */ -class DownloadService : Service() { - +class DownloadService : LifecycleService() { private val binder = LocalBinder() - private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() - private val jobMain = SupervisorJob() - private val scope = CoroutineScope(dispatcher + jobMain) private lateinit var notificationManager: NotificationManager private lateinit var summaryNotificationBuilder: NotificationCompat.Builder @@ -81,6 +74,7 @@ class DownloadService : Service() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + super.onStartCommand(intent, flags, startId) when (intent?.action) { ACTION_DOWNLOAD_RESUME -> resume(intent.getIntExtra("id", -1)) ACTION_DOWNLOAD_PAUSE -> pause(intent.getIntExtra("id", -1)) @@ -94,9 +88,11 @@ class DownloadService : Service() { val audioQuality = intent.getStringExtra(IntentData.audioQuality) val subtitleCode = intent.getStringExtra(IntentData.subtitleCode) - scope.launch { + lifecycleScope.launch { try { - val streams = RetrofitInstance.api.getStreams(videoId) + val streams = withContext(Dispatchers.IO) { + RetrofitInstance.api.getStreams(videoId) + } val thumbnailTargetFile = getDownloadFile(DownloadHelper.THUMBNAIL_DIR, fileName) @@ -153,7 +149,7 @@ class DownloadService : Service() { Database.downloadDao().insertDownloadItem(item) }.toInt() - scope.launch { + lifecycleScope.launch { downloadFile(item) } } @@ -297,7 +293,7 @@ class DownloadService : Service() { val downloadCount = downloadQueue.valueIterator().asSequence().count { it } if (downloadCount >= DownloadHelper.getMaxConcurrentDownloads()) { toastFromMainThread(getString(R.string.concurrent_downloads_limit_reached)) - scope.launch { + lifecycleScope.launch { _downloadFlow.emit(id to DownloadStatus.Paused) } return @@ -306,7 +302,7 @@ class DownloadService : Service() { val downloadItem = awaitQuery { Database.downloadDao().findDownloadItemById(id) } - scope.launch { + lifecycleScope.launch { downloadFile(downloadItem) } } @@ -468,9 +464,9 @@ class DownloadService : Service() { super.onDestroy() } - override fun onBind(intent: Intent?): IBinder { - val ids = intent?.getIntArrayExtra("ids") - ids?.forEach { id -> resume(id) } + override fun onBind(intent: Intent): IBinder { + super.onBind(intent) + intent.getIntArrayExtra("ids")?.forEach { resume(it) } return binder }