Использование внутреннего хранилища Android для изображений

Я пытаюсь сохранить файл изображения во внутренней памяти моего приложения.

Для этого я написал следующий метод, который принимает идентификатор и растровое изображение и создает файл изображения, где каталог — это статическое поле класса типа File.

// Returns thumbnail
private static Bitmap saveBitmapWithThumbnail(long id, Bitmap bitmap) {
    Bitmap thumbnail;

    if(directory == null) {
        ContextWrapper cw = new ContextWrapper(Engine.getContext());
        directory = cw.getDir(DIRECTORY_NAME, Context.MODE_PRIVATE);
        if(!directory.exists()) directory.mkdir();
    }

    saveBitmap(getImageFileName(id), bitmap);
    saveBitmap(getThumbnailFileName(id), thumbnail=makeThumbnail(bitmap));
    return thumbnail;
}

Что делает этот метод, так это получает идентификатор и растровое изображение и сохраняет исходный файл и созданную миниатюру во внутреннем хранилище.

Имена генерируются как [id+".png"] для исходного файла и [id+"_tn.png"] для файла эскиза.

Метод saveBitmap() — это тот, который записывает растровое изображение во внутреннюю память.

private static void saveBitmap(String fileName, Bitmap bitmap) {
    File imageFile = new File(directory, fileName);

    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.close();
    } catch(Exception e) {}
}

Он берет имя файла (11.png, 11_tn.png, ...) и растровое изображение (будь то оригинал или миниатюра), создает файл и сжимает его в выходной поток.

Странно то, что когда я запускаю свое приложение в первый раз, сохраняя изображения, оно отлично работает.

Он может читать и записывать изображения, хранящиеся во внутренней памяти.

Однако после того, как я закрою свое приложение и снова запущу его, оно выдает исключение FileNotFoundException со следующими журналами.

W/System.err: java.io.FileNotFoundException: /1.png: open failed: ENOENT (No such file or directory)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:458)
W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:78)
W/System.err:     at com.google.dotplace.dotplace.data.Image.parseCursor(Image.java:118)
W/System.err:     at com.google.dotplace.dotplace.data.Image.checkDebug(Image.java:74)
W/System.err:     at com.google.dotplace.dotplace.LoadActivity.debugDatabase(LoadActivity.java:77)
W/System.err:     at com.google.dotplace.dotplace.LoadActivity.onCreate(LoadActivity.java:25)
W/System.err:     at android.app.Activity.performCreate(Activity.java:5275)
W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2167)
W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2253)
W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:142)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1203)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err:     at android.os.Looper.loop(Looper.java:136)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5120)
W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err:     at java.lang.reflect.Method.invoke(Method.java:515)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
W/System.err:     at dalvik.system.NativeStart.main(Native Method)
W/System.err: Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err:     at libcore.io.Posix.open(Native Method)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:442)
W/System.err:   ... 19 more

Единственный вывод, который я могу сделать, это то, что внутреннее хранилище изменяется или его файлы удаляются после закрытия моего приложения, но я не знаю, почему.

Теперь я предполагаю, что у меня проблемы с моим тестированием.

Я тестирую это следующим образом.

  1. Скомпилируйте и запустите проект с файловыми вставками и проверкой.

  2. Скомпилируйте и запустите проект без вставки файлов и проверьте, остались ли данные 1.

Я делаю это, потому что я не делал никакого пользовательского интерфейса для записи или чтения файлов в своем приложении.

Мое единственное предположение: когда я снова компилирую проект, он каким-то образом меняет что-то уникальное в контексте моего приложения, что приводит к изменению внутренней памяти, что я думаю, что это полная ерунда.

Где я не прав??


person Hyun I Kim    schedule 06.04.2017    source источник


Ответы (2)


Есть несколько вещей, которые вы можете делать неправильно. Всякий раз, когда вы хотите читать/записывать внутреннюю/внешнюю память, вы должны убедиться, что делаете следующие вещи;

  1. Поместите READ/WRITE разрешения на хранение в свой манифест.
  2. Если ваш Android Version равен Marshmallow или больше, спросите разрешения во время выполнения. Вы можете получить информацию об этом здесь
  3. Убедитесь, что path указан правильно. В большинстве случаев жестко закодированные пути имеют значение. Дополнительные сведения см. здесь.
  4. Убедитесь, что вы вызываете mkdirs(), если directory не существует.
  5. Убедитесь, что filename указан правильно. Ранее вы сказали, что это 11.png и 11_tn.png, но позже вы обратились к 1.png. Возможно, это вызывает проблему.
person Waqas Ahmed Ansari    schedule 06.04.2017
comment
Спасибо за ответ, но я использую внутреннюю память и не требует разрешения. Я не задаю путь жестко, а получаю его из ContextWrapper. Я проверяю, существует ли папка внутри оператора if в методе saveBitmapWithThumbnail(). 11.png и 11_tn.png были просто примерами, и я использую имена файлов в соответствии с идентификатором sqllite, который начинается с 1. Вот почему мое приложение пыталось получить доступ к 1.png и 1_tn.png. Они были первыми, кто поместил их в базу данных, и id был установлен на 1. - person Hyun I Kim; 06.04.2017
comment
Ваш error ясно говорит, что не находит файл, значит, что-то не так с хранилищем. Посмотрите здесь - person Waqas Ahmed Ansari; 06.04.2017
comment
Да ... Вот почему я так запутался ... Я видел этот вопрос, когда искал эту проблему, но он путал внутренний и внешний пути хранения, в то время как я использую только внутренний путь, который предоставляют ContextWrapper и File. Кроме того, это гораздо более странно, потому что мой код работает при первом выполнении. Он может писать и читать изображения. Ошибка возникает, когда я закрываю приложение и снова запускаю его. Я понятия не имею, что происходит. :( - person Hyun I Kim; 06.04.2017

вы должны дать разрешение runtime для зефира и выше:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />`
person sanjeev kumar    schedule 06.04.2017
comment
Спасибо за ответ, но я использую внутреннюю память, которая не требует разрешения. - person Hyun I Kim; 06.04.2017