DownloadManager'ı kullanarak aktivite içindeki İndirme ilerlemesini göster


90

DownloadManager'ın uygulamamın içindeki Bildirim çubuğunda gösterdiği ilerlemeyi yeniden oluşturmaya çalışıyorum, ancak ilerlemem asla yayınlanmıyor. RunOnUiThread () kullanarak güncellemeye çalışıyorum, ancak bazı nedenlerden dolayı güncellenmedi.

indirmem:

String urlDownload = "https://dl.dropbox.com/s/ex4clsfmiu142dy/test.zip?token_hash=AAGD-XcBL8C3flflkmxjbzdr7_2W_i6CZ_3rM5zQpUCYaw&dl=1";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(urlDownload));

request.setDescription("Testando");
request.setTitle("Download");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "teste.zip");

final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);

final long downloadId = manager.enqueue(request);

final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);

new Thread(new Runnable() {

    @Override
    public void run() {

        boolean downloading = true;

        while (downloading) {

            DownloadManager.Query q = new DownloadManager.Query();
            q.setFilterById(downloadId);

            Cursor cursor = manager.query(q);
            cursor.moveToFirst();
            int bytes_downloaded = cursor.getInt(cursor
                    .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
            int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

            if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                downloading = false;
            }

            final double dl_progress = (bytes_downloaded / bytes_total) * 100;

            runOnUiThread(new Runnable() {

                @Override
                public void run() {

                    mProgressBar.setProgress((int) dl_progress);

                }
            });

            Log.d(Constants.MAIN_VIEW_ACTIVITY, statusMessage(cursor));
            cursor.close();
        }

    }
}).start();

my statusMessage yöntemim:

private String statusMessage(Cursor c) {
    String msg = "???";

    switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
    case DownloadManager.STATUS_FAILED:
        msg = "Download failed!";
        break;

    case DownloadManager.STATUS_PAUSED:
        msg = "Download paused!";
        break;

    case DownloadManager.STATUS_PENDING:
        msg = "Download pending!";
        break;

    case DownloadManager.STATUS_RUNNING:
        msg = "Download in progress!";
        break;

    case DownloadManager.STATUS_SUCCESSFUL:
        msg = "Download complete!";
        break;

    default:
        msg = "Download is nowhere in sight";
        break;
    }

    return (msg);
}

Günlüğüm mükemmel çalışıyor, indirme işlemim devam ederken "İndirme işlemi devam ediyor!" ve tamamlandığında "İndirme tamamlandı!", ancak ilerlememde aynı şey olmuyor, neden? Gerçekten biraz yardıma ihtiyacım var, bunu yapmak için diğer mantıklar gerçekten takdir ediliyor


Dosyanızın çok küçük olması ve indirme işleminin ilerleme yayınlanmadan önce tamamlanması olabilir mi? İndirme sorgusu görevinizde ne döndürür? Görev yalnızca belirli bir süre sonra yürütülürse, ana iş parçacığınız üzerinde uzun süre çalışan başka bir işleminiz olabilir.
Paul Lammertsma

Kodu güncelledim, şimdi bir bakabilir misin? Ve dosya uzunluğu hakkında çok küçük değil, indirme ilerlemesini bildirim çubuğunda görebiliyorum
Victor Laerte

Yanıtlar:


62

İki tam sayıyı bölüyorsunuz:

final double dl_progress = (bytes_downloaded / bytes_total) * 100;

Şundan bytes_downloadedküçük olduğu gibi bytes_total, (bytes_downloaded / bytes_total)0 olacak ve bu nedenle ilerlemeniz her zaman 0 olacaktır.

Hesaplamanızı şununla değiştirin:

final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);

ilerlemeyi bütün olarak (tabanlı olsa da) yüzdelik dilimlerde elde etmek.


@AZ_ Katkınız için teşekkürler. Daha ayrıntılı bir çözümle kendi cevabınızı eklemenizi öneririm.
Paul Lammertsma

Sorun değil Zaten kabul edilmiş cevaba başka bir cevap koymak istemiyorum çünkü kullanıcılar için zor olacak. Düzenlememi kabul etmemeyi tercih edebilirsiniz :)
AZ_

1
Aktiviteniz biterse ve indirmeyi iptal etmek isterseniz, division by zeroölümcül bir hata alırsınız . Bu yüzden beğendim final int dl_progress = ( bytes_total > 0 ? (int) ((bytes_downloaded * 100L) / bytes_total) : 0 );
KaHa6uc

17

Paul'un cevabı doğru, ancak daha büyük indirmelerle max int'e oldukça hızlı bir şekilde ulaşacak ve olumsuz bir ilerleme kaydedeceksiniz. Sorunu çözmek için bunu kullandım:

final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);

Haklısın; Başkalarının da aynı hatayı yapmamasını sağlamak için cevabımı değiştirdim.
Paul Lammertsma

5

Birinin @Victor Laerte'nin RxJava ile Kotlin'deki sorusundan indirme ilerleme alıcısının uygulanmasına ihtiyaç duyması durumunda, buraya gidin:

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)
}

Daha fazla kod netliği için imlece uzantılar ekledim:

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))


4

Paul'un dediği gibi, sonuç her zaman <1 olacak şekilde iki tamsayıyı bölersiniz.

Sayınızı daima bölmeden önce çevirin, bu hesaplanır ve kayan noktada döner.

DivByZero'yu kullanmayı unutmayın.

final int dl_progress = (int) ((double)bytes_downloaded / (double)bytes_total * 100f);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.