khushpanchal / Ketch

An Android File downloader library based on WorkManager with pause and resume support.
https://medium.com/@khush.panchal123/ketch-android-file-downloader-library-7369f7b93bd1
440 stars 33 forks source link

Clear queue after a file has been downloaded #22

Closed Sir-Dave closed 2 months ago

Sir-Dave commented 2 months ago

When I use the download() function, passing in a file, it gets downloaded. However, when I pass in another file, the new file gets downloaded alongside the first one and this happens for subsequent files.

Is there a way to clear queue after a file has been downloaded, so it does not get downloaded again?

khushpanchal commented 2 months ago

Are you passing the same download url, name and path?

In case yes, library will delete the existing file and re download the same file.

You can check if file is not downloaded, then only call download function.

Additionally if you are sending the same filename and path but with different url, then also the previous file will be deleted and new file will download.

Every filename, path, and download url makes a unique id again which download happens.

Sir-Dave commented 2 months ago

Oh no, I have already implemented the check for if the file exists. I am passing another file and a different url, but when I check the content of ketch.getAllDownloads(), the second file is referencing the url of the first file, even though it has its own url.

khushpanchal commented 2 months ago

Hm, I need to reproduce it to check. Could you help with the exact steps to reproduce this?

Sir-Dave commented 2 months ago

Sure thing. Here you go:

`fun downloadSong( fileUrl: String, trackExtension: String, extractedDir: File, trackName: String){

val filename = File("${trackName}$trackExtension")
        if (filename.exists())
        return

val id = ketch.download(
            url = fileUrl,
            path = extractedDir.absolutePath,
            fileName = filename
       )

CoroutineScope(Dispatchers.IO).launch {
        val ongoingDownloads = ketch.getAllDownloads()
        ongoingDownloads.forEach {
            Log.d(TAG, "${it.url} - ${it.fileName}")
        }
    }

    CoroutineScope(Dispatchers.IO).launch {

        ketch.observeDownloadById(id).collect{ downloadModel ->
            when (downloadModel.status){
                Status.QUEUED -> {
                    Log.d(TAG, "Operation queued")
                }
                Status.STARTED -> {
                    Log.d(TAG, "Operation started")
                }
                Status.PROGRESS -> {
                    val progress = downloadModel.progress
                    Log.d(TAG, "Operation in progress downloadId: ${downloadModel.id} --> progress $progress")
                }
                Status.SUCCESS -> {
                    Log.d(TAG, "Operation successful")
                }
                Status.CANCELLED -> {
                    Log.d(TAG, "Operation cancelled")
                }
                Status.PAUSED -> {
                    Log.d(TAG, "Operation paused")
                }
                Status.FAILED -> {
        Log.d(TAG, "Operation failed")
                }
                Status.DEFAULT -> {
                    Log.d(TAG, "Default operation")
                }
            }
        }
    }
}`

When this function is executed with a filename "Afro Pop.mp3" and an example url "https://www.example.com/afro-pop.mp3", the first song is downloaded alright. However, when you pass another filename e.g "Afro Rhythm.mp3" with its own url e.g "https://www.example.com/afro-rhythm.mp3", it saves the content of Afro Pop into Afro Rhythm, while using the original name.

If you inspect the content of ketch.getAllDownloads(), I added logs to show that the downloadModel with the file name Afro Rhythm has its url pointed to that from Afro Pop.

khushpanchal commented 2 months ago

I tried, it working fine at my end.

 21:36:02.137  D  Operation queued
 21:36:02.697  D  Operation queued
 21:36:03.622  D  Operation started
 21:36:05.133  D  Operation in progress downloadId: -778282298 --> progress 1
 21:36:06.631  D  Operation in progress downloadId: -778282298 --> progress 18
 21:36:08.130  D  Operation in progress downloadId: -778282298 --> progress 38
 21:36:09.742  D  Operation in progress downloadId: -778282298 --> progress 56
 21:36:11.257  D  Operation in progress downloadId: -778282298 --> progress 75
 21:36:12.766  D  Operation in progress downloadId: -778282298 --> progress 95
 21:36:13.143  D  Operation in progress downloadId: -778282298 --> progress 100
 21:36:13.189  D  Operation successful
 21:36:16.399  D  https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 - BigBuckBunny.mp4
 21:36:16.437  D  Operation queued
 21:36:16.722  D  Operation queued
 21:36:17.755  D  Operation started
 21:36:20.772  D  Operation in progress downloadId: 1881062884 --> progress 17
 21:36:22.274  D  Operation in progress downloadId: 1881062884 --> progress 35
 21:36:23.772  D  Operation in progress downloadId: 1881062884 --> progress 53
 21:36:25.291  D  Operation in progress downloadId: 1881062884 --> progress 70
 21:36:26.810  D  Operation in progress downloadId: 1881062884 --> progress 88
 21:36:27.967  D  Operation in progress downloadId: 1881062884 --> progress 100
 21:36:27.996  D  Operation successful

Also why are you putting type File inside filename variable?

Also when you called ketch.getAllDownloads second time, you may get previous download, because you are calling it immediately after ketch.download() call, so it may be possible that it is not yet inserted into DB.

Sir-Dave commented 2 months ago

The filename was just for debugging purposes initially. The bug was due to some coroutine issues on my end which has now been resolved.

So yeah, it is working correctly now. Thank you for your time and your work!