2012-12-19 49 views
7

在我的Android應用程序,而不是,我想創建對SD卡的以下文件夾:的Android mkdirs()創建一個零字節文件的文件夾

/mnt/sdcard/OSGiComponents/admin/felix-cache/ 

下面的代碼:

File cacheDir = 
    new File(Environment.getExternalStorageDirectory().getAbsolutePath() + 
       "/OSGiComponents/admin/felix-cache/"); 
// Create the folder 
cacheDir.mkdirs(); 
// Check if it exists 
if (! cacheDir.exists()) { 
    Log.e ("Debug" , "Cache directory cannot be created"); 
} 

我有Android清單文件清單標記下的WRITE_STORAGE_PERMISSION。我可以在SD卡上創建其他文件夾和文件,沒有問題。 該應用程序工作正常以下電話:

  1. 的Nexus S(源於)運行薑餅(2.3)
  2. 的Nexus S(無根)運行果凍豆(4.1.2)
  3. 的HTC Desire(源於)運行的是Froyo(2.2)
  4. 的HTC Desire(無根)運行升級Froyo(2.2)

然而在三星Galaxy Nexus手機(無根)運行冰淇淋三明治(4.0.4),該目錄中創建一個零大小的文件,它可以在Astro被看見。 exists()調用返回false。

Astro showing a zero byte felix-cache file

  1. 你可以從文件夾名稱看,我使用Apache菲利克斯。如果Felix不存在,Felix會自動創建緩存目錄。在Galaxy Nexus上,它總是抱怨它無法創建緩存目錄。 Astro顯示0字節文件而不是文件夾。這就是爲什麼我決定嘗試在初始化Felix之前自己創建緩存文件夾。
  2. 所以,我自己創建了緩存文件夾。該應用第一次運行良好,我可以在Astro中看到該文件夾​​。如果關閉應用程序,然後刪除Astro中的文件夾,然後重新啓動應用程序,即使我的代碼神祕地無法創建緩存目錄,Astro顯示一個0字節的文件。
  3. 在Astro中無法刪除0字節的文件。但是,當我重新啓動手機時,該文件夾神奇地在那裏,並確定。
  4. 我使用FileInstall來觀察OSGiComponents/install文件夾。當我將捆綁包放入該文件夾時,除了Galaxy Nexus(當應用程序首次運行時)時,它會在所有手機上檢測到並安裝。 FileInstall沒有關於無法觀察目錄的日誌/錯誤。
  5. 我已經在2款Galaxy Nexus手機上測試過這個,同樣的問題。

我懷疑這是一個權限問題,但我不確定它是什麼,以及爲什麼在exists()返回false時創建一個0字節的文件。我在代碼中沒有其他地方創建這個文件。

關於可能是什麼問題的任何建議?

謝謝:)

更新:我想我已經確定的問題,請回答我張貼。

+0

public static String FOLDER = Environment.getExternalStorageDirectory()。getPath()+「/ folder /」; 文件screensPath =新文件(FOLDER); screensPath.mkdirs(); 這可能工作。 – itsrajesh4uguys

+0

謝謝,但不幸的是仍然給出了同樣的問題:(我認爲我已經確定了這個問題,我發佈了一個答案如下 –

回答

2

我找到了解決此問題的解決方法。每當我刪除一個文件/目錄,而不是直接使用delete(),我重命名文件/文件夾,然後刪除()它。這種奇怪的解決方法似乎消除了這個問題。

我通過看這個問題的答案有這樣的想法 - Open failed EBUSY device or Resource busy

不過,我不知道爲什麼這個工程,或者是擺在首位造成的問題。

在情況下其他人是否在Galaxy Nexus的使用菲利克斯並遇到同樣的問題,只是改變Felix的源代碼,如下所示:

org.apache.felix.framework.util.SecureAction.java:

public boolean deleteFile(File target) 
{ 
    if (System.getSecurityManager() != null) 
    { 
     try 
     { 
      Actions actions = (Actions) m_actions.get(); 
      actions.set(Actions.DELETE_FILE_ACTION, target); 
      return ((Boolean) AccessController.doPrivileged(actions, m_acc)) 
       .booleanValue(); 
     } 
     catch (PrivilegedActionException ex) 
     { 
      throw (RuntimeException) ex.getException(); 
     } 
    } 
    else 
    { 
     // Solution: Rename before deleting 
     // https://stackoverflow.com/questions/11539657/open-failed-ebusy-device-or-resource-busy 

     File to = new File(target.getAbsolutePath() + System.currentTimeMillis()); 
     boolean renameStatus = target.renameTo(to); 
     boolean deleteStatus = to.delete(); 
     boolean returnStatus = (renameStatus && deleteStatus); 

     // Debug SecureAction 
     //boolean returnStatus = target.delete(); 
     Log.e ("SecureAction" , "Deleting " + target + " delete(): " + returnStatus); 
     return returnStatus; 
    } 
} 
2

請使用而不是

File cacheDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + 
      "/OSGiComponents/admin/felix-cache/"); 
     cacheDir.mkdirs(); 

