The aim of the application is to offer a simple way to download and extract a bunch of archives (~200mo), to delete it, and to open it. The download display a notification which display the progress.
I'm using a ListView to display every archive that can be downloaded. Each array contain an image, some text, and two buttons (for reading/deleting, downloading, or cancel). The data are retrieved from a json.
I've got some issues while I try to cancel the AsyncTask which display the notification and download the file. When I call the async.cancel(true);, the notification and the download are still running.
Maybe am I calling the asyncTask from the wrong place, but I don't know how to fix this.
My adapter :
public class ListArrayAdapter extends ArrayAdapter<String> {
private final Context context;
public Drawable d;
private ArrayList<HashMap<String, String>> list;
public boolean finishDownload = false;
JSONArray jsonArray;
// Constructor
public ListArrayAdapter(Context context, List<String> values,
ArrayList<HashMap<String, String>> list) {
super(context, R.layout.activity_list_array_adapter, values);
this.context = context;
this.list = list;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_list_array_adapter,
parent, false);
// Déclaration
TextView date = (TextView) rowView.findViewById(R.id.date);
TextView title = (TextView) rowView.findViewById(R.id.title);
TextView description = (TextView) rowView.findViewById(R.id.description);
ImageView imageView = (ImageView) rowView.findViewById(R.id.cover);
ProgressBar pd = (ProgressBar) rowView.findViewById(R.id.progress);
final Button button1 = (Button) rowView.findViewById(R.id.button1);
final Button button2 = (Button) rowView.findViewById(R.id.button2);
// Fill the array with the json file
title.setText(list.get(position).get("Title"));
date.setText(list.get(position).get("Date"));
description.setText(list.get(position).get("Description"));
new ParseImage(position, imageView, pd).execute();
final File file = new File(Environment.getExternalStorageDirectory()
.getPath() + "/Magazine/" + list.get(position).get("Name") + ".zip");
//If the file exist, let the user open it
if (file.exists()) {
button1.setText("Lire");
button2.setVisibility(View.VISIBLE);
button2.setText("Supprimer");
}
// else, let the user download it
else {
button1.setText("Télécharger");
button2.setVisibility(View.GONE);
}
final DownloadTask async = new DownloadTask(context, position, list);
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
if (button1.getText() == "Télécharger") {
button1.setEnabled(false);
button2.setVisibility(View.VISIBLE);
button2.setText("Annuler");
finishDownload = false;
async.execute(0);
} else if (button1.getText() == "Lire") {
Intent i1 = new Intent(context, WebActivity.class);
context.startActivity(i1);
}
}
});
button2.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
if (button2.getText() == "Annuler") {
async.cancel(true);
button1.setEnabled(true);
button2.setVisibility(View.GONE);
button1.setText("Télécharger");
} else if (button2.getText() == "Supprimer") {
button1.setEnabled(true);
button2.setVisibility(View.GONE);
button1.setText("Télécharger");
if (file.exists()) {
file.delete();
}
}
}
});
return rowView;
}
public class DownloadTask extends AsyncTask<Integer, Integer, Void> {
private NotificationHelper mNotificationHelper;
public int position;
public ArrayList<HashMap<String, String>> list;
public DownloadTask(Context context, int position,
ArrayList<HashMap<String, String>> list) {
mNotificationHelper = new NotificationHelper(context);
this.position = position;
this.list = list;
}
@Override
protected void onPreExecute() {
mNotificationHelper.createNotification();
}
@Override
protected Void doInBackground(Integer... integers) {
int count = 0;
try {
Thread.sleep(1);
URL url = new URL(list.get(position).get("Content"));
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream(),
8192);
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().getPath()
+ "/Magazine/"
+ list.get(position).get("Name")
+ ".zip");
byte data[] = new byte[1024];
long total = 0;
int progress_temp = 0;
while ((count=input.read(data)) != -1)
{
total += count;
progress_temp = (int) total*100/lenghtOfFile;
output.write(data, 0, count);
}
publishProgress(progress_temp);
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
mNotificationHelper.progressUpdate(progress[0]);
}
@Override
protected void onCancelled() {
mNotificationHelper.completed();
super.onCancelled();
}
@Override
protected void onPostExecute(Void result) {
mNotificationHelper.completed();
finishDownload = true;
}
}
}
The notificationHelper class which manage the notification :
public class NotificationHelper {
private Context mContext;
private int NOTIFICATION_ID = 1;
private Notification mNotification;
private NotificationManager mNotificationManager;
private PendingIntent mContentIntent;
private CharSequence mContentTitle;
public NotificationHelper(Context context) {
mContext = context;
}
@SuppressWarnings("deprecation")
public void createNotification() {
mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
int icon = android.R.drawable.stat_sys_download;
CharSequence tickerText = mContext.getString(R.string.download_ticker);
long when = System.currentTimeMillis();
mNotification = new Notification(icon, tickerText, when);
mContentTitle = mContext.getString(R.string.content_title);
CharSequence contentText = "0% téléchargé";
Intent notificationIntent = new Intent(mContext, MainActivity.class);
mContentIntent = PendingIntent.getActivity(mContext, 0,
notificationIntent, 0);
mNotification.setLatestEventInfo(mContext, mContentTitle, contentText,
mContentIntent);
mNotification.flags = Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
}
@SuppressWarnings("deprecation")
public void progressUpdate(int percentageComplete) {
CharSequence contentText = percentageComplete + "% téléchargé";
mNotification.setLatestEventInfo(mContext, mContentTitle, contentText,
mContentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
}
public void completed() {
mNotificationManager.cancel(NOTIFICATION_ID);
}
}
The
cancel()
method onAsyncTasks
(confusingly) doesn't actually stop the Thread from running, but rather sets a flag on the Task. You can find some discussion about that here. It seems that currently, if you want your Thread to actually stop mid-execution, you'll need to manually check that flag in your looping code using theisCancelled()
method. For example, in your while loop in doInBackground:You can find another example of this in the AsyncTask docs under the "Usage" header. Hope this helps!