Android ProgressBar в ListView при использовании DownloadManager
У меня есть ListView, в котором каждый элемент представляет файл PDF. Когда пользователь нажимает на элемент, приложение должно загрузить файл на внешнее хранилище. Теперь загрузка не работает должным образом, но это не вопрос. Я хочу, чтобы ProgressBar, стиль вращающегося колеса, появлялся рядом с каждым элементом списка во время загрузки файла.
Моя проблема: я не могу найти способ заставить вращающееся колесо появиться. До Менеджера загрузок я пробовал это с AsyncTask, и вращающееся колесо работало.
Вот мой код:
CategoryActivity.java (активность ListView)
@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);
}
}
Обратите внимание, что если я не заставлю вращающееся колесо исчезнуть, оно всегда будет видно после нажатия на элемент. С линией, чтобы скрыть это, он даже не появляется.
РЕДАКТИРОВАТЬ :
Я добавил BroadcastReceiver.
Поместите эти две строки в onCreate ():
final DownloadManager mgr=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
И добавил это:
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
loader.setVisibility(View.GONE);
}
};
@Override
public void onDestroy(){
super.onDestroy();
unregisterReceiver(onComplete);
}
РЕДАКТИРОВАТЬ 2: Итак, вот некоторые изменения, которые я сделал:
Я сохраняю идентификатор загрузки в переменной:
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));
В зависимости от статуса загрузки я хочу делать разные вещи:
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;
}
}
}
};
Проблема в том, что прялка прячется только за последний элемент, нажатый в listView. Я пытался с режимом отладки, но программа имеет правильное поведение (имеется в видуloader.setVisibility(View.GONE)
вызывается для каждой загрузки). Я не знаю, почему вращающееся колесо не спрячется, за исключением последнего нажатого элемента.
РЕДАКТИРОВАТЬ: 3 Я знаю, почему вращающееся колесо не скрывается, за исключением последнего нажатого элемента.
Когда я нажимаю на несколько элементов, lastDownload получает идентификатор последнего из нажатых. Таким образом, в широковещательном приемнике это происходит в случае последнего нажатого элемента, умноженного на количество нажатых элементов.
Я попытался изменить lastDownload в массив / таблицу long и сравнить его с referenceId, который, как я считаю, является идентификатором, содержащимся в намерении.
Вот новый код (y = 0, а ld - количество нажатых элементов):
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;
}
}
}
};
Я не писал ту часть, где я помещал переменные обратно в 0, но сейчас код работает почти так, как ожидалось. Единственная проблема остается в том, что вращающееся колесо, которое я делаю, исчезает, это вращающееся колесо последнего нажатого элемента. И я знаю почему. Потому что эта строка:loader = ((ProgressBar) view.findViewById(R.id.spinWheel2));
находится вonItemClicked
метод. Я не думаю, что могу поместить это куда-либо еще, потому что точка зрения, в которой он находится, не является точкой зрения на действие.
Короче говоря: я должен найти способ получить доступ к индикатору выполнения элемента / представления, на который я нажал, зная, что я могу щелкнуть несколько элементов, прежде чем первый из них достигнет Broadcast Receiver.
РЕДАКТИРОВАТЬ: 4 Итак, я сделал это:
y
,z
, а такжеld
установлены в0
в начале.
Когда на элемент нажимают:
// 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 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 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;
}
}
}
}
}
};
Работает нормально, за исключением случаев, когда элемент небольшого файла нажимается во время загрузки большого файла. Небольшой файл имеет приоритет, а менеджер загрузок больше не следует порядку таблиц, в результате чего колесо загрузки не исчезает.
РЕДАКТИРОВАТЬ: 5
Я нашел способ сделать то, что хотел, см. Мой ответ.
Спасибо за вашу помощь.