在android大文件中下载

时间:2011-03-06 08:01:47

标签: android multithreading download

当我尝试使用此代码时,它会开始下载,但随后警告“强制关闭” 我该怎么办?使用某种后台线程?

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");
}

2 个答案:

答案 0 :(得分:10)

我上周正在处理类似的问题,并最终使用显示进度条的AsyncTask,因为可能需要一些时间来下载文件。一种方法是将下面的类嵌套在Activity中,只需将它调用到您需要的位置即可:

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

或者,如果课程不在活动中并且从活动中调用..

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

这会传递活动,因此我们可以访问方法getSystemService();

这是执行所有脏工作的实际代码。您可能需要根据需要对其进行修改。

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
    }
}

答案 1 :(得分:2)

您应该尝试使用AsyncTask。你正在获得强制退出对话框,因为你试图在UI线程上做太多工作,并且Android判断你的应用程序没有响应。

this question的答案有一些很好的联系。

以下内容将是一个良好的开端:

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();
     }
 }

然后执行以下任务:

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