5

My app is targetSdkVersion = 29

I take a photo and it save at path:

src = /storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg

Then I want to copy this image to internal storage using FileInputStream/FileOutputStream. Although, my app has WRITE/READ storage permission, but when I code

InputStream inputStream = FileInputStream(src)

I received a FileNotFoundException (open failed: EACCES permission denied).

Anyone have same problem?

Note: I don't want to fix this problem by using a option AndroidManifest.xml because it is temp

android:requestLegacyExternalStorage="true"

bongtoi
  • 181
  • 2
  • 9
  • `I don't want to fix this problem by using a option AndroidManifest.xml because it is temp` No. Not at all. It will stay and be usable for Android 10 devices in the future. Android 11 is less restrictive. But i wonder how you can save a file to that path and after that cannot read from it. – blackapps Nov 20 '20 at 11:27
  • `I take a photo and it save at path:` It seems that you did not use your app for that but just the Camera app. You should have told that yourself. After that you used the Gallery app to find that path. You should have told us that. You just hard coded that path in your code. – blackapps Nov 20 '20 at 11:32

3 Answers3

1

When your targetSdkVersion >= 29 then you have to use ScopedStorage, see the docs: https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage

So the short answer is you can't really do this. You should use MediaStore API to write shared storage ("/storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg" is not private to your app, so the rules apply) if your targetSdkVersion is 29

Here's how you can use MediaStoreApi to insert your image to the user's images: https://stackoverflow.com/a/56990305/5601663

Also if you really just want to save the file, so that it is only available inside your application, then you don't need to use MediaStoreApi see this article on how you can save inside your apps private directory: https://medium.com/@maksymilian.wojcik/android-saving-files-in-internal-storage-image-from-byte-array-etc-dd7d1b86d309

Edit: you can use of course the requestLegacyExternalStorage flag on your manifest, but you've already said that you don't want to use that

Edit2: I see now that you wanted to read from the shared storage. That too won't work, because you need to use either the Storage Access Framework, or the Media Store to read from there, if your targetSdkVersion >= 29. So for that case follow the instructions described here: https://developer.android.com/training/data-storage/use-cases#import-image-media

A. Patrik
  • 1,530
  • 9
  • 20
1

On Android 10 you can't use File API to access files in shared storage, unfortunately, the Android doc is not consistent about this, you can find it here thought

To work around this use Uri API on Android 10, although this is not an issue in Android 11 forward

val uri = ContentUris.withAppendedId(MediaStore.Image.Media.EXTERNAL_CONTENT_URI, id)

applicationContext.contentResolver.openInputStream(uri).use { stream ->
   // do your thing here
}

Note: You can still use File API on any files that your app owns

M. Reza Nasirloo
  • 16,434
  • 2
  • 29
  • 41
0

I show detail my code using FileInputStream/FileOutputStream

src = /storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg

dst = /storage/emulated/0/Android/data/my_app/files/Pictures/IMG_20201118_113434.jpg

src is place where save photo taken, dst is place where I want to copy file src to this

public void copy(String src, String dst) {
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
            OutputStream outPutStream = new FileOutputStream(dst);
            int len;
            byte[] buf = new byte[1024];
            while ((len = bufferedInputStream.read(buf)) > 0) {
                outPutStream.write(buf, 0, len);
            }

            outPutStream.flush();
            outPutStream.close();
            bufferedInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

FileNotFoundException (open failed: EACCES permission denied) at line:

BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));

bongtoi
  • 181
  • 2
  • 9
  • Please dont post your code as answer. Remove this answer snd post your cide in an extra code block in your post – blackapps Nov 20 '20 at 11:29