Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to save image file in android oreo update. How to do it?

I can't save an image file in android oreo(8.0) api 26.
The code is working perfectly in api level 25 (7.0) and I didn't find any changes in the documentation "Android 8.0 Behavior Changes"

Here is my code

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);
}

Exception is FileNotFoundException, No such file or directory. (But Why not in 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$12.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)
like image 457
jomin v george Avatar asked Dec 13 '17 07:12

jomin v george


2 Answers

There is, in fact, a slight, subtle change in Permissions for apps running on and targeting API 26.

Previously, apps were automatically granted all permissions in a given group if at least one permission in that group had been granted by the user. This means that an app that had been granted the READ_EXTERNAL_STORAGE would've had WRITE_EXTERNAL_STORAGE immediately granted to it as well, regardless of whether WRITE_EXTERNAL_STORAGE had been explicitly requested.

As of Oreo, for apps targeting API 26+, this has been corrected, and only those permissions that are explicitly requested will be granted. If the user has already granted a permission in the same group, then there will be no prompt for the new permission, but it still must be requested.

That was the problem, in this case. When the READ_EXTERNAL_STORAGE permission was granted to your app on Nougat or below, you were automatically getting WRITE_EXTERNAL_STORAGE, too, without having to request that one specifically. When you try the same file save procedure in Oreo, you aren't getting WRITE_EXTERNAL_STORAGE automatically, so the write ultimately fails.

Simply add a specific request for WRITE_EXTERNAL_STORAGE. If the user has already granted READ_EXTERNAL_STORAGE, they won't be bothered with another prompt. Alternatively, you could request solely WRITE_EXTERNAL_STORAGE from the start, which implicitly includes READ_EXTERNAL_STORAGE, and would save you the need for two separate requests.

like image 158
Mike M. Avatar answered Nov 19 '22 05:11

Mike M.


I am also experiencing the same issue and i am stuck with this issue from 2 months. I have already given permission for WRITE_EXTERNAL_STORAGE in the manifest first and also again checking is it have write permission. I think it is not a permission issue. Because when i test with oreo the folder is creating and there is a corrupted image file in the folder i am creating. Because of that it is not coming to the gallery and then on save it returns me Image not captured. I am getting this problem only in android 7.1.1 and oreo. Upto android 7.0 it is working fine. I have checked with devices samsung galaxy note 8 and google pixel xl 2. I am using a custom camera with with gps and below function

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);

for image byte save and the save function contains the code below

OutputStream output = null;
                    try {
                        output = new FileOutputStream(finalFile);
                        output.write(bytes);
                    } finally {
                        if (null != output) {
                            output.close();
                        }
                    }
like image 21
Bindu K S Avatar answered Nov 19 '22 03:11

Bindu K S