Java.io.ioexception: open failed: einval (Invalid argument) при сохранении изображения на внешнем хранилище

Это мой код:

private boolean writeToSD(Bitmap bm, String url) {
    if (canIWriteOnSD()) {
        File sd = Environment.getExternalStorageDirectory();
        File dest = new File(sd, "MoveInBlue/");
        try {
            url = urlCleaner(url);
            if (!dest.exists()) {
                dest.mkdir();
            }
            File file = new File(dest, url + ".png");
            if (!file.exists()) {
                file.createNewFile();
            }
            FileOutputStream out = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            // Do nothing
        }
    }
    return false;
}

РЕШЕНИЕ ПРОБЛЕМЫ:

urlCleaner теперь возвращает url.substring(url.lastIndexOf('?') + 1), и все работает по назначению.

Исключение на самом деле выбрано в file.createNewFile();, и я действительно не знаю почему.

Большое спасибо.

(urlCleaner просто удаляет http://... из URL-адреса и оставляет теги php)

Здесь LogCat:

07-09 13:57:13.479: W/System.err(5715): java.io.IOException: open failed: EINVAL (Invalid argument)
07-09 13:57:13.479: W/System.err(5715):     at java.io.File.createNewFile(File.java:940)
07-09 13:57:13.479: W/System.err(5715):     at com.moveinblue.planner.asynctask.ImageDownloader.writeToSD(ImageDownloader.java:459)
07-09 13:57:13.479: W/System.err(5715):     at com.moveinblue.planner.asynctask.ImageDownloader.access$2(ImageDownloader.java:448)
07-09 13:57:13.479: W/System.err(5715):     at com.moveinblue.planner.asynctask.ImageDownloader$BitmapDownloaderTask.onPostExecute(ImageDownloader.java:270)
07-09 13:57:13.479: W/System.err(5715):     at com.moveinblue.planner.asynctask.ImageDownloader$BitmapDownloaderTask.onPostExecute(ImageDownloader.java:1)
07-09 13:57:13.479: W/System.err(5715):     at android.os.AsyncTask.finish(AsyncTask.java:602)
07-09 13:57:13.479: W/System.err(5715):     at android.os.AsyncTask.access$600(AsyncTask.java:156)
07-09 13:57:13.479: W/System.err(5715):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
07-09 13:57:13.479: W/System.err(5715):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-09 13:57:13.479: W/System.err(5715):     at android.os.Looper.loop(Looper.java:137)
07-09 13:57:13.479: W/System.err(5715):     at android.app.ActivityThread.main(ActivityThread.java:4575)
07-09 13:57:13.489: W/System.err(5715):     at java.lang.reflect.Method.invokeNative(Native Method)
07-09 13:57:13.489: W/System.err(5715):     at java.lang.reflect.Method.invoke(Method.java:511)
07-09 13:57:13.489: W/System.err(5715):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
07-09 13:57:13.489: W/System.err(5715):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
07-09 13:57:13.489: W/System.err(5715):     at dalvik.system.NativeStart.main(Native Method)
07-09 13:57:13.489: W/System.err(5715): Caused by: libcore.io.ErrnoException: open failed: EINVAL (Invalid argument)
07-09 13:57:13.489: W/System.err(5715):     at libcore.io.Posix.open(Native Method)
07-09 13:57:13.489: W/System.err(5715):     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
07-09 13:57:13.489: W/System.err(5715):     at java.io.File.createNewFile(File.java:933)
07-09 13:57:13.489: W/System.err(5715):     ... 15 more

Ответ 1

Строка url содержит недопустимые символы для имени файла. Вам нужно будет очистить имя файла, удалив недопустимые символы.

Ответ 2

Действительно хитрая ошибка, поскольку Android 28 работает просто отлично при попытке написать имя файла с? или: во имя, но Android 22, например, взорвется. Просто запустите пару замен в имени файла:

File(filename.replace(":", "").replace("?", "") [...])

и тогда ты хорошо бежишь

file.createNewFile()