0

I am developing a music player app that allows users to blacklist certain folders. The audio files from those folders will not be shown in the app.

I am using the MediaStore.Audio.AudioColumns.DATA column to filter out audio files that is present inside those folders when querying MediaStore for audio files.

I am using this logic to build a complete real path from the uri.

// Open folder picker
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, REQUEST_CODE_FOLDER_SELECT);


// Then in onActivityResult I am building the real path

Uri folder = data.getData();
String[] paths = Objects.requireNonNull(folder.getPath()).split(":");

// completePath looks like: /storage/emulated/0/Test/Another test
String completePath = Environment.getExternalStorageDirectory() + 
                      (paths.length > 1 ? File.separator + paths[1] : "");

Currently, this works fine with folder that are present in primary external storage. But i would like users to select folders from external (removable) sdcards.

I am not sure how to build real folder path for folders present in (removable) sdcards.

I have come across a lot of solutions for "Get part from uri", but most of them were written before Android 10 came with Storage restrictions or only work for internal storage.

My real concern is that different vendors have different name and mounting paths for removable sdcards, hence i cannot hard code something like: "storage/sdcard/{relative folder path from uri}"

Ashutosh Patoa
  • 294
  • 4
  • 20
  • A normal app does not need 'real paths' but uses the uries obtained by those actions. You got a nice SAF uri. Use it as it is. But.. you can tell us of course why you think you need to convert it to a file system path. – blackapps Nov 11 '20 at 10:58
  • `intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)` Remove that. It does nothing. You cannot grant anything. You should be glad that something becomes granted to you. – blackapps Nov 11 '20 at 11:00
  • You can obtain the 'real path' of a removable micro sd card by looking at the second item returned by getExternalFilesDirs(). – blackapps Nov 11 '20 at 11:04
  • Also if you looked at the uri.toString() value of a uri choosed from removable sd card you could easily decode 'real path' yourself. Please post such an uri and i will show you. – blackapps Nov 11 '20 at 11:05
  • @blackapps i need the real path so that i can check if the path in the `MediaStore.Audio.AudioColumns.DATA` column matches the selected path. `MediaStore.Audio.AudioColumns.DATA` contains real path of audio files ant not the uri. – Ashutosh Patoa Nov 11 '20 at 11:24
  • @blackapps Uri of folder selected from sdcard looks like `content://com.android.externalstorage.documents/tree/96EC-0CA8%3ATestFolder`. Can you help me build the real path? – Ashutosh Patoa Nov 11 '20 at 11:26
  • Well after you have seen a few of such paths you would know the 'real path' would be `/storage/96EC-0CA8/TestFolder`. Not too difficult to make a function who does that conversion. – blackapps Nov 11 '20 at 11:34
  • The .DATA column is not available on Android 10+. – blackapps Nov 11 '20 at 11:37
  • Further it is totally unclear why you would mess around with the media store for an uri obtained by SAF. Makes no sense. – blackapps Nov 11 '20 at 11:41
  • I am not querying media store with the URI obtained by SAF or anything such. When loading audio files from MediaStore, I am simply filtering audio files whose path in the `MediaStore.Audio.AudioColumns.DATA` column matches the selected folder path. Since you mentioned that the specific column will not be available from Android 10+, can you suggest any alternative so that i can hide audio files from the folders that the user blacklisted in my app? – Ashutosh Patoa Nov 11 '20 at 11:47
  • "Currently, this works fine with folder that are present in primary external storage" -- there are over 26,000 device models. How many were you planning on testing to see if this undocumented and unsupported approach will prove to be reliable? What do you plan to do when the user chooses a cloud storage provider when you request a location via `ACTION_OPEN_DOCUMENT_TREE`? What do you plan to do with `DATA` values that do not match your expectations? – CommonsWare Nov 11 '20 at 11:52
  • @CommonsWare. This is my initial implementation which i am currently testing. And yes this may not be reliable but i am not sure how to get the user select a folder otherwise. This is what i came up with initially. – Ashutosh Patoa Nov 11 '20 at 11:59
  • `am using the MediaStore.Audio.AudioColumns.DATA column to filter out audio files that is present inside those folders ` Use the .RELATIVE_PATH column to filter out folders. As .RELATIVE_PATH contains folder names. – blackapps Nov 11 '20 at 12:00
  • If you want to let the user choose folders to blacklist them then query the mediastore for all audio files. Meanwhile make an arraylist of all .RELATIVE_PATH values. Let the user choose from this arraylist to block folders. No need for all that SAF and 'real path' stuff. – blackapps Nov 11 '20 at 12:04
  • @blackapps Thanks for your suggestions. As per the documentation RELATIVE_PATH is added in Api 29 so i need to continue to use the "real path" impl. for Api<29, which is not an issue as we dont have storage restrictions. – Ashutosh Patoa Nov 11 '20 at 12:56
  • Even then you could do without SAF by building up an arraylist of folders obtained from .DATA column. – blackapps Nov 11 '20 at 13:02
  • Yup i was thinking of the same. Thanks for the help. – Ashutosh Patoa Nov 11 '20 at 13:15

0 Answers0