0

I'm trying to listen for folder changes on an external SD card on Android Api 26+ , The problem is I don't get the real path, I only get the content URI. I have almost tried everything:

1- third-party libraries.

2- Environment.getExternalStorageDirectory();

3- System.getenv("SECONDARY_STORAGE")

4- System.getenv("EXTERNAL_STORAGE")

5- Environment.getExternalStoragePublicDirectory();

I can't get access to the external SD card and I need a real path to add in the FileObserver. Any suggestions on how to listen to a folder on SD card, or how to get its path?

ahmed galal
  • 504
  • 5
  • 15
  • what you want is to get: `file://` path from `content://` right? – some user Feb 07 '20 at 09:52
  • Yes, I want a real path to pass it in the FileObserver. – ahmed galal Feb 07 '20 at 09:55
  • Try getExternalFilesDirs(). It will return two items of which the second is on the SD card if there is any. – blackapps Feb 07 '20 at 12:38
  • getExternalFilesDirs() returns the app folder in the sd card, I want the root of the sd card. – ahmed galal Feb 07 '20 at 13:40
  • What does it matter? You can remove the ../Android/data//files piece. Then you have your root. There is no other way. – blackapps Feb 07 '20 at 14:08
  • What about the write access? I have granted external read/write but when I try to copy or move files, it returns false. – ahmed galal Feb 07 '20 at 14:14
  • You cannot grant anything. Its Android that could grant you to write to SD card. But Android does not. SD cards are read only since Android 6. Only the app specific directory (app folder) is writable. WIth Android Q you cannot even read with classic file methods outside app folder. – blackapps Feb 07 '20 at 14:16

1 Answers1

0

So after debugging, I found a way to get the path of the picked folder.

First, I build uri using the document tree

Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
                DocumentsContract.getTreeDocumentId(uri));

and performed a query on it

cursor = context.getContentResolver().query(contentUri,  null, null, null, null);

and get the data in document_id column

String string = cursor.getString(cursor.getColumnIndex("document_id"));

it will be something like XXX-XXX:DCIM/ffmpeg if it's in the sd card, or primary:DCIM/ffmpeg if it's in the internal storage.

In the end, I was able to get the real path by using this:

String[] strings = string.split(":");
            String newPath = "/storage/" +
                    (strings[0].equals("primary")?"emulated/0/"+strings[1]:
                            string.replaceAll(":", "/"));

This will split the data in the column into two part (I'm interested in the first string only to know if it's in sd card or not). If it's in the sd card, it will add a prefix /storage/ and replace all colons with a forward slashes, if it's in the primary storage, it will add a prefix /storage/emulated/0/ and replace the colons with forward slashes.

I have tested it with many devices (even the emulator) and it worked fine.

ahmed galal
  • 504
  • 5
  • 15
  • In your first code block, you have `docUri` but in your second code block, you use `contentUri`. Were those intended to be the same? – merlin2011 Apr 19 '20 at 07:36