Не удалось сохранить файл изображения в Android Oreo update. Как это сделать?

Я не могу сохранить файл изображения в Android Орео(8.0) интерфейс 26.
Код отлично работает на уровне api 25 (7.0), и я не нашел никаких изменений в документации "Android 8.0 Изменения Поведения"

вот мой код

String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myrootDir = new File(root);
if (!myrootDir.exists()) {
    myrootDir.mkdir();
}

File myDir = new File(root + "/Myimages");
if (!myDir.exists()) {
    myDir.mkdir();
}
final String fname = System.currentTimeMillis()+"myimage.png";
File file = new File(myDir, fname);
if (file.exists())
    file.delete();
try {
    FileOutputStream out = new FileOutputStream(file);
    b.compress(Bitmap.CompressFormat.PNG, 100, out);
    out.flush();
    out.close();
}catch (Exception e){
   Log.e("MYAPP", "exception", e);
}

исключением является FileNotFoundException, нет такого файла или каталога. (Но почему не в android n ?)

java.io.FileNotFoundException: /storage/emulated/0/Pictures/Myimages/1513151272243myimage.png (No such file or directory)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.open0(Native Method)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.open(FileOutputStream.java:287)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at com.package.package.DetailPage.run(DetailPage.java:737)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Handler.handleCallback(Handler.java:789)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:98)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Looper.loop(Looper.java:164)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6541)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

2 ответов


существует, на самом деле, небольшое, тонкое изменение разрешений для приложений, работающих на и таргетинг API 26.

ранее приложениям автоматически предоставлялись все разрешения в данной группе, если хотя бы одно разрешение в этой группе было предоставлено пользователем. Это означает, что приложение, которое было предоставлено READ_EXTERNAL_STORAGE было бы WRITE_EXTERNAL_STORAGE немедленно предоставлено ему, а также, независимо от того,WRITE_EXTERNAL_STORAGE был явно запрошен.

по состоянию на Oreo, для приложений таргетинг API 26+, это было исправлено, и будут предоставлены только те разрешения, которые явно запрашиваются. Если пользователь уже предоставил разрешение в той же группе, то не будет запроса на новое разрешение, но его все равно необходимо запросить.

в этом-то и была проблема. Когда READ_EXTERNAL_STORAGE было получено разрешение на нугу или ниже, вы автоматически получаете WRITE_EXTERNAL_STORAGE, тоже, без необходимости запрашивать это конкретно. Когда вы попробуйте ту же процедуру сохранения файла в Oreo, вы не получаете WRITE_EXTERNAL_STORAGE автоматически, поэтому запись в конечном итоге терпит неудачу.

просто добавьте конкретный запрос для WRITE_EXTERNAL_STORAGE. Если пользователь уже предоставил READ_EXTERNAL_STORAGE, Они не будут беспокоиться о другом приглашении. Кроме того, вы можете запросить только WRITE_EXTERNAL_STORAGE С самого начала, что неявно включает READ_EXTERNAL_STORAGE, и сэкономит вам потребность в двух отдельных запросах.


Я также испытываю ту же проблему, и я застрял с этой проблемой с 2 месяцев. Я уже дал разрешение на WRITE_EXTERNAL_STORAGE в манифесте, а также снова проверил, есть ли у него разрешение на запись. Я думаю, это не вопрос разрешения. Потому что, когда я тестирую с oreo, папка создается, и в папке, которую я создаю, есть поврежденный файл изображения. Из-за этого он не приходит в галерею, а затем при сохранении возвращает мне изображение, не захваченное. Я получаю эта проблема только в android 7.1.1 и oreo. До Android 7.0 он работает нормально. Я проверил с устройствами samsung galaxy note 8 и Google pixel xl 2. Я использую пользовательскую камеру с функцией gps и ниже

public void onImageAvailable(ImageReader reader) {
                    Image image = null;
                    try {
                        image = reader.acquireLatestImage();
                        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                        byte[] bytes = new byte[buffer.capacity()];
                        buffer.get(bytes);
                        save(bytes);

для сохранения байта изображения и функция сохранения содержит код ниже

OutputStream output = null;
                    try {
                        output = new FileOutputStream(finalFile);
                        output.write(bytes);
                    } finally {
                        if (null != output) {
                            output.close();
                        }
                    }