0

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

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())整个文件下载。我如何监视下载进度?

回答

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

    } 


} 
1

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

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

public abstract int read() throws IOException;

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

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

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

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

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

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


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

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

+0

谢谢!最后一件事:'ByteListener'应该是'StreamListener',而不是?如果你解决,我可以接受你的答案:) – Keelan 2013-05-13 09:47:51

+0

你能改变这一点,亚历克斯? – Keelan 2013-05-15 07:17:47