Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very Slow Download Speed #690

Open
Soft-Buddy opened this issue Sep 14, 2024 · 1 comment
Open

Very Slow Download Speed #690

Soft-Buddy opened this issue Sep 14, 2024 · 1 comment

Comments

@Soft-Buddy
Copy link

I migrated from using basic HttpUrlConnection to Fetch. But I've seen a huge download speed loss.
For reference, I have 50mbps connection

Here's my code :
My old approach : (hardly takes few seconds to download)
OnlinePdfLoader.kt

import android.app.Activity
import android.content.Context
import android.util.Log
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL

@Suppress("unused")
class OnlinePdfLoader(private val activity: Activity) {
    fun resolveFile(
        target: String,
        onDownloaded: (file: File) -> Unit,
        onDownloadFailed: (error: String) -> Unit
    ) {
        Thread {
            var file: File? = null
            var inputStream: InputStream? = null
            var outputStream: FileOutputStream? = null
            try {
                val url = URL(target)
                val fileName = getFileName(url)
                val directory =
                    File(activity.filesDir.absolutePath + File.separator + DIRECTORY_TEMP)
                file = File(directory, fileName)
                if (file.exists()) {
                    activity.runOnUiThread {
                        onDownloaded(file)
                    }
                    return@Thread
                }
                val connection = url.openConnection() as HttpURLConnection
                connection.connect()
                inputStream = connection.inputStream

                if (!directory.exists()) {
                    val success = directory.mkdirs()
                    if (!success) {
                        throw Exception(
                            String.format(
                                "Error creating directory",
                                directory.name
                            )
                        )
                    }
                }
                outputStream = FileOutputStream(file)
                val bufferSize = 4096
                val buffer = ByteArray(bufferSize)
                var bytesRead: Int
                var totalBytesRead: Long = 0
                while ((inputStream.read(buffer).also { bytesRead = it }) != -1) {
                    outputStream.write(buffer, 0, bytesRead)
                    totalBytesRead += bytesRead.toLong()
                }
                activity.runOnUiThread {
                    onDownloaded(file)
                }
            } catch (e: Exception) {
                if (file != null && file.exists()) {
                    file.delete()
                }
                e.printStackTrace()
                e.message?.let {
                    activity.runOnUiThread {
                        onDownloadFailed(it)
                    }
                }
            } finally {
                try {
                    inputStream?.close()
                    outputStream?.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }.start()
    }

    fun resolveStream(
        target: String,
        onResolved: (inputStream: InputStream) -> Unit,
        onError: (error: String) -> Unit
    ) {
        Thread {
            var inputStream: InputStream? = null
            val url = URL(target)
            try {
                val connection = url.openConnection() as HttpURLConnection
                connection.connect()
                inputStream = connection.inputStream
                activity.runOnUiThread {
                    onResolved(inputStream)
                }
            } catch (e: Exception) {
                e.printStackTrace()
                e.message?.let {
                    activity.runOnUiThread {
                        onError(it)
                    }
                }
            } finally {
                try {
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }.start()
    }

    companion object {
        fun isDownloaded(context: Context, url: String): Boolean {
            val fileName = getFileName(URL(url))
            val directory =
                File(context.filesDir.absolutePath + File.separator + DIRECTORY_TEMP)
            val file = File(directory, fileName)
            return file.exists()
        }

        fun getFileName(url: URL): String {
            val urlString = url.toString()
            return urlString.substring(urlString.lastIndexOf('/') + 1)
        }
    }

    interface DownloadListener {
        fun onDownloadComplete(filePath: String)

        fun onDownloadFailed(message: String, logs: String)
    }
}

New Approach : (Takes almost a minute)

val fetch = getInstance(
            FetchConfiguration.Builder(this)
                .setHttpDownloader(OkHttpDownloader())
                .build()
        )
val request = Request(url, file.absolutePath)
                    request.priority = Priority.HIGH
                    request.networkType = NetworkType.ALL
                    circularProgress.setOnClickListener {
                        fetch.cancel(request.id)
                    }
                    fetch.enqueue(request, {
                        var fetchListener: FetchListener? = null
                        fetchListener = object : FetchListener {
                            override fun onQueued(download: Download, waitingOnNetwork: Boolean) {}

                            override fun onCompleted(d: Download) {
                                isDownloading = false
                                Toast.makeText(context, "Download Complete", Toast.LENGTH_SHORT).show()
                                mode.text = "Downloaded"
                                download.setImageResource(R.drawable.ic_delete)
                                circularProgress.visibility = View.GONE
                                download.visibility = View.VISIBLE
                                fetch.removeListener(fetchListener!!)
                            }

                            override fun onPaused(download: Download) { }

                            override fun onProgress(
                                download: Download,
                                etaInMilliSeconds: Long,
                                downloadedBytesPerSecond: Long
                            ) {

                            }

                            override fun onResumed(download: Download) {
                            }

                            override fun onStarted(
                                download: Download,
                                downloadBlocks: List<DownloadBlock>,
                                totalBlocks: Int
                            ) {

                            }

                            override fun onWaitingNetwork(download: Download) {

                            }

                            override fun onAdded(download: Download) {

                            }

                            override fun onCancelled(dw: Download) {
                                File(dw.file).delete()
                                isDownloading = false
                                mode.text = "Online"
                                circularProgress.visibility = View.GONE
                                download.visibility = View.VISIBLE
                                fetch.removeListener(fetchListener!!)
                            }

                            override fun onRemoved(download: Download) {
                            }

                            override fun onDeleted(download: Download) {
                            }

                            override fun onDownloadBlockUpdated(
                                download: Download,
                                downloadBlock: DownloadBlock,
                                totalBlocks: Int
                            ) {

                            }

                            override fun onError(
                                dw: Download,
                                error: com.tonyodev.fetch2.Error,
                                throwable: Throwable?
                            ) {
                                isDownloading = false
                                circularProgress.visibility = View.GONE
                                download.visibility = View.VISIBLE
                                mode.text = "Online"
                                Toast.makeText(context, "Download Failed. $it", Toast.LENGTH_SHORT).show()
                                fetch.removeListener(fetchListener!!)
                            }
                        }
                        fetch.addListener(fetchListener)
                    }, { error ->
                        Toast.makeText(
                            context,
                            "Error enqueuing download request. $error",
                            Toast.LENGTH_SHORT
                        ).show()
                    })
                    

Demo Video :

Old Approach-
https://github.com/user-attachments/assets/5dd25a5b-f520-41f5-80f7-554e17599b5d

New Approach -
https://github.com/user-attachments/assets/23eb3ec5-2669-4ed2-94ce-729122da8422

@tonyofrancis
Copy link
Owner

New version 3.4.0 has been released. Please try it out and let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants