Show Download progress inside activity using DownloadManager
In case if someone needs implementation of download progress retriever from @Victor Laerte's question in Kotlin with RxJava here you go:
DownloadStateRetriever.kt
class DownloadStateRetriever(private val downloadManager: DownloadManager) {
fun retrieve(id: Long) {
var downloading = AtomicBoolean(true)
val disposable = Observable.fromCallable {
val query = DownloadManager.Query().setFilterById(id)
val cursor = downloadManager.query(query)
cursor.moveToFirst()
val bytesDownloaded = cursor.intValue(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
val bytesTotal = cursor.intValue(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
if (isSuccessful(cursor)) downloading.set(false)
cursor.close()
if (bytesTotal == 0) 0.toInt() else ((bytesDownloaded * 100F) / bytesTotal).toInt()
}
.subscribeOn(Schedulers.newThread())
.delay(1, TimeUnit.SECONDS)
.repeatUntil { !downloading.get() }
.subscribe {
Timber.i("Subscribed to $id. progress: $it")
}
}
private fun isSuccessful(cursor: Cursor) = status(cursor) == DownloadManager.STATUS_SUCCESSFUL
private fun status(cursor: Cursor) = cursor.intValue(DownloadManager.COLUMN_STATUS)
}
I have added extensions to cursor for more code clarity:
CursorExtensions.kt
import android.database.Cursor
fun Cursor.column(which: String) = this.getColumnIndex(which)
fun Cursor.intValue(which: String): Int = this.getInt(column(which))
fun Cursor.floatValue(which: String): Float = this.getFloat(column(which))
fun Cursor.stringValue(which: String): String = this.getString(column(which))
fun Cursor.doubleValue(which: String): Double = this.getDouble(column(which))
As paul said, you are dividing two integers, with result always <1.
Always cast your number before divide, which calculate and return in float-point.
Don't forget to handle DivByZero.
final int dl_progress = (int) ((double)bytes_downloaded / (double)bytes_total * 100f);
You are dividing two integers:
final double dl_progress = (bytes_downloaded / bytes_total) * 100;
As bytes_downloaded
is less than bytes_total
, (bytes_downloaded / bytes_total)
will be 0, and your progress will therefore always be 0.
Change your calculation to
final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
to obtain the progress in whole (albeit floored) percentiles.
Paul's answer is correct but with larger downloads you will hit max int pretty quick and start getting a negative progress. I used this to solve the issue:
final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);