有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java监控BufferedInputStream下载进度

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

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) 个答案

  1. # 1 楼答案

    使用您自己的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获取它。否则,您需要适当的服务器支持或启发

  2. # 2 楼答案

    此代码用于显示下载项目的总大小和下载大小

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