Reputation: 744
I have multiple asynctask's running in a for loop inside my splash screen. I want the app to stop execution until all the asynctasks are complete.And I would like to update the UI thread with the total number of async task and task's completed.Like if there are 3 tasks and 1 is complete I would like to display 1/3 complete. This is code for the loop:-
String[] images = Parse_imgJSON.image;
for (int i = 0; i < images.length; i++) {
Log.d("Image ", images[i]);
download_img(images[i]);
}
Code for download_img():-
public void download_img(String img_url) {
String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
File file = new File("/storage/emulated/0/rready_images/" + fileName);
if (file.exists() && !file.isDirectory()) {
Log.d("Image exists", fileName);
} else {
if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
new DownloadImagesAsync().execute(img_url);
} else {
Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);
}
}
}
The actual Async Task code for downloading file:-
class DownloadImagesAsync extends AsyncTask<String, String, String> {
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
private String resp;
int lengthOfFile;
@Override
protected String doInBackground(String... params) {
int count;
try {
URL url = new URL(params[0]);
URLConnection connection = url.openConnection();
connection.connect();
lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);
String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
Log.d("FILENAME", fileName);
resp = fileName;
if (isSDPresent) {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} else {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
@Override
protected void onPostExecute(String filename) {
Log.d("PARAM", filename + " Downloaded ");
String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());
Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));
if (isSDPresent) {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
// Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
// dbHandler.updateDownloadStatus(image_id, "YES");
}
} else {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
// dbHandler.updateDownloadStatus(image_id, "YES");
}
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(String... values) {
Log.d("ANDRO_ASYNC", values[0]);
}
}
Any help or suggestion is appreciated. Thank you.
Upvotes: 1
Views: 844
Reputation: 844
I am using ProgressBar
to display the update as an example. You can of course choose whatever view you like. In download_img()
i am incrementing the value so that it shows 1/3 instead of 0/3.
Also, i am assuming that all these methods and the AsyncTask are in a Single java file.
ProgressBar mProgress = (ProgressBar) findViewById(R.id.progress_bar); <------------Here
probressbar.setMax(images.length) <---------------Here
for (int i = 0; i < images.length; i++) {
Log.d("Image ", images[i]);
download_img(images[i], i);
}
download_img()
public void download_img(String img_url, int i) { <---------------Here
String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
File file = new File("/storage/emulated/0/rready_images/" + fileName);
if (file.exists() && !file.isDirectory()) {
Log.d("Image exists", fileName);
} else {
if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
new DownloadImagesAsync().execute(img_url, ++i); <------------------Here
} else {
Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);
}
}
}
AsyncTask
class DownloadImagesAsync extends AsyncTask<String, String, String> {
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
private String resp;
int lengthOfFile, progressStatus; <------------Here
@Override
protected String doInBackground(String... params) {
int count;
try {
progressStatus=Integer.parseInt(params[1]); <-----------Here
URL url = new URL(params[0]);
URLConnection connection = url.openConnection();
connection.connect();
lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);
String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
Log.d("FILENAME", fileName);
resp = fileName;
if (isSDPresent) {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} else {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
@Override
protected void onPostExecute(String filename) {
Log.d("PARAM", filename + " Downloaded ");
mProgress.setProgress(mProgressStatus); <----------------Here
String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());
Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));
if (isSDPresent) {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
// Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
// dbHandler.updateDownloadStatus(image_id, "YES");
}
} else {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
//dbHandler.updateDownloadStatus(image_id, "YES");
}
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(String... values) {
Log.d("ANDRO_ASYNC", values[0]);
}
}
Upvotes: 1
Reputation: 27211
There are a lot of methods.
For example, you can use interface callbacks.
Create an interface:
public interface MyCallback {
public void readycallback(int index_thread);
}
change the class:
class DownloadImagesAsync extends AsyncTask<String, String, String> {
private int id = 0;
private MyCallback callback;
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
private String resp;
int lengthOfFile;
public DownloadImagesAsync(int id, MyCallback callback) {
this.id = id;
this.callback = callback;
}
@Override
protected String doInBackground(String... params) {
int count;
try {
URL url = new URL(params[0]);
URLConnection connection = url.openConnection();
connection.connect();
lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);
String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
Log.d("FILENAME", fileName);
resp = fileName;
if (isSDPresent) {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} else {
InputStream inputStream = new BufferedInputStream(url.openStream());
OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
@Override
protected void onPostExecute(String filename) {
Log.d("PARAM", filename + " Downloaded ");
if (callback != null) {
callback.readycallback(myid);
}
String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());
Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));
if (isSDPresent) {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
// Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
// dbHandler.updateDownloadStatus(image_id, "YES");
}
} else {
File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
if (f.length() < lengthOfFile) {
if (f.delete()) {
Log.d("Del", "File deleted");
} else {
Log.d("NOTDel", "File not deleted");
}
} else {
// dbHandler.updateDownloadStatus(image_id, "YES");
}
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(String... values) {
Log.d("ANDRO_ASYNC", values[0]);
}
}
to use this class change main function
String[] images = Parse_imgJSON.image;
for (int i = 0; i < images.length; i++) {
Log.d("Image ", images[i]);
download_img(images[i], i);
}
public void download_img(String img_url, int i) {
String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
File file = new File("/storage/emulated/0/rready_images/" + fileName);
if (file.exists() && !file.isDirectory()) {
Log.d("Image exists", fileName);
} else {
if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
new DownloadImagesAsync(i, new MyCallback() {
@Override
public void readycallback(int index_thread) {
//this is your ready callback
}
}).execute(img_url);
} else {
Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);
}
}
}
Do not forget to check whether you using main UI thread:
if you need you may wrap updates by this function:
@Override
public void readycallback(int index_thread) {
//this is your ready callback
runOnUiThread(new Runnable() {
@Override
public void run() {
//this is your ready callback in main UI
//I do not remember if onPostExecute is in main UI thread
}
});
}
Upvotes: 1
Reputation: 217
The whole point of using async task is to not block the main thread. Trying to block all the operations until the files are downloaded in async task might not be the way to go and is definitely not recommended. Instead i would suggest you download the required files and store them using a background service that runs the first time the user is installing the app, so that you simply have to read on startup. And if you do manage to stop all work before download completes you will get an ANR message.
So what can you do in this situation, use a fragment and AsyncTaskLoader or a background service that broadcasts an intent after completion of download, in place of Async Task as Async task is only recommended for short operations. Listen for this broadcast by registering a receiver and update your UI accordingly after receiving the result from loader or service.
Upvotes: 3