Мое приложение для Android наносит ущерб SD-картам

Я выпустил приложение на Android Market, который я должен был с тех пор удалить, потому что приблизительно половина комментариев была людьми, жалующимися на поврежденные SD-карты. Я пробежался через код несколько раз и не могу найти ничего, что могло повредить SD-карту. Все, что происходит, который включает внешнее устройство хранения данных, является сохранением потоков как изображения, которые затем прочитаны в ImageView.

Это - то, что называют в корневом действии для создания папок. Пути к каталогам хранятся в общедоступных статических переменных.

//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-11 с расширением изображения (.jpeg, .png, .gif конкретно).

И это - подобный код, выполненный в фоновом режиме 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, и ошибка не recreatable через эмулятор или персональное тестирование на 2.1update1 с HTC Desire.

Править: Я посмотрел на некоторые другие вопросы, и проблемы могли являться результатом меня не сбрасывание буферизированных потоков вывода? Это - грандиозное предприятие?

6
задан daniel 20 July 2010 в 12:08
поделиться