0

Files:

root@generic_x86:/storage # ls -la 1AF9-2810/
-rwxrwx--x root     sdcard_rw   348218 2016-08-19 17:55 2012 (1).JPG
-rwxrwx--x root     sdcard_rw   106512 2014-12-05 19:49 2012 (2).jpg
drwxrwx--x root     sdcard_rw          2016-08-16 19:36 Android
drwxrwx--x root     sdcard_rw          2016-08-16 19:36 LOST.DIR

Android API 23 Permissions granted:

ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
true
ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
true

Test new file 1: ko

new File("/storage/emulated/1AF9-2810/test1").createNewFile()
IOException - open failed: ENOENT (No such file or directory)

Test new file 2: ko

new FileOutputStream("/storage/emulated/1AF9-2810/test2", false)
FileNotFoundException - /storage/emulated/1AF9-2810/test2: open failed: ENOENT (No such file or directory)

Test existing file: ko

new FileOutputStream("/storage/emulated/1AF9-2810/2012 (1).JPG", false)
FileNotFoundException - /storage/emulated/1AF9-2810/2012 (1).JPG: open failed: ENOENT (No such file or directory)

Test /storage/emulated/0: ok

new FileOutputStream("/storage/emulated/0/test3.JPG", false)
FileOutputStream OK!!

The original Google Android Gallery has Write access to my images and can write into it. (See timestamp "2016-08-19 17:55 2012 (1).JPG")

Can someone explain what happens? Why can't I write into the sd card path /storage/emulated/1AF9-2810?

root@generic_x86:/storage # ls -la
drwxrwx--x root     sdcard_rw          2016-08-19 17:55 1AF9-2810
drwx--x--x root     sdcard_rw          2016-08-19 17:28 emulated
drwxr-xr-x root     root              2016-08-19 17:28 self

df

root@generic_x86:/storage # df
Filesystem               Size     Used     Free   Blksize
/dev                   249.6M    44.0K   249.6M   4096
/sys/fs/cgroup         249.6M    12.0K   249.6M   4096
/mnt                   249.6M     0.0K   249.6M   4096
/system                  1.2G   861.7M   378.2M   4096
/cache                  61.0M    64.0K    60.9M   4096
/data                    1.9G   205.6M     1.7G   4096
/storage               249.6M     0.0K   249.6M   4096
/mnt/runtime/default/emulated     1.9G   205.6M     1.7G   4096
/storage/emulated        1.9G   205.6M     1.7G   4096
/mnt/runtime/read/emulated     1.9G   205.6M     1.7G   4096
/mnt/runtime/write/emulated     1.9G   205.6M     1.7G   4096
/mnt/media_rw/1AF9-2810  1020.0M   474.0K  1019.5M   2048
/mnt/runtime/default/1AF9-2810  1020.0M   474.0K  1019.5M   2048
/storage/1AF9-2810    1020.0M   474.0K  1019.5M   2048
/mnt/runtime/read/1AF9-2810  1020.0M   474.0K  1019.5M   2048
/mnt/runtime/write/1AF9-2810  1020.0M   474.0K  1019.5M   2048

Edit: Interesting discussion: http://forum.xda-developers.com/showthread.php?t=2634840&page=2

But it does not work without root access. We need the WRITE_MEDIA_STORAGE permission which is only allowed for system processes.

Denny Weinberg
  • 2,492
  • 1
  • 21
  • 34
  • Why not try it the right way, using getExternalStoragePublicDirectory(), getExternalFilesDir(), or getExternalFilesDirs() – lionscribe Aug 19 '16 at 18:49
  • Because I need to write into the original file in order to update the exif information. – Denny Weinberg Aug 19 '16 at 18:56
  • Any trial to `/storage/emulated/1AF9-2010` will fail anyway because it's an invalid path. The test with `/storage/emulated/0/test3.JPG` is ok because 0 is, as expected, a user_id (you). Is 1AF9-2810 an external scdard or a USB? Could you report `ls -la /mnt/runtime/write/1AF9-2810` and try to create a new file on that folder? – libeasy Aug 21 '16 at 12:29

