2012-12-19 17 views
7

Nella mia applicazione Android, sto cercando di creare la seguente cartella sul sdcard:mkdirs Android() crea un file di byte allo zero, invece di una cartella

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

Ecco il codice:

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

Ho WRITE_STORAGE_PERMISSION sotto il tag manifest del file manifest di Android. Sono in grado di creare altre cartelle e file senza problemi sulla sdcard. L'applicazione funziona bene sui seguenti telefoni:

  1. Nexus S (radicata) in esecuzione Gingerbread (2.3)
  2. Nexus S (senza radici) in esecuzione Jelly Bean (4.1.2)
  3. HTC Desire (radicata) in esecuzione Froyo (2.2)
  4. HTC Desire (senza radici) in esecuzione Froyo (2,2)

Tuttavia sul Samsung Galaxy Nexus telefono (senza radici) in esecuzione Ice Cream Sandwich (4.0.4), la directory viene creata come uno zero file di dimensioni, che può essere visto in Astro. La chiamata exists() restituisce false.

Astro showing a zero byte felix-cache file

  1. Come si può vedere dal nome della cartella, sto usando Apache Felix. Felix crea automaticamente la directory della cache se non esiste. Su Galaxy Nexus, si è sempre lamentato che non è in grado di creare la directory della cache. Astro mostra un file da 0 byte invece di una cartella. Questo è il motivo per cui ho deciso di provare a creare la cartella cache prima di inizializzare Felix.
  2. Quindi, creo me stesso la cartella cache. L'app funziona bene la prima volta e posso vedere bene la cartella in Astro. Se chiudo l'app, quindi elimino la cartella in Astro e quindi rilancio l'app, anche il mio codice non può creare misteriosamente la directory cache e Astro mostra un file da 0 byte.
  3. Il file da 0 byte non può essere cancellato in Astro. Tuttavia, quando riavvio il telefono, la cartella è magicamente lì e ok.
  4. Uso FileInstall per guardare la cartella OSGiComponents/install. Quando faccio cadere i pacchetti bundle in quella cartella, viene rilevato e installato correttamente su tutti i telefoni ad eccezione di Galaxy Nexus (quando l'app funziona per la prima volta). Non ci sono registri/errori da FileInstall su non essere in grado di guardare la directory.
  5. Ho provato questo su 2 telefoni Galaxy Nexus, lo stesso problema.

Sospetto che si tratti di un problema di autorizzazioni, ma non sono sicuro di cosa sia e perché venga creato un file di 0 byte mentre esiste() restituisce false. In nessun altro punto del codice sto creando questo file.

Qualche suggerimento su quale potrebbe essere il problema?

Grazie :)

UPDATE: Penso che ho identificato il problema, si prega di vedere la risposta che ho postato.

+0

public static String FOLDER = Environment.getExternalStorageDirectory(). GetPath() + "/ folder /"; Screen filesPath = new File (FOLDER); screensPath.mkdirs(); questo potrebbe funzionare. – itsrajesh4uguys

+0

Grazie, ma purtroppo continua a dare lo stesso problema :(Penso di aver identificato il problema, ho postato una risposta qui sotto –

risposta

2

Ho trovato una soluzione che risolve questo problema. Ogni volta che si elimina un file/directory, invece di usare delete() direttamente, rinominare il file/cartella e quindi cancellarlo(). Questa soluzione alternativa sembra rimuovere il problema.

Ho avuto questa idea vedendo le risposte di questa domanda - Open failed EBUSY device or Resource busy

Tuttavia, non sono sicuro perché questo funziona, o che cosa ha causato il problema in primo luogo.

Nel caso qualcuno altro sta usando Felix su Galaxy Nexus e incontra lo stesso problema, basta cambiare il codice sorgente Felix come illustrato di seguito:

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

si prega di utilizzare al posto di

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

a

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

Grazie, tuttavia ottengo lo stesso problema sulla rimozione dell'ultima barra e cambio di mkdir() in mkdir(), o qualsiasi combinazione di questi cambiamenti Se la mia comprensione è corretta, poiché inizialmente questo albero di directory non è presente sul telefono, è necessario utilizzare mkdirs() e non mkdir(). Inoltre, Felix usa anche internamente mkdirs() –

+0

una volta per favore rimuovere getAbsolutePath() e controllare una volta – raju

+0

Ho ancora lo stesso problema –

0

Anche se non è una risposta diretta alla sua domanda, le informazioni di cui qui di seguito possono aiutare a:

In alcuni dispositivi, il Environment.getExternalStorageDirectory().getAbsolutePath() non è necessario riflettere il percorso effettivo della scheda sd esterna. A volte rappresenta la memoria interna.

ad esempio nel Galaxy Note 2:

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

stamperà

12-19 17: 35: 11,366: E/sample.Examples (10420):/stoccaggio/sdcard0

nel frattempo il cartellino SD esterna dovrebbe essere:

/stoccaggio/extSdCard

Di seguito sono diversi posti per quanto riguarda a questo questioni che possono aiutare:

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

Grazie per le informazioni, guarderò attraverso i tuoi link e vedere se qualcuno di loro getta luce sul problema –

+0

Ho passato attraverso i collegamenti, tuttavia sul mio telefono la/mnt/sdcard è corretta e si riferisce al flash interno "esterno" Inoltre, non importa dove viene creata la cache, purché sia ​​creata e possa essere tten to. –

1

Ti suggerisco di connetterti al dispositivo utilizzando adb e utilizzare il comando ls -l nella directory, per verificare che cosa sta segnalando il sistema operativo su questo 0 size file (autorizzazioni, ecc.). Questo alla fine può portare un po 'di luce al problema.

Se non si riesce a trovare una soluzione funzionante, è possibile eseguire un workarround utilizzando exec() per eseguire direttamente un mkdir.

È possibile utilizzare il COBE soffietto per farlo:

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

usarlo:

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; 

saluti.

+0

Grazie per la risposta dettagliata. Ho provato la soluzione, ma sfortunatamente continua a dare lo stesso problema :( –

+0

Oggi ho eseguito il debug e ho identificato la sequenza di operazioni sui file che sta causando il problema. Ho pubblicato una domanda su questo argomento [Domanda correlata] (http: //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

Una spiegazione è sempre utile quando si rilascia un blocco di codice. – Mike

+0

@ Yogesh - Grazie, ma sto cercando di creare una directory, non un file. –

Problemi correlati