Download manger not able to download large files in android

988 Views Asked by At

By large file i mean 8.5 MB and by small files I mean 80KB to 1MB.

while download manager can download files up to 2GB

The below code is able to download small files but not large one. For the large files it shows the downloading notification but then after some time shows 0kb/unknown (waiting for retry) in the notification. And in the logcat there is no error or any kind of message which can point to this problem. I'm calling this code from a normal service() class.

    if (PermissionsUtil.hasExternalStoragePermission(context)) {
                if (fileName.isNotBlank() && mimeType.isNotBlank()) {
                    // get download service and enqueue file
                    Toaster.showMessageShort(R.string.download_started)
                    manager?.let {
                        enq = it.enqueue(getDownloadManagerRequest(link, mimeType, fileName, withHeader))
                        context.registerReceiver(downloadCompletionReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
                    }
                }
            }

PS:

Im able to download large file in the postman using the same URL which is being provided to the download manger.

My network is working fine, I have tried with 6 different phone on different networks, all the showing the same behaviors.

On trying to listen to all the events while the (large) file is getting downloaded I get the below event

PAUSED_WAITING_TO_RETRY

Update

So I tried these test pdf files of various different sizes (100MB to 1GB), they are getting downloaded without any issue. But the 8.5MB whose URL im getting in an API response is showing the PAUSED_WAITING_TO_RETRY message.

And I also noticed one thing, when I tested the 1GB file in postman it just took almost half a second to send request after that it started downloading the file, but when I tried the 8.5MB one it almost takes more then a mintune in sending the request.

So is there anything like "Time Out" which can be set on a download manager because I think that might be the case, that the url is taking lot of time in sending the request and in the main time download manger runs out of time. (Just an assumption)

1

There are 1 best solutions below

9
On

Download manager has limitation only with available disk space. To check downloading status you need to use download id returned by enqueue(...) method. Check this example

private val statusHandler = Handler(Looper.getMainLooper())
private val statusRunnable = Runnable {
     downloadStatusQuery(downloadId)
}

private fun downloadStatusQuery(id: Long) {

    val downloadQuery = DownloadManager.Query()
    downloadQuery.setFilterById(id)

    val cursor = mDownloadManager.query(downloadQuery)
    Thread {
        cursor.use { cursor ->
            if (cursor.moveToFirst()) {
                downloadStatus(cursor, id)
            }
        }
    }.start()
}

private fun downloadStatus(cursor: Cursor, id: Long) {

    //column for download  status
    val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
    val status = cursor.getInt(columnIndex)
    //column for reason code if the download failed or paused
    val columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON)
    val reason = cursor.getInt(columnReason)
    var statusText = ""
    var reasonText = ""
    val bytesTotal = cursor.getLong(
        cursor.getColumnIndex(
            DownloadManager.COLUMN_TOTAL_SIZE_BYTES
        )
    )

    when (status) {
        DownloadManager.STATUS_FAILED -> {
            statusText = "STATUS_FAILED"
            when (reason) {
                DownloadManager.ERROR_CANNOT_RESUME -> reasonText = "ERROR_CANNOT_RESUME"
                DownloadManager.ERROR_DEVICE_NOT_FOUND -> reasonText = "ERROR_DEVICE_NOT_FOUND"
                DownloadManager.ERROR_FILE_ALREADY_EXISTS -> reasonText =
                    "ERROR_FILE_ALREADY_EXISTS"
                DownloadManager.ERROR_FILE_ERROR -> reasonText = "ERROR_FILE_ERROR"
                DownloadManager.ERROR_HTTP_DATA_ERROR -> reasonText = "ERROR_HTTP_DATA_ERROR"
                DownloadManager.ERROR_INSUFFICIENT_SPACE -> reasonText =
                    "ERROR_INSUFFICIENT_SPACE"
                DownloadManager.ERROR_TOO_MANY_REDIRECTS -> reasonText =
                    "ERROR_TOO_MANY_REDIRECTS"
                DownloadManager.ERROR_UNHANDLED_HTTP_CODE -> reasonText =
                    "ERROR_UNHANDLED_HTTP_CODE"
                DownloadManager.ERROR_UNKNOWN -> reasonText = "ERROR_UNKNOWN"
            }
          statusHandler.removeCallbacks(statusRunnable)
        }
        DownloadManager.STATUS_PAUSED -> {
            statusText = "STATUS_PAUSED"
            when (reason) {
                DownloadManager.PAUSED_QUEUED_FOR_WIFI -> reasonText = "PAUSED_QUEUED_FOR_WIFI"
                DownloadManager.PAUSED_UNKNOWN -> reasonText = "PAUSED_UNKNOWN"
                DownloadManager.PAUSED_WAITING_FOR_NETWORK -> reasonText =
                    "PAUSED_WAITING_FOR_NETWORK"
                DownloadManager.PAUSED_WAITING_TO_RETRY -> reasonText =
                    "PAUSED_WAITING_TO_RETRY"
            }
            statusHandler.postDelayed(statusRunnable, 2000)
        }
        DownloadManager.STATUS_PENDING -> {
            statusHandler.postDelayed(statusRunnable, 2000)
            statusText = "STATUS_PENDING"
        }
        DownloadManager.STATUS_RUNNING -> {
            statusHandler.postDelayed(statusRunnable, 2000)
            statusText = "STATUS_RUNNING"
        }
        DownloadManager.STATUS_SUCCESSFUL -> {
            statusText = "STATUS_SUCCESSFUL"
            statusHandler.removeCallbacks(statusRunnable)
        }
    }

    Log.i(TAG, "Status $statusText : $reasonText : ID: $id")
}