I released an application on the Android market that has since been removed because about half of the comments were people complaining about corrupted SD cards. I review the code several times and cannot find anything that could damage the SD card. All that happens with external storage is saving streams as images, which are then read into ImageView.
This is what is called in the root activity to create folders. Directory paths are stored in public static variables.
//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();
Below is the code for downloading images and copying them (when they are moved to a saved directory).
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(); }
And this is the background thread for network 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); } } }
If the reboot is executable to update the adapter, the thumbnails are an array of string URLs, and the image name is a unique number of 10-11 digits with the image extension (.jpeg, .png, .gif specifically).
And this is a similar code that runs against the background of synthetics.
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; }
The only instance I could find for damaged SD cards is http://code.google.com/p/android/issues/detail?id=2500
The application is built on Android 1.6, and the error cannot be fixed using an emulator or personal testing on 2.1update1 with HTC Desire.
EDIT: I considered some other questions, and could problems have arisen because I did not flush the buffered output streams? Is this a big deal?