diff --git a/android/build.gradle.kts b/android/build.gradle.kts index dc5be589..2e027593 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -106,31 +106,19 @@ dependencies { implementation("com.google.accompanist:accompanist-insets:0.7.1") - //DECOMPOSE + // DECOMPOSE implementation(Decompose.decompose) implementation(Decompose.extensionsCompose) - //Firebase + // Firebase implementation(platform("com.google.firebase:firebase-bom:27.0.0")) implementation("com.google.firebase:firebase-analytics-ktx") implementation("com.google.firebase:firebase-crashlytics-ktx") implementation("com.google.firebase:firebase-perf-ktx") -/* - //Lifecycle - Versions.androidLifecycle.let{ - implementation("androidx.lifecycle:lifecycle-runtime-ktx:$it") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:$it") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$it") - implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$it") - } -*/ - - Extras.Android.apply { implementation(appUpdator) implementation(razorpay) - implementation(fetch) } implementation(MVIKotlin.mvikotlin) implementation(MVIKotlin.mvikotlinMain) @@ -139,11 +127,11 @@ dependencies { implementation(Decompose.decompose) implementation(Decompose.extensionsCompose) - //Test + // Test testImplementation("junit:junit:4.13.2") androidTestImplementation(Androidx.junit) androidTestImplementation(Androidx.expresso) - //Desugaring + // Desugaring coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") } \ No newline at end of file diff --git a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt index b226b846..d5307a80 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt @@ -66,7 +66,7 @@ import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks import com.shabinder.common.uikit.* import com.shabinder.spotiflyer.utils.* -import com.tonyodev.fetch2.Status +import com.shabinder.common.models.Status import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.koin.android.ext.android.inject diff --git a/android/src/main/java/com/shabinder/spotiflyer/di/AppModule.kt b/android/src/main/java/com/shabinder/spotiflyer/di/AppModule.kt index 34ff7b9d..54077069 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/di/AppModule.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/di/AppModule.kt @@ -16,28 +16,6 @@ package com.shabinder.spotiflyer.di -import com.shabinder.common.database.appContext -import com.tonyodev.fetch2.Fetch -import com.tonyodev.fetch2.FetchConfiguration import org.koin.dsl.module -fun appModule(enableLogging:Boolean = false) = module { - single { createFetchInstance(enableLogging) } -} - -private fun createFetchInstance(enableLogging:Boolean = false):Fetch{ - val fetchConfiguration = - FetchConfiguration.Builder(appContext).run { - setNamespace("ForegroundDownloaderService") - setDownloadConcurrentLimit(4) - enableLogging(enableLogging) - build() - } - - return Fetch.run { - setDefaultInstanceConfiguration(fetchConfiguration) - getDefaultInstance() - }.apply { - removeAll() //Starting fresh - } -} \ No newline at end of file +fun appModule(enableLogging:Boolean = false) = module {} diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Status.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Status.kt new file mode 100644 index 00000000..a133732d --- /dev/null +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/Status.kt @@ -0,0 +1,64 @@ +package com.shabinder.common.models + +import kotlin.jvm.JvmStatic + +/** + * Enumeration which contains the different states a download + * could go through. + * + * From Fetch + * */ +enum class Status constructor(val value: Int) { + + /** Indicates when a download is newly created and not yet queued.*/ + NONE(0), + + /** Indicates when a newly created download is queued.*/ + QUEUED(1), + + /** Indicates when a download is currently being downloaded.*/ + DOWNLOADING(2), + + /** Indicates when a download is paused.*/ + PAUSED(3), + + /** Indicates when a download is completed.*/ + COMPLETED(4), + + /** Indicates when a download is cancelled.*/ + CANCELLED(5), + + /** Indicates when a download has failed.*/ + FAILED(6), + + /** Indicates when a download has been removed and is no longer managed by Fetch.*/ + REMOVED(7), + + /** Indicates when a download has been deleted and is no longer managed by Fetch.*/ + DELETED(8), + + /** Indicates when a download has been Added to Fetch for management.*/ + ADDED(9); + + companion object { + + @JvmStatic + fun valueOf(value: Int): Status { + return when (value) { + 0 -> NONE + 1 -> QUEUED + 2 -> DOWNLOADING + 3 -> PAUSED + 4 -> COMPLETED + 5 -> CANCELLED + 6 -> FAILED + 7 -> REMOVED + 8 -> DELETED + 9 -> ADDED + else -> NONE + } + } + + } + +} \ No newline at end of file diff --git a/common/dependency-injection/build.gradle.kts b/common/dependency-injection/build.gradle.kts index 98089083..1ffb4c60 100644 --- a/common/dependency-injection/build.gradle.kts +++ b/common/dependency-injection/build.gradle.kts @@ -20,7 +20,7 @@ plugins { id("multiplatform-setup") id("android-setup") kotlin("plugin.serialization") - kotlin("native.cocoapods") //version "1.4.32" + kotlin("native.cocoapods") } version = "1.0" @@ -69,7 +69,6 @@ kotlin { implementation(compose.materialIconsExtended) implementation(Koin.android) implementation(Ktor.clientAndroid) - implementation(Extras.Android.fetch) implementation(Extras.Android.razorpay) api(Extras.mp3agic) api(Extras.jaudioTagger) diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt index 657099bf..bd682a91 100644 --- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt +++ b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt @@ -45,15 +45,7 @@ import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.TrackDetails import com.shabinder.downloader.YoutubeDownloader import com.shabinder.downloader.models.formats.Format -import com.tonyodev.fetch2.Download -import com.tonyodev.fetch2.Error -import com.tonyodev.fetch2.Fetch -import com.tonyodev.fetch2.FetchListener -import com.tonyodev.fetch2.NetworkType -import com.tonyodev.fetch2.Priority -import com.tonyodev.fetch2.Request -import com.tonyodev.fetch2.Status -import com.tonyodev.fetch2core.DownloadBlock +import com.shabinder.common.models.Status import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -80,7 +72,6 @@ class ForegroundService : Service(), CoroutineScope { override val coroutineContext: CoroutineContext get() = serviceJob + Dispatchers.IO - //private val requestMap = hashMapOf() private val allTracksStatus = hashMapOf() private var wakeLock: PowerManager.WakeLock? = null private var isServiceStarted = false @@ -90,7 +81,6 @@ class ForegroundService : Service(), CoroutineScope { private lateinit var downloadService: ParallelExecutor private val fetcher: FetchPlatformQueryResult by inject() private val logger: Kermit by inject() - private val fetch: Fetch by inject() private val dir: Dir by inject() private val ytDownloader: YoutubeDownloader get() = fetcher.youtubeProvider.ytDownloader @@ -111,7 +101,6 @@ class ForegroundService : Service(), CoroutineScope { ).apply { action = "kill" } cancelIntent = PendingIntent.getService(this, 0, intent, FLAG_CANCEL_CURRENT) downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager - //fetch.removeAllListeners().addListener(fetchListener) } @SuppressLint("WakelockTimeout") @@ -245,14 +234,14 @@ class ForegroundService : Service(), CoroutineScope { sendBroadcast(intent) } - is DownloadResult.Success -> { // Todo clear map + is DownloadResult.Success -> { try { // Save File and Embed Metadata val job = launch(Dispatchers.Default) { dir.saveFileWithMetadata(it.byteArray, track) } allTracksStatus[track.title] = DownloadStatus.Converting sendTrackBroadcast("Converting", track) addToNotification("Processing ${track.title}") - job.invokeOnCompletion { _ -> + job.invokeOnCompletion { converted++ allTracksStatus[track.title] = DownloadStatus.Downloaded sendTrackBroadcast(Status.COMPLETED.name, track) @@ -274,152 +263,12 @@ class ForegroundService : Service(), CoroutineScope { } } } - - /* val request = Request(url, track.outputFilePath).apply { - priority = Priority.NORMAL - networkType = NetworkType.ALL - } - fetch.enqueue( - request, - { request1 -> - requestMap[request1] = track - logger.d(tag) { "Enqueuing Download" } - }, - { error -> - logger.d(tag) { "Enqueuing Error:${error.throwable}" } - } - )*/ } - /** - * Fetch Listener/ Responsible for Fetch Behaviour - **/ - /*private var fetchListener: FetchListener = object : FetchListener { - override fun onQueued( - download: Download, - waitingOnNetwork: Boolean - ) { - requestMap[download.request]?.let { sendTrackBroadcast(Status.QUEUED.name, it) } - } - - override fun onRemoved(download: Download) { - // TODO("Not yet implemented") - } - - override fun onResumed(download: Download) { - // TODO("Not yet implemented") - } - - override fun onStarted( - download: Download, - downloadBlocks: List, - totalBlocks: Int - ) { - launch { - val track = requestMap[download.request] - addToNotification("Downloading ${track?.title}") - logger.d(tag) { "${track?.title} Download Started" } - track?.let { - allTracksStatus[it.title] = DownloadStatus.Downloading() - sendTrackBroadcast(Status.DOWNLOADING.name, track) - } - } - } - - override fun onWaitingNetwork(download: Download) { - // TODO("Not yet implemented") - } - - override fun onAdded(download: Download) { - // TODO("Not yet implemented") - } - - override fun onCancelled(download: Download) { - // TODO("Not yet implemented") - } - - override fun onCompleted(download: Download) { - val track = requestMap[download.request] - try { - track?.let { - val job = launch { dir.saveFileWithMetadata(byteArrayOf(), it) } - allTracksStatus[it.title] = DownloadStatus.Converting - sendTrackBroadcast("Converting", it) - addToNotification("Processing ${it.title}") - job.invokeOnCompletion { _ -> - converted++ - allTracksStatus[it.title] = DownloadStatus.Downloaded - sendTrackBroadcast(Status.COMPLETED.name, it) - removeFromNotification("Processing ${it.title}") - } - } - logger.d(tag) { "${track?.title} Download Completed" } - } catch ( - e: KotlinNullPointerException - ) { - logger.d(tag) { "${track?.title} Download Failed! Error:Fetch!!!!" } - logger.d(tag) { "${track?.title} Requesting Download thru Android DM" } - downloadUsingDM(download.request.url, download.request.file, track!!) - } - downloaded++ - requestMap.remove(download.request) - removeFromNotification("Downloading ${track?.title}") - } - - override fun onDeleted(download: Download) { - // TODO("Not yet implemented") - } - - override fun onDownloadBlockUpdated( - download: Download, - downloadBlock: DownloadBlock, - totalBlocks: Int - ) { - // TODO("Not yet implemented") - } - - override fun onError(download: Download, error: Error, throwable: Throwable?) { - launch { - val track = requestMap[download.request] - downloaded++ - logger.d(tag) { download.error.throwable.toString() } - logger.d(tag) { "${track?.title} Requesting Download thru Android DM" } - downloadUsingDM(download.request.url, download.request.file, track!!) - requestMap.remove(download.request) - removeFromNotification("Downloading ${track.title}") - } - updateNotification() - } - - override fun onPaused(download: Download) { - // TODO("Not yet implemented") - } - - override fun onProgress( - download: Download, - etaInMilliSeconds: Long, - downloadedBytesPerSecond: Long - ) { - launch { - requestMap[download.request]?.run { - allTracksStatus[title] = DownloadStatus.Downloading(download.progress) - logger.d(tag) { "$title ETA: ${etaInMilliSeconds / 1000} sec" } - - val intent = Intent().apply { - action = "Progress" - putExtra("progress", download.progress) - putExtra("track", this@run) - } - sendBroadcast(intent) - } - } - } - }*/ - /** * If fetch Fails , Android Download Manager To RESCUE!! **/ - fun downloadUsingDM(url: String, outputDir: String, track: TrackDetails) { + private fun downloadUsingDM(url: String, outputDir: String, track: TrackDetails) { launch { val uri = Uri.parse(url) val request = DownloadManager.Request(uri).apply { @@ -514,8 +363,6 @@ class ForegroundService : Service(), CoroutineScope { launch { logger.d(tag) { "Killing Self" } messageList = mutableListOf("Cleaning And Exiting", "", "", "", "") - fetch.cancelAll() - fetch.removeAll() downloadService.close() updateNotification() cleanFiles(File(dir.defaultDir())) @@ -573,7 +420,7 @@ class ForegroundService : Service(), CoroutineScope { updateNotification() } - fun sendTrackBroadcast(action: String, track: TrackDetails) { + private fun sendTrackBroadcast(action: String, track: TrackDetails) { val intent = Intent().apply { setAction(action) putExtra("track", track) @@ -581,10 +428,3 @@ class ForegroundService : Service(), CoroutineScope { this@ForegroundService.sendBroadcast(intent) } } - -private fun Fetch.removeAllListeners(): Fetch { - for (listener in this.getListenerSet()) { - this.removeListener(listener) - } - return this -}