2011-03-06 60 views
2

當我嘗試這個代碼,它開始下載,但隨後卡住警報「逼近」 我該怎麼辦?使用某種背景線程?在android中的大文件下載

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

回答

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