title: Solution for downloading hundreds of files asynchronously
body: <p>I have an app in which the user may need to download up to 760 files, totaling around 350MB. It is <em>not</em> possible to zip these files, they must be downloaded as loose files!</p>
  
  <p>I'm currently using <a href="http://loopj.com/android-async-http/" rel="nofollow">Android Asynchronous Http Client</a> to download individual files, and <code>AsyncTask</code> to run the entire process.</p>
  
  <p>Here's an example of a <code>DownloadThread</code> object which handles downloading hundreds of files in the background:</p>
  
  <pre><code>public class DownloadThread extends AsyncTask&lt;String,String,String&gt; {
  
  ArrayList&lt;String&gt; list;
  AsyncHttpClient client;
  String[] allowedContentTypes = new String[] { "audio/mpeg" };
  BufferedOutputStream bos;
  FileOutputStream fos;
  
  @Override
  protected String doInBackground(String... params) {
      DownloadTask task;
      for (String file : list) {
          //the "list" variable has already been populated with hundreds of strings
          task = new DownloadTask(file);
          task.execute("");
          while (!task.isdone)
              try {
                  Thread.sleep(10);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
      }
  
      return null;
  }
  
  
  class DownloadTask extends AsyncTask&lt;String, String, String&gt; {
  
      String character, filename;
      boolean isdone = false;
  
      public DownloadTask(String file) {
          //file = something like "Whale/sadwhale.mp3"
          character = file.split("/")[0];
          filename = file.split("/")[1];
      }
  
      @Override
      protected void onPreExecute() {
      }
  
      @Override
      protected void onPostExecute(String result) {
          if (!result.equals("Error")) {
                          //Do something on success
          }
          isdone = true;
      }
  
      @Override
      protected String doInBackground(String... str) {
          client = new AsyncHttpClient();
          client.get("http://some-site.com/sounds/" + character + "/"
                  + filename, new BinaryHttpResponseHandler(
                  allowedContentTypes) {
              @Override
              public void onSuccess(byte[] fileData) {
                  try {
                      // Make file/folder and create stream
                      File folder = new File(Environment
                              .getExternalStorageDirectory()
                              + CharSelect.directory + character);
                      folder.mkdirs();
                      File dest = new File(folder, filename);
                      fos = new FileOutputStream(dest);
                      bos = new BufferedOutputStream(fos);
                      // Transfer data to file
                      bos.write(fileData);
                      bos.flush();
                      bos.close();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          });
          return "Success";
      }
  
  }
  </code></pre>
  
  <p>}</p>
  
  <p><code>DownloadThread</code> runs in the background, and also calls hundreds of it's own <code>AsyncTasks</code>. It waits until the task is done downloading, then continues the <code>for</code> loop for each download.</p>
  
  <p>This works, kinda. Some downloads appear to not finish properly or not start at all. Out of a list of 760 downloads, an average of 100 downloads complete properly, and I have to restart the process to download another additional 100 downloads until that one fails as well. I have a feeling this is due to timing issues, as the <code>Thread.sleep(10)</code> line seems a little "hackish".</p>
  
  <p>Surely, calling hundreds of <code>AsyncTasks</code> from another <code>AsyncTask</code> is not the most efficient way to do this. How can I alter this code or implement a 3rd party solution to fit this task?</p>