Android ProgressBar in ListView when using DownloadManager

I have a ListView in which each item represents a PDF file. When the user clicks on an item, the application must upload the file to external storage. Now loading does not work properly, but that is not a question. I want the ProgressBar style, the spinning wheel style, to appear next to each list item while the file is loading.

My problem: I cannot find how to make the spinning wheel appear. Before Download Manager, I tried it with AsyncTask, and the spinning wheel worked.

Here is my code:

CategoryActivity.java (ListView activity)

@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // Récupère les valeurs depuis ListItem udl = ((TextView) view.findViewById(R.id.udl)).getText().toString(); // This is the spinning wheel loader = ((ProgressBar) view.findViewById(R.id.spinWheel2)); filepath = dirpath + udl + ".pdf"; File file = new File(filepath); if (file.exists()) { // If the file exists, I open it }else{ // Else I download it // Setting the spinning wheel to VISIBLE loader.setVisibility(View.VISIBLE); SharedPreferences codeSaveUrl = getSharedPreferences(PREFS_TEXT,Context.MODE_PRIVATE); url2 = codeSaveUrl.getString("defaut", ""); // Code Organisation // Constructing the uriString uri = url10 + url2 + "&file=" + udl ; Uri myuri = Uri.parse(uri); DownloadManager mgr=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE); 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)); // Hiding the spinning wheel loader.setVisibility(View.GONE); } } 

Please note: if I do not close the spinning wheel, it will always be visible after clicking on an element. With a line to hide her, she does not even appear.


EDIT:
I added BroadcastReceiver.

Put these two lines in onCreate ():

 final DownloadManager mgr=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE); registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 

And added:

 BroadcastReceiver onComplete = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { loader.setVisibility(View.GONE); } }; @Override public void onDestroy(){ super.onDestroy(); unregisterReceiver(onComplete); } 

EDIT 2: So, here are some changes I made:

I save the boot id in a variable:

 lastDownload = 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_NOTIFY_COMPLETED)); 

Depending on the state of the download, I want to do different things:

 BroadcastReceiver onComplete = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload)); if(c.moveToFirst()){ int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); switch(x){ case DownloadManager.STATUS_PAUSED: case DownloadManager.STATUS_PENDING: case DownloadManager.STATUS_RUNNING: break; case DownloadManager.STATUS_SUCCESSFUL: loader.setVisibility(View.GONE); break; case DownloadManager.STATUS_FAILED: //TODO: retry download break; } } } }; 

The problem is that the spinning wheel is hidden only for the last item clicked in the View list. I tried in debug mode, but the program has the correct behavior ( loader.setVisibility(View.GONE) is called for each download). I do not know why the spinning wheel will not hide, with the exception of the last clicked item.


EDIT: 3 I know why the spinning wheel does not hide, except for the last clicked item.

When I click on a few items, lastDownload accepts the id of the last click. Thus, in the broadcast receiver, in the case of the last element, the number of clicks is clicked. I tried changing lastDownload to an array / table longs and comparing it with referenceId, which I believe is the identifier contained in the intent.
Here is the new code (y = 0 and ld is the number of elements pressed):

 BroadcastReceiver onComplete = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if(y <ld){ if(lastDownload[y] == referenceId){ Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload[y])); if(c.moveToFirst()){ int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); switch(x){ case DownloadManager.STATUS_PAUSED: case DownloadManager.STATUS_PENDING: case DownloadManager.STATUS_RUNNING: break; case DownloadManager.STATUS_SUCCESSFUL: loader.setVisibility(View.GONE); // This loader is the one of the last item clicked break; case DownloadManager.STATUS_FAILED: //TODO: retry download break; } } y=y+1; } } } }; 

I did not write the part where I returned the variables to 0, but at the moment the code is working as expected. The only problem is that the spinning wheel that I am doing disappears, it is the spinning wheel of the last clicked item. And I know why. Because this line: loader = ((ProgressBar) view.findViewById(R.id.spinWheel2)); is in the onItemClicked method. I don’t think I can put it in another place, because the performance in which it is located is not a form of activity.

In short: I have to find a way to access the execution line of the item / view that I clicked on, knowing that I can click on multiple items before the first reaches the broadcast receiver.


EDIT: 4 Ok, so I did this:

y , z and ld are set to 0 at the beginning.

When you click an item:

 // 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)); // 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 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 id of the download corresponds to the one for which the method is called if(lastDownload[y] == referenceId){ // We define a cursor depending on the id Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload[y])); 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; } } } } } }; 

It works fine, except when a small file item is clicked while loading a large file. The small file takes precedence, and the download manager no longer performs the order of the tables, as a result of which the boot wheel does not disappear.


EDIT: 5

I found a way to do what I wanted, to see my answer.

Thank you for your help.

+6
source share
3 answers

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

 // HashTable to store download id 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 a HashTable: (the downloa key 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 onReceive method for Broadcast receiver, instead:

 if(lastDownload[y] == referenceId) 

I am looking to see if the HashTable contains the intent load identifier:

 if(storeTable.containsKey(referenceId)) 

And I set the correct value in the bootloader:

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

Then I just need to set the bootloader 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 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; } } } } } }; 
+2
source

Note that DownloadManager.enqueue is asynchronous, which means that mgr.enqeue returns almost immediately, and after that your current code returns the spinner back to invisible.

To hide the counter, you need to register a broadcast receiver to receive a notification when the download is complete. Then you need to find the appropriate counter and hide it. Please note that the download may fail (and the notification is still sent in this case).

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

+1
source

I would use AsyncTask for this and make the wheel appear / disappear in onPreCreate and 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 run the task using the new MyDownloader (). execute ("linktopdf"); or something like this (what you have enclosed .execute will be passed to the doInBackground method)

0
source

Source: https://habr.com/ru/post/974214/


All Articles