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