package com.rnfs;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import android.os.AsyncTask;

public class Downloader extends AsyncTask<DownloadParams, int[], DownloadResult> {
  private DownloadParams mParam;
  private AtomicBoolean mAbort = new AtomicBoolean(false);

  protected DownloadResult doInBackground(DownloadParams... params) {
    mParam = params[0];

    DownloadResult res = new DownloadResult();

    try {
      this.download(mParam, res);
      mParam.onTaskCompleted.onTaskCompleted(res);
    } catch (Exception ex) {
      res.exception = ex;
      mParam.onTaskCompleted.onTaskCompleted(res);
      return res;
    }

    return res;
  }

  private void download(DownloadParams param, DownloadResult res) throws IOException {
    InputStream input = null;
    OutputStream output = null;
    HttpURLConnection connection = null;

    try {
      connection = (HttpURLConnection)param.src.openConnection();

      connection.setConnectTimeout(5000);
      connection.connect();

      int statusCode = connection.getResponseCode();
      int lengthOfFile = connection.getContentLength();

      Map<String, List<String>> headers = connection.getHeaderFields();

      Map<String, String> headersFlat = new HashMap<String, String>();

      for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
        String headerKey = entry.getKey();
        String valueKey = entry.getValue().get(0);
        
        if (headerKey != null && valueKey != null) {
          headersFlat.put(headerKey, valueKey);
        }
      }

      mParam.onDownloadBegin.onDownloadBegin(statusCode, lengthOfFile, headersFlat);

      input = new BufferedInputStream(connection.getInputStream(), 8 * 1024);
      output = new FileOutputStream(param.dest);

      byte data[] = new byte[8 * 1024];
      int total = 0;
      int count;

      while ((count = input.read(data)) != -1) {
        if (mAbort.get()) {
          break;
        }

        total += count;
        publishProgress(new int[] { lengthOfFile, total });
        output.write(data, 0, count);
      }

      output.flush();

      res.statusCode = statusCode;
      res.bytesWritten = total;
    } finally {
      if (output != null) output.close();
      if (input != null) input.close();
      if (connection != null) connection.disconnect();
    }
  }

  protected void stop() {
    mAbort.set(true);
  }

  @Override
  protected void onProgressUpdate(int[]... values) {
    super.onProgressUpdate(values);
    mParam.onDownloadProgress.onDownloadProgress(values[0][0], values[0][1]);
  }

  protected void onPostExecute(Exception ex) {

  }
}

@@ -1418,24 +1418,614 @@
 tLength();%0A%0A
+      boolean isRedirect = (%0A        statusCode != HttpURLConnection.HTTP_OK &&%0A        (%0A          statusCode == HttpURLConnection.HTTP_MOVED_PERM %7C%7C%0A          statusCode == HttpURLConnection.HTTP_MOVED_TEMP%0A        )%0A      );%0A%0A      if (isRedirect) %7B%0A        String redirectURL = connection.getHeaderField(%22Location%22);%0A        connection = (HttpURLConnection) new URL(redirectURL).openConnection();%0A        connection.setConnectTimeout(5000);%0A        connection.connect();%0A%0A        statusCode = connection.getResponseCode();%0A        lengthOfFile = connection.getContentLength();%0A      %7D%0A%0A
       Map%3CSt

Add support for following 301/302 redirects on android