1 Answers1

2

You have not been able to write to arbitrary locations on removable storage since Android 4.4. Your permissions are for external storage, which is not removable storage.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Why does the original gallery can write into this folder? And also any third party file explorer? – Denny Weinberg Aug 19 '16 at 18:57
  • @DennyWeinberg: "Why does the original gallery can write into this folder?" -- pre-installed apps can be granted additional rights by the ROM developer. "And also any third party file explorer?" -- generally, they can't work with removable storage either. – CommonsWare Aug 19 '16 at 18:58
  • So absolutely no solution for that? You are maybe right. Someone reported to me that ES File Explorer could access the files. But maybe only read access? No write access? – Denny Weinberg Aug 19 '16 at 19:01
  • @DennyWeinberg: "So absolutely no solution for that?" -- you are welcome to use `ACTION_OPEN_DOCUMENT`, `ACTION_CREATE_DOCUMENT`, and the rest of [the Storage Access Framework](https://developer.android.com/guide/topics/providers/document-provider.html). Those two `Intent` actions correspond to "file open" and "file save as" dialogs from a deskop OS. The user can work with any storage provider: external storage, removable storage, Google Drive, Dropbox, etc. You work with `Uri` objects (analogous to URLs) and a `ContentResolver` (analogous to an HTTP client API) to read and write the contents. – CommonsWare Aug 19 '16 at 19:04
  • That is really crazy no? The hardware provider/google can develop a camera app that creates photos and the normal developer cannot change the exif information and no "hard write" permission exists... Or simply delete an image from the gallery... Am I alone with this opinion? – Denny Weinberg Aug 19 '16 at 19:09
  • @DennyWeinberg: "the normal developer cannot change the exif information" -- sure the developer can. Have the user choose the image via `ACTION_OPEN_DOCUMENT` and use [an EXIF library that can work with streams instead of files](https://commonsware.com/blog/2016/05/31/tale-two-exifinterfaces.html). – CommonsWare Aug 19 '16 at 19:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/121378/discussion-between-denny-weinberg-and-commonsware). – Denny Weinberg Aug 19 '16 at 19:22
  • So If I try to open the outputStream with "getContentResolver().openOutputStream(uri)" it says that I need the permisson WRITE_MEDIA_STORAGE. But this is only possible for system apps! – Denny Weinberg Aug 19 '16 at 21:24
  • @DennyWeinberg: If you got the `Uri` from `ACTION_OPEN_DOCUMENT` or `ACTION_CREATE_DOCUMENT`, that shouldn't happen. You might consider asking a fresh Stack Overflow question, showing your code, the value of your `Uri`, and the stack trace. – CommonsWare Aug 19 '16 at 21:29
  • @DennyWeinberg: [This sample app](https://github.com/commonsguy/cw-omnibus/tree/master/Documents/TinyTextEditor) handles writing to a `Uri` from those actions. It's a bit convoluted, because it is demonstrating a number of different things (tabbed text editing, edit history, spinning tabs off into a separate window on Android 7.0+, getting persistable `Uri` permissions, etc.). – CommonsWare Aug 19 '16 at 21:49
  • ok. Thank you. I found also that after using ACTION_OPEN_DOCUMENT_TREE I can access the entire tree selected by the user. Damn this is not cool! – Denny Weinberg Aug 19 '16 at 21:53
  • I found my solution here: http://stackoverflow.com/questions/26744842/how-to-use-the-new-sd-card-access-api-presented-for-lollipop But I have to ask the user one times to open the SD card root tree. – Denny Weinberg Aug 20 '16 at 12:08
  • @DennyWeinberg: I would not rely on that working over the long haul. – CommonsWare Aug 20 '16 at 12:44