2010-07-20 9 views
6

Ho rilasciato un'applicazione sul mercato Android che da allora ho dovuto smontare perché circa la metà dei commenti riguardava persone che si lamentavano di schede SD danneggiate. Ho letto il codice alcune volte e non riesco a trovare nulla che possa danneggiare una scheda SD. Tutto ciò che accade per l'archiviazione esterna è il salvataggio di flussi come immagini, che poi vengono letti in ImageView.La mia app Android danneggia le schede SD

Questo è ciò che viene chiamato nell'attività root per creare le cartelle. I percorsi di directory sono memorizzati in variabili statiche pubbliche.

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

E il seguito è riportato il codice per il download di immagini e la copia (per quando vengono spostati nella directory salvata).

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

E questo è un thread in background per la rete di 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); 
     } 
    } 
} 

Dove ricarica è un eseguibile per aggiornare un adattatore, le miniature è un array di stringhe di URL e il nome dell'immagine è un unico 10- Numero a 11 cifre con un'estensione dell'immagine (.jpeg, .png, .gif in particolare).

E questo è un codice simile eseguito sullo sfondo di un 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; 
    } 

L'unico caso che ho trovato su schede SD danneggiate è http://code.google.com/p/android/issues/detail?id=2500

L'applicazione si basa su Android 1.6 e il bug non è recreatable tramite emulatore o test personale su 2.1update1 con HTC Desire.

MODIFICA: ho esaminato alcune altre domande e potrebbero esserci dei problemi che potrebbero sorgere da me non svuotando i flussi di output bufferizzati? È un grosso problema?

+0

Che cosa si intende per SDcards danneggiati? Cosa succede esattamente? – Macarse

+0

Dove l'utente riceve il messaggio "Corrupt SD Card" quando viene montato e deve formattarlo per farlo funzionare di nuovo. – daniel

+0

ohhh! Codice pericoloso: | hehe! – Jorgesys

risposta

2

vedo due cose che potrebbero essere collegati:

  • si dovrebbe chiamare .close() sui flussi all'interno di un blocco finally{ } in modo che siano chiusi nel caso in cui ci sia un errore o di forza vicino durante la scrittura.
  • Catching OutOfMemoryError di solito non è una buona idea. La VM ha esaurito la memoria e molte cose si troveranno in uno stato di imprevedibilità, meglio abortire in questi casi.

La mia scommessa è sul finally blocco, forse in relazione a un OutOfMemoryError accadendo e non abortire l'applicazione a causa della catch, causando qualche errore più in basso.

+0

Grazie. Implementerò le modifiche e lo ricaricherò su un mercato più piccolo per vedere se si presentano gli stessi problemi. – daniel

0

Presumo che si stia parlando di danneggiamento del filesystem e non di danni hardware della scheda SD. Le app per Android funzionano in sandbox, quindi penso che sarebbe (quasi) impossibile per un'app danneggiare il filesystem.

Probabilmente si tratta di un bug specifico per Android che viene attivato da qualcosa che sta facendo il tuo codice.

Devo dire che copiare i byte è una cattiva pratica. Dovresti provare a copiare blocchi di 512 o 1024 byte.

Inoltre vorrei utilizzare memoria interna per i file tmp: Android Storage Options

Problemi correlati