SERG
SERG

Reputation: 3971

Download in android large files

When I try this code, it starts download but then stuck with alert "force close" what should I do? Use some kind of background thread?

try {
    long startTime = System.currentTimeMillis();

    URL u = new URL("http://file.podfm.ru/3/33/332/3322/mp3/24785.mp3");
    HttpURLConnection c = (HttpURLConnection) u.openConnection();

    c.setRequestMethod("GET");
    c.setDoOutput(true);
    c.connect();
    FileOutputStream f = new FileOutputStream(new File("/sdcard/","logo.mp3"));

    InputStream in = c.getInputStream();

    byte[] buffer = new byte[1024];
    int len1 = 0;
    while ( (len1 = in.read(buffer)) != -1 ) {
        f.write(buffer,0, len1);
    }
    f.close();

    Log.d("ImageManager", "download ready in" +
        ((System.currentTimeMillis() - startTime) / 1000) + " sec");
}
catch (IOException e)
{
    Log.d("ImageManager", "Error" +
        ((System.currentTimeMillis()) / 1000) + e + " sec");
}

Upvotes: 2

Views: 6824

Answers (2)

David Kuridža
David Kuridža

Reputation: 7197

I was dealing with similar problem last week and ended up using AsyncTask with progress bar displayed since it could take some time for the file to be downloaded. One way of doing it is to have below class nested in your Activity and just call it where you need to simply like this:

new DownloadManager().execute("here be URL", "here be filename");

Or if the class is not located within an activity and calling from an activity..

new DownloadManager(this).execute("URL", "filename");

This passes the activity so we have access to method getSystemService();

Here is the actual code doing all the dirty work. You will probably have to modify it for your needs.

private class DownloadManager extends AsyncTask<String, Integer, Drawable>
{

    private Drawable d;
    private HttpURLConnection conn;
    private InputStream stream; //to read
    private ByteArrayOutputStream out; //to write
    private Context mCtx;

    private double fileSize;
    private double downloaded; // number of bytes downloaded
    private int status = DOWNLOADING; //status of current process

    private ProgressDialog progressDialog;

    private static final int MAX_BUFFER_SIZE = 1024; //1kb
    private static final int DOWNLOADING = 0;
    private static final int COMPLETE = 1;

    public DownloadManager(Context ctx)
    {
        d          = null;
        conn       = null;
        fileSize   = 0;
        downloaded = 0;
        status     = DOWNLOADING;
        mCtx       = ctx;
    }

    public boolean isOnline()
    {
        try
        {
            ConnectivityManager cm = (ConnectivityManager)mCtx.getSystemService(Context.CONNECTIVITY_SERVICE);
            return cm.getActiveNetworkInfo().isConnectedOrConnecting(); 
        }
        catch (Exception e)
        {
            return false;
        }
    }

    @Override
    protected Drawable doInBackground(String... url)
    {
        try
        {
            String filename = url[1];
            if (isOnline())
            {
                conn     = (HttpURLConnection) new URL(url[0]).openConnection();
                fileSize = conn.getContentLength();
                out      = new ByteArrayOutputStream((int)fileSize);
                conn.connect();

                stream = conn.getInputStream();
                // loop with step
                while (status == DOWNLOADING)
                {
                    byte buffer[];

                    if (fileSize - downloaded > MAX_BUFFER_SIZE)
                    {
                        buffer = new byte[MAX_BUFFER_SIZE];
                    }
                    else
                    {
                        buffer = new byte[(int) (fileSize - downloaded)];
                    }
                    int read = stream.read(buffer);

                    if (read == -1)
                    {
                        publishProgress(100);
                        break;
                    }
                    // writing to buffer
                    out.write(buffer, 0, read);
                    downloaded += read;
                    // update progress bar
                    publishProgress((int) ((downloaded / fileSize) * 100));
                } // end of while

                if (status == DOWNLOADING)
                {
                    status = COMPLETE;
                }
                try
                {
                    FileOutputStream fos = new FileOutputStream(filename);
                    fos.write(out.toByteArray());
                    fos.close();
                }
                catch ( IOException e )
                {
                    e.printStackTrace();
                    return null;
                }

                d = Drawable.createFromStream((InputStream) new ByteArrayInputStream(out.toByteArray()), "filename");
                return d;
            } // end of if isOnline
            else
            {
                return null;
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }// end of catch
    } // end of class DownloadManager()

    @Override
    protected void onProgressUpdate(Integer... changed)
    {
        progressDialog.setProgress(changed[0]);
    }

    @Override
    protected void onPreExecute()
    {
        progressDialog = new ProgressDialog(/*ShowContent.this*/); // your activity
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setMessage("Downloading ...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    protected void onPostExecute(Drawable result)
    {
        progressDialog.dismiss();
        // do something
    }
}

Upvotes: 10

Matthew
Matthew

Reputation: 44919

You should try using an AsyncTask. You are getting the force quit dialog because you are trying to do too much work on the UI thread and Android judges that your application has become unresponsive.

The answers to this question have some good links.

Something like the following would be a good start:

private class DownloadLargeFileTask extends AsyncTask<Void, Void, Void> {
     private final ProgressDialog dialog;

     public DownloadLargeFileTask(ProgressDialog dialog) {
          this.dialog = dialog;
     }

     protected void onPreExecute() {
         dialog.show();
     }

     protected void doInBackground(Void... unused) {
         downloadLargeFile();
     }

     protected void onPostExecute(Void unused) {
         dialog.dismiss();
     }
 }

and then execute the task with:

ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Loading. Please Wait...");
new DownloadLargeFileTask(dialog).execute();

Upvotes: 2

Related Questions