File cacheDir = 
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + 
      "/OSGiComponents/admin/felix-cache"); 
    cacheDir.mkdir(); 
+1

謝謝,但是我得到了刪除最後一個斜槓和mkdirs()mkdir()或者這些改變的任何組合,如果我的理解是正確的,由於這個目錄樹最初並不存在於手機上,所以必須使用mkdirs()而不是mkdir(),而且Felix也在內部使用mkdirs() –

+0

刪除getAbsolutePath()並檢查一次 – raju

+0

我仍然得到同樣的問題 –

0

雖然沒有直接回答你的問題,下面提及的信息可以幫助你:

在某些設備上,Environment.getExternalStorageDirectory().getAbsolutePath()沒有必要反映實際的外部SD卡路徑。有時它代表內部存儲。

例如在銀河注2:

Log.i(TAG,Environment.getExternalStorageDirectory().getAbsolutePath()); 

將打印

12-19 17:35:11.366: E/sample.Examples(10420):/存儲/ sdcard0

同時實際的外置SD卡應該是:

/存儲/ extSdCard

以下是關於這個問題的幾個職位可以幫助您:

Building a Utility to get the path to External Removable storage every time

Check if the SDCard is present, boolean is always true

How could i get the correct external storage on Samsung and all other devices?

Android how to use Environment.getExternalStorageDirectory()

+0

感謝您的信息,我會查看你的鏈接,看看他們是否有任何問題拋出光明 –

+0

我通過鏈接,但在我的手機/ mnt/sdcard是正確的,並且指向'external'內部閃存。此外,創建緩存的位置並不重要,只要它被創建並且可以是wri tten to。 –

1

我建議您使用adb連接到設備,並使用目錄中的命令ls -l來檢查什麼是操作系統報告關於此0 size file(權限等)。這最終可能會帶來一些問題。

如果你不能找出一個工作解決方案,也許你可以使用exec()直接執行mkdir作出workarround。

可以使用COBE波紋管做到這一點:

public static boolean execCmd(String command, ArrayList<String> results){ 
    Process process; 
    try { 
     process = Runtime.getRuntime().exec(new String [] {"sh", "-c", command}); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return false; 
    } 

    int result; 
    try { 
     result = process.waitFor(); 
    } catch (InterruptedException e1) { 
     e1.printStackTrace(); 
     return false; 
    } 

    if(result != 0){ //error executing command 
     Log.d("execCmd", "result code : " + result); 
     String line; 
     BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
     try { 
      while ((line = bufferedReader.readLine()) != null){ 
       if(results != null) results.add(line); 
       Log.d("execCmd", "Error: " + line); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return false; 
     } 
     return false; 
    } 

    //Command execution is OK 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); 

    String line; 
    try { 
     while ((line = bufferedReader.readLine()) != null){ 
      if(results != null) results.add(line); 
      Log.d("execCmd", line); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return false; 
    } 
    return true; 
} 

要使用它:

boolean res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents", results); 
if(!res) return error; 

res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin", results); 
if(!res) return error; 

res= execCmd("mkdir "+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSGiComponents/admin/felix-cache", results); 
if(!res) return error; 

問候。

+0

感謝您的詳細回覆。我試過你的解決方法,但不幸的是,它仍然給出了同樣的問題:( –

+0

我今天做了一些調試,並確定了引起問題的文件操作的順序。我發佈了一個關於這個問題 - [相關問題](http: //www.stackoverflow.com/questions/14001730/android-felix-bug-particular-sequence-of-operations-producing-zero-byte-file-i) –

1
String root = Environment.getExternalStorageDirectory() 
      .getAbsolutePath()+"/OSGiComponents/admin/felix-cache"; 
    File myDir = new File(root); 

    String fname = "Image Name as you want"; 
    File file = new File(myDir, fname); 
    if (file.exists()) 
     file.delete(); 
    try { 
     FileOutputStream out = new FileOutputStream(file); 
     bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); 
     out.flush(); 
     out.close(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
+0

當你刪除一段代碼時,解釋總是很好 – Mike

+0

@ Yogesh - 謝謝,但我想創建一個目錄,而不是一個文件。 –

相關問題