监控BufferedInputStream下载进度

时间:2013-05-13 09:02:10

标签: java android android-asynctask progressdialog bufferedinputstream

我正在尝试使用Android上的AsyncTask下载文件。我想显示一个ProgressDialog,它应该有一个进度条来显示下载的状态。我正在使用onProgressUpdate()函数,并在我的publishProgress()函数中实现了对doInBackground()的调用。但是,进度对话框仅在下载文件后弹出。我的代码:

protected Long doInBackground(URL...urls) {
    for (int i = 0; i < urls.length; i++) {
        url = urls[i];
        try {
            URLConnection conn = url.openConnection();
            conn.connect();
            totalSize = conn.getContentLength();

            BufferedInputStream bis = new BufferedInputStream(url.openStream());
            FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/forvo_temp.mp3");
            BufferedOutputStream bos = new BufferedOutputStream(fos,1024);
            byte [] data = new byte[1024];

            int x=0; int c=0;
            while((x=bis.read(data,0,1024))>=0){
                bos.write(data,0,x);
                c += 1024;
                publishProgress(c);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    return 0L; // Don't know what to do with this
}

protected void onProgressUpdate(Integer...args) {
    pd = ProgressDialog.show(context, "Downloading...", "Downloading...", true, false);
    pd.setProgress(args[0] / totalSize);
}

我想在调用new BufferedInputStream(url.openStream())时会下载整个文件。如何监控下载进度?

2 个答案:

答案 0 :(得分:2)

使用您自己的InputStream包装URL输入流,该InputStream只读取字节并“监视”状态,例如发送通知。

很简单:InputStream是一个抽象类,只有一个抽象方法:

public abstract int read() throws IOException;

在你的情况下,它应该从它包装的流中读取字节。

public class NotifcationInputStream extends InputStream {
    private InputStream in;
    private int count;
    private Collection<ByteListener> listeners = new ArrayList<ByteListener>();

    NotificationInputStream(InputStream in) {
         this.in = in;
    }

    public int read() throws IOException {
        int b = in.read(); 
        byteReceived(b);
        return b;
    }

    public void addListener(ByteListener listener) {
        listeners.add(listener);
    }

    private void byteReceived(int b) {
        for (ByteListener l : listeners) {
             l.byteReceived(b, ++count);
        }
    }
}


public interface ByteListener extends EventListener {
    public void byteReceived(int b, int count);
}

这里的问题是如何显示进程条:你必须知道总字节数。如果您的资源是静态的,您可以从HTTP标头content-length获取它。否则,您需要适当的服务器支持或启发式方法。

答案 1 :(得分:0)

此代码非常有用,可显示下载项目的大小和下载大小。

private static final int DOWNLOAD_ONPROGRESS = 1;

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case DOWNLOAD_ONPROGRESS:
        progressDialog = new ProgressDialog(this);

        progressDialog.setMessage("Downloading latest ...");
        progressDialog.setCancelable(true);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        try {
            progressDialog.show();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return progressDialog;
    default:
        return null;
    }
}

您可以使用AsyncTask在后台下载该版本。

private class DownLoad extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        logger.info("LoadDataAsync onPreExecute");
        showDialog(DOWNLOAD_ONPROGRESS);
    }

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

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

            int contentlength = urlConnection.getContentLength();
            progressDialog.setMax(contentlength);
            String PATH = "";
            File file = null;
            if (android.os.Environment.getExternalStorageState().equals(
                    android.os.Environment.MEDIA_MOUNTED)) {
                PATH = Environment.getExternalStorageDirectory()
                        + "/download/";
                file = new File(PATH);

                file.mkdirs();

                File outputFile = new File(file, "telfaz.apk");
                OutputStream fos = new FileOutputStream(outputFile);

                InputStream is = new BufferedInputStream(url.openStream());

                byte[] buffer = new byte[1024];
                long len1 = 0;
                while ((count = is.read(buffer)) != -1
                        && !downLoad.isCancelled()) {
                    len1 += count;
                    publishProgress("" + len1);
                    fos.write(buffer, 0, count);
                }
                fos.flush();
                fos.close();
                is.close();

            }
            logger.info("Success -> file downloaded succesfully. returning 'success' code");
            return Util.APK_DOWNLOAD_SUCCESS;

        } catch (IOException e) {
            logger.error("Exception in update process : "
                    + Util.getStackTrace(e));
        }
        logger.info("Failed -> file download failed. returning 'error' code");
        return Util.APK_DOWNLOAD_FAILED;
    }

    @Override
    protected void onPostExecute(String result) {
        logger.info("on DownLoad onPostExecute. result : " + result);
        progressDialog.dismiss();
        removeDialog(DOWNLOAD_ONPROGRESS);
        if (result.equalsIgnoreCase(Util.APK_DOWNLOAD_SUCCESS)) {
            Update();

        } else {
            Toast.makeText(DownloadAllContentsActivity.this,
                    getString(R.string.updateApplicationFailed),
                    Toast.LENGTH_LONG).show();

            loadDataAsync.execute();

        }

    }

    @Override
    protected void onProgressUpdate(String... values) {
        if (values != null && values.length > 0) {
            progressDialog.setProgress(Integer.parseInt(values[0]));
        }

    }


}