2010-07-20 43 views
6

我在Android市場發佈了一個應用程序,之後我不得不取消,因爲大約有一半的評論是人們抱怨損壞的SD卡。我已經翻了幾遍代碼,找不到可能會損壞SD卡的任何東西。所有涉及外部存儲的事情都是將流保存爲圖像,然後將其讀入ImageView。我的Android應用程序正在破壞SD卡

這是在根活動中稱爲創建文件夾的內容。目錄路徑存儲在公共靜態變量中。

//Get the SD Card directory 
    String external = Environment.getExternalStorageDirectory().getAbsolutePath() + "/appfolder/"; 

    CACHE_DIRECTORY = external + ".cache/"; 
    SAVED_DIRECTORY = external + "saved/"; 

    File cache = new File(CACHE_DIRECTORY); 
    File saved = new File(SAVED_DIRECTORY); 
    cache.mkdirs(); 
    saved.mkdirs(); 

下面是下載圖像並複製它們(當它們被移動到保存的目錄時)的代碼。

public static void saveImage(File file, URL url) throws IOException { 
    BufferedInputStream bis = new BufferedInputStream(url.openStream()); 
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 
    int bytes; 
    while ((bytes = bis.read()) != -1) { 
     bos.write(bytes); 
    } 
    bos.close(); 
    bis.close(); 
} 

public static void copy(File fileIn, File fileOut) throws IOException { 
    BufferedInputStream bin = new BufferedInputStream(new FileInputStream(fileIn)); 
    BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(fileOut)); 
    int bytes; 
    while ((bytes = bin.read()) != -1) { 
     bout.write(bytes); 
    } 
    bin.close(); 
    bout.close(); 
} 

這是網絡後臺線程I/O

public void run() { 
    for (String url : thumbnails) { 
     if (url != null) { 
      String[] urlParts = url.split("/"); 
      String imageName = urlParts[urlParts.length - 1]; 
      File file = new File(Main.CACHE_DIRECTORY + imageName); 
      if (!file.exists() || file.length() == 0) { 
       try { 
        Image.saveImage(file, new URL(url)); 
       } catch (IOException e) {} 
      } 
     actx.runOnUiThread(reload); 
     } 
    } 
} 

凡重載是可運行的更新適配器,縮略圖是字符串URL的數組和形象的名字是一個獨特的10具有圖像擴展名(.jpeg,.png,.gif)的11位數字。

這是在asynctask的背景下運行的類似代碼。

String imageUrl = (String)params[0]; 
    String[] imageUrlParts = imageUrl.split("/"); 
    String imageName = imageUrlParts[imageUrlParts.length - 1]; 
    URL fullImageUrl; 
    try { 
     fullImageUrl = new URL(imageUrl); 
    } catch (MalformedURLException me) { 
     cancel(true); 
     return null; 
    } 

    File file = new File(Main.CACHE_DIRECTORY + imageName); 
    try { 
     URLConnection ucon = fullImageUrl.openConnection(); 
     int requestedSize = ucon.getContentLength(); 
     long fileSize = file.length(); 
     //Either the file does not exist, or it exists but was cancelled early due to 
     //User or IOException, so it needs to be redownloaded 
     if (!file.exists() || ((file.exists()) && fileSize < (requestedSize * 0.8))) { 
      mLoad.setMax(requestedSize); 
      BufferedInputStream bis = new BufferedInputStream(ucon.getInputStream()); 
      BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(file)); 
      int bytes; 
      int count = 0; 
      while ((bytes = bis.read()) != -1) { 
       bout.write(bytes); 
       count++; 
       //Updates in increments of 2kb 
       if (count % 2048 == 0) { 
        publishProgress(count); 
       } 
      } 
      bis.close(); 
      bout.close(); 
     } 

     if (save) { 
      File saveFile = new File(Main.SAVED_DIRECTORY + imageName); 
      copy(file, saveFile); 
     } 
    } catch (IOException e) { 
     cancel(true); 
     return null; 
    } catch (OutOfMemoryError e) { 
     cancel(true); 
     return null; 
    } 

我能找到的損壞SD卡的唯一實例是http://code.google.com/p/android/issues/detail?id=2500

這個應用程序是建立在Android 1.6及錯誤不是通過模擬器或個人測試用的HTC Desire上重新創建2.1update1。

編輯:我已經看了一些其他問題,並可能產生的問題不是我沖洗緩衝輸出流?這是一件大事嗎?

+0

你是什麼損壞SDcards是什麼意思?究竟發生了什麼? – Macarse 2010-07-20 12:23:15

+0

用戶在安裝時收到「損壞的SD卡」消息,並且必須對其進行格式化才能使其再次正常工作。 – daniel 2010-07-20 12:29:16

+0

哦!危險代碼:|呵呵! – Jorgesys 2010-07-20 15:12:20

回答

2

我看到可能與兩件事情:

  • 你應該在finally{ }塊中呼籲流.close()所以他們在結案有錯誤或強制關閉,而寫。
  • 捕捉OutOfMemoryError通常不是一個好主意。 VM已經耗盡內存,許多事情將處於不可預知的狀態,最好在這些情況下放棄。

我的賭注是finally塊,可能與一個OutOfMemoryError發生,而不是中止應用由於catch,導致一些錯誤進一步向下。

+0

謝謝。我將實施這些更改並將其重新上傳到較小的市場,並查看是否出現相同的問題。 – daniel 2010-07-22 00:50:57

0

我假設你說的是文件系統損壞,而不是SD卡的硬件損壞。 Android應用程序在沙盒中運行,所以我認爲應用程序會(幾乎)不可能破壞文件系統。

也許這是一個安卓特定的錯誤,它是由你的代碼正在做的事情觸發的。我不得不同意複製字節是不好的做法。您應該嘗試複製512或1024字節的塊。

而且我會用內部存儲。tmp文件: Android Storage Options

相關問題