Android ProgressBar in ListView while using DownloadManager

后端 未结 3 1568
深忆病人
深忆病人 2020-12-30 13:36

I have a ListView in which each item represents a PDF file. When the user clicks on an item, the application must download the file on external storage. Now the download doe

相关标签:
3条回答
  • 2020-12-30 14:03

    I'd use an AsyncTask for that, and make the wheel appear / disappear in onPreCreate & onPostCreate

    private class MyDownloader extends AsyncTask<String, Void, File>{
    
        @Override
        protected void onPreExecute() {
            loader.setVisibility(View.VISIBLE);
        }
    
        @Override
        protected File doInBackground(String... params) {
            //Download and save file here, and return the result, which will be fed into the onPostExecute method
            return file;
        }
    
        @Override
        protected void onPostExecute(File file) {
            super.onPostExecute(file);
            loader.setVisibility(View.GONE);
        }
    }
    

    Then start the task with new MyDownloader().execute("linktopdf"); or something like that (what you put in .execute will be fed into the doInBackground method)

    0 讨论(0)
  • 2020-12-30 14:11

    Ok so I managed to do what I wanted to do with a HashTable :

    // HashTable to store download id's and loaders
    Hashtable<Long, SyncedProgressBar> storeTable = new Hashtable<Long, SyncedProgressBar>();
    

    In my onClickListener method, after loader[z] and lastDownload[ld] take their value, I put them in the HashTable : ( the downloa id will be the key, the loader will be the value )

    // Storing download id and loader in HashTable
    storeTable.put(lastDownload[ld], loader[z]);
    

    In my Broadcast Receiver's onReceive method, instead of doing this :

    if(lastDownload[y] == referenceId)
    

    I look if the HashTable contains the download id of the intent :

    if(storeTable.containsKey(referenceId))
    

    And I put the correct value in the loader :

    loader[y] = storeTable.get(referenceId);
    

    Then I just have to put the loader's visibility to GONE where I want. This solution works for me, but I will update it if I find something new.

    Here is my new code :

    In the onClickListener method : ( not complete here )

    // Loader of the clicked item is made visible
    loader[z].setVisibility(View.VISIBLE);
    
    // Construction of the URL
    SharedPreferences codeSaveUrl = getSharedPreferences(PREFS_TEXT,Context.MODE_PRIVATE);
    url2 = codeSaveUrl.getString("defaut", ""); // Organization code
    uri = url10 + url2 + "&file=" + udl ;
    
    // URL parse to URI
    Uri myuri = Uri.parse(uri);
    
    // Enqueue file to downloads, with notification. Storage of download id in a table
    lastDownload[ld] = mgr.enqueue(new DownloadManager.Request(myuri)
    .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
    .setAllowedOverRoaming(false)
    .setTitle(udl + ".pdf")
    .setDescription("Téléchargement en cours")
    .setDestinationInExternalPublicDir("/Protocols/", (udl+".pdf"))
    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE));
    
    // Storing download id and loader in HashTable
    storeTable.put(lastDownload[ld], loader[z]);
    
    // Increment variables for next downloads
    ld=ld+1;
    z=z+1;
    

    Broadcast Receiver :

    // Broadcast Receiver called when a download is finished
    BroadcastReceiver onComplete = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            // referenceId is the download's id for which the method is called
            long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            // If y (=0 at the beginning) is inferior to the number of downloads
            if(y <ld){
                // If the HashTable contains the Key-download-id for which the method is called
                if(storeTable.containsKey(referenceId)){
                    // Loader takes the value for the key
                    loader[y] = storeTable.get(referenceId);
                    // We define a cursor depending on the id
                    Cursor c = mgr.query(new DownloadManager.Query().setFilterById(referenceId));
                    if(c.moveToFirst()){
                        // Download status recovery
                        int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                        switch(x){
                        // If download is paused, pending or running, we do nothing
                        case DownloadManager.STATUS_PAUSED:
                        case DownloadManager.STATUS_PENDING:
                        case DownloadManager.STATUS_RUNNING:
                            break;
                        // If file has successfully been downloaded, loader is hidden
                        case DownloadManager.STATUS_SUCCESSFUL:
                            loader[y].setVisibility(View.GONE); 
                            // Increment y to go to next download
                            y=y+1;
                            break;
                        // If download failed, it is retried
                        case DownloadManager.STATUS_FAILED:
                            //TODO: retry download
                            break;
                        }
                    }
                }
            }
        }
    };
    
    0 讨论(0)
  • 2020-12-30 14:14

    Please note that DownloadManager.enqueue is asynchronous, it means mgr.enqeue returns almost immediately and after that your current code sets spinner back to invisible.

    To hide spinner you have to register a broadcast receiver to receive notification when download completes. You then have to find corresponding spinner and hide it. Please note that download can fail (and notification is still sent in this case).

    CommonsWare has posted an example showing how to work with DownloadManager.

    0 讨论(0)
提交回复
热议问题