DownloadManager का उपयोग करके गतिविधि के अंदर डाउनलोड प्रगति दिखाएं


89

मैं उसी प्रगति को पुन: पेश करने की कोशिश कर रहा हूं जो DownloadManager अपने ऐप के अंदर सूचना पट्टी में दिखाता है, लेकिन मेरी प्रगति कभी प्रकाशित नहीं होती है। मैं इसे runOnUiThread () का उपयोग करके अपडेट करने का प्रयास कर रहा हूं, लेकिन किसी कारण से इसे अपडेट नहीं किया गया है।

मेरा डाउनलोड:

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

मेरी स्थिति

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

मेरा लॉग पूरी तरह से काम कर रहा है, जबकि मेरा डाउनलोड चल रहा है "प्रगति में डाउनलोड करें!" और जब यह पूरा हो गया है "डाउनलोड पूरा!", लेकिन वही मेरी प्रगति पर नहीं होता है, क्यों? मुझे वास्तव में कुछ मदद की ज़रूरत है, अन्य लॉजिक्स जो वास्तव में सराहना की जाती हैं


क्या यह हो सकता है कि आपकी फ़ाइल बहुत छोटी है, और प्रगति प्रकाशित होने से पहले डाउनलोड पूरा हो गया है? आपके कार्य में डाउनलोड क्वेरी क्या लौटाती है? यदि कार्य को केवल कुछ समय के बाद निष्पादित किया जाता है, तो आपके मुख्य धागे पर कुछ अन्य लंबे समय तक चलने वाला ऑपरेशन हो सकता है।
पॉल लामर्ट्स्मा

मैंने कोड अपडेट कर दिया है, क्या आप अभी देख सकते हैं? और फ़ाइल के बारे में यह बहुत छोटा नहीं है, मैं सूचना पट्टी पर डाउनलोड प्रगति देख सकता हूं
विक्टर लेरटे

जवाबों:


62

आप दो पूर्णांकों को विभाजित कर रहे हैं:

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

की bytes_downloadedतुलना में कम है bytes_total, (bytes_downloaded / bytes_total)0 होगा, और इसलिए आपकी प्रगति हमेशा 0 होगी।

अपनी गणना बदलें

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

पूरे (यद्यपि फ्लोयर्ड) प्रतिशत में प्रगति प्राप्त करना।


@AZ_ आपके योगदान के लिए धन्यवाद। मैं आपको अधिक विस्तृत समाधान के साथ अपना जवाब जोड़ने का सुझाव दूंगा।
पॉल लामर्ट्समा

यह ठीक है मैं पहले से स्वीकार किए गए उत्तर का एक और जवाब नहीं देना चाहता क्योंकि यह उपयोगकर्ताओं के लिए मुश्किल होगा। आप मेरे संपादन को स्वीकार नहीं करने का विकल्प चुन सकते हैं :)
AZ_

1
यदि आपकी गतिविधि समाप्त हो जाती है और आप डाउनलोड रद्द करना चाहते हैं, तो आपको एक division by zeroघातक त्रुटि मिलेगी । इसलिए मैंने इसे पसंद किया final int dl_progress = ( bytes_total > 0 ? (int) ((bytes_downloaded * 100L) / bytes_total) : 0 );
KaHa6uc

17

पॉल का जवाब सही है लेकिन बड़े डाउनलोड के साथ आप बहुत जल्दी अधिकतम हिट करेंगे और नकारात्मक प्रगति प्राप्त करना शुरू कर देंगे। मैंने इस मुद्दे को हल करने के लिए इसका इस्तेमाल किया:

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

तुम सही हो; मैंने अपने उत्तर को यह सुनिश्चित करने के लिए संशोधित किया है कि अन्य लोग एक ही गलती न करें।
पॉल लामर्ट्स्मा

4

जैसा कि पॉल ने कहा, आप दो पूर्णांकों को विभाजित कर रहे हैं, परिणाम हमेशा <1 के साथ।

विभाजित होने से पहले हमेशा अपना नंबर डालें , जो फ्लोट-पॉइंट में गणना और वापस आए।

DivByZero को हैंडल करना न भूलें।

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

4

अगर किसी को RxJava के साथ Kotlin में @Victor Laerte के प्रश्न से डाउनलोड प्रगति के कार्यान्वयन की आवश्यकता है तो यहां जाएं:

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

मैंने अधिक कोड स्पष्टता के लिए कर्सर में एक्सटेंशन जोड़े हैं:

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))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.