6

I'm using the following script based on the tutorial Android Series: Download files with Progress Dialog to download multiple video files from the internet to the SD card. It displays a progress bar while the download is in progress.

public class MyDownload extends Activity {

public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private Button startBtn;
private ProgressDialog mProgressDialog;

private String videoPath = "http://my_site.com/test_videos/";    
private String[] fileNames = {"file1.mp4","file2.mp4"};
private TextView tv;    


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    startBtn = (Button)findViewById(R.id.startBtn);
    startBtn.setOnClickListener(new OnClickListener(){
        public void onClick(View v) {
            startDownload();
        }
    });
}

private void startDownload() {      

    tv = (TextView) findViewById(R.id.TextView01);       

    if(checkExternalMedia()==true) {

           File file = null;                
           for(int i=0; i<fileNames.length; i++) {
                file = new File("/sdcard/videos/"+fileNames[i]);
                boolean exists = file.exists();
                if(exists){
                    tv.append("\n\n"+fileNames[i]+" already exists");
                    continue;
                }
                else {
                    new DownloadFileAsync().execute(videoPath+fileNames[i],fileNames[i]);               
                }
                file = null;
            }               
        }            
    else {          
        tv.append("\n\nExternal Media is NOT readable/writable");
    }
}

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
        case DIALOG_DOWNLOAD_PROGRESS:
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("Downloading files...");
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setCancelable(false);
            mProgressDialog.show();
            return mProgressDialog;
        default:
            return null;
    }
}

/** Method to check whether external media available and writable. */

private boolean checkExternalMedia(){
    boolean mExternalStorageAvailable = false;
    boolean mExternalStorageWriteable = false;
    boolean stat;
    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals(state)) {
        // Can read and write the media
        mExternalStorageAvailable = mExternalStorageWriteable = true;
        stat = true;
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        // Can only read the media
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
        stat = false;
    } else {
        // Can't read or write
        mExternalStorageAvailable = mExternalStorageWriteable = false;
        stat = false;
    }          
    tv.append("\n\nExternal Media: readable="+mExternalStorageAvailable+" writable="+mExternalStorageWriteable);

    return stat;
}

class DownloadFileAsync extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showDialog(DIALOG_DOWNLOAD_PROGRESS);
    }

    @Override
    protected String doInBackground(String... aurl) {
        int count;

        try {
            URL url = new URL(aurl[0]);
            URLConnection conexion = url.openConnection();
            conexion.connect();

            File root = android.os.Environment.getExternalStorageDirectory();

            int lenghtOfFile = conexion.getContentLength();
            Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);

            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream(root.getAbsolutePath() + "/videos/" + aurl[1]);

            byte data[] = new byte[10485760];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress(""+(int)((total*100)/lenghtOfFile));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();          

        } catch (Exception e) {}
        return null;

    }
    protected void onProgressUpdate(String... progress) {
         Log.d("ANDRO_ASYNC",progress[0]);
         mProgressDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected void onPostExecute(String unused) {
        dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
        tv.append("\n\nFile Download Completed!");
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));            
    }
}

}

This code works fine when the size of each video is less (around 300KB). But when the video size increases to 7-8 MB the application crashes.

However, if I try to download a single large file instead of

private String[] fileNames = {"file1.mp4","file2.mp4"};

this code works fine. Any thoughts ?

2
  • What is the exception? Apps have limited memory in the jvm. Commented Feb 22, 2011 at 14:26
  • @Robby Pond ERROR/dalvikvm-heap(4539): Out of memory on a 10485776-byte allocation. 02-23 11:52:54.713: ERROR/AndroidRuntime(4539): Uncaught handler: thread AsyncTask #2 exiting due to uncaught exception 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): java.lang.RuntimeException: An error occured while executing doInBackground() 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): at android.os.AsyncTask$3.done(AsyncTask.java:200) 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) Commented Feb 23, 2011 at 10:14

3 Answers 3

4

You are reserving a buffer of 10 MB per file

byte data[] = new byte[10485760];

As memory is constrained on Android devices (think of 24 - 48MB per process), you will run in out of memory situations.

I doubt that you need a this big buffer - try lowering that to 1MB or even less and retry.

Sign up to request clarification or add additional context in comments.

9 Comments

@Heiko Rupp Do you think there is any problem with my for loop inside the startDownload() method? If I place a single filename inside the array String[] fileNames, which is quite large say 10MB then this code works fine. Instead if I place two files of 4MB size, then it fails. In the documentation for AsyncTask it says "The task can be executed only once (an exception will be thrown if a second execution is attempted.)" Is this bcoz of that? - Thanks
"The task can be executed only once (an exception will be thrown if a second execution is attempted.)" means, that you cannot use the same AsyncTask object to run a task again. Once an AsyncTask has finished you have to create an new AsyncTask object and execute that one.
You are doing new DownloadFileAsync().execute(.. which creates a new task for each file.
@Heiko Rupp Tried lowering the buffer size to 1MB (1048576) & 100KB (102400), but still having the same issue.
I got this error info: 02-23 11:52:54.633: ERROR/dalvikvm-heap(4539): Out of memory on a 10485776-byte allocation. 02-23 11:52:54.713: ERROR/AndroidRuntime(4539): Uncaught handler: thread AsyncTask #2 exiting due to uncaught exception 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): java.lang.RuntimeException: An error occured while executing doInBackground() 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): at android.os.AsyncTask$3.done(AsyncTask.java:200) 02-23 11:52:54.723: ERROR/AndroidRuntime(4539): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
|
0

Is there any specific reason as to why you are not using the DownloadManager Class provided by the SDK for GingerBread+ target devices?

Comments

0

I think you should declare the following:

byte data[] = new byte[lengthOfFile];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.