AndroidNewBee
AndroidNewBee

Reputation: 744

How to stop execution till all the async tasks finish execution in android?

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

Answers (3)

Darshan Miskin
Darshan Miskin

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

Vyacheslav
Vyacheslav

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

Chetna Priyadarshini
Chetna Priyadarshini

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

Related Questions