Problem with downloading multiple files using AsyncTask
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 = mExternalStorageWritea开发者_如何学Goble = 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 ?
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.
Is there any specific reason as to why you are not using the DownloadManager Class provided by the SDK for GingerBread+ target devices?
I think you should declare the following:
byte data[] = new byte[lengthOfFile];
精彩评论