Scoped storage with MediaStore

Hi team at FMOD, I am wanting to program an Android music player app so am currently exploring some Audio Engines.
When making an Android app, it’s now recommended to use the Scoped Storage framework.
So to work with Uri’s, a FileDescriptor can be created and used to read the file (as I have seen with BASS Audio Engine).
Is this possible for FMOD Audio Engine for Android?
If so, please can you point me to the documentation regarding this, as I was unable to see it.

Otherwise if it’s not possible, then please can you suggest a workaround. Here are some links that may help:

(same domain/extension as above)/questions/57445600/ffmpeg-seeking-not-possible-with-file-descriptor-on-android-q
(same domain/extension as above)/questions/59000390/android-accessing-files-in-native-c-c-code-with-google-scoped-storage-api

If it helps, I have tried with the android:requestLegacyExternalStorage=“true” flag in the manifest and it reads the file fine as I pass a path of that file into the method. But this flag is now not being used in Android as the apps need to target the latest version of Android when uploading to Google Play.
I have downloaded this project from GitHub and just editing and playing around with it before I’m certain that FMOD does what I am looking for:

Thanks :slight_smile:

Hi sachinsshah,

Currently we only support uris under the path file:///android_asset/ using the Asset Manager. Files not under that path are currently opened via fopen, which as you note, is not supported in Android 10/11 for files that you do not have permission to access. I have added a task to add support for Scoped Storage.

We did some further investigation to this:

It appears as though, although scoped storage was recommended for API 29, for API 30 onwards, support for fopen was restored assuming that access permissions were obtained. To work with this, it appears as though the requirements are

API 28 and earlier - no new requirements
API 29 - recommended that you use requestLegacyExternalStorage
API 30+ you need to ensure you have the required access permission using scoped storage apis. After this, you should be able to use the fmod apis via their file paths as was the case previously.

Is it possible for you to add support for either Android 's document URI or Java’s InputStream to FMOD_System_CreateSound() ?

We were building with target API 29 to support Android 11 devices with the requestLegacyExternalStorage option as you suggested above.

But Google Play Store now only allows apps built with target API 30 and up, so all the Android developers have to use either Storage Access Framework ( SAF ) or Media Store API to access public directories of Android 10 devices and later ones.

As you said, it’s still possible to access via direct file paths thanks to the File path API introduced with Android 11 , but the problem is now there’s no way to get any absolute paths with SAF in the first place.

There are two types of URI s.

One is Media URI , which can be obtained using Media Store API .

This provides a column named DATA that contains an absolute path to a file. This is, in fact, officially deprecated but Google said they will keep this as a read-only field for File path API .

So if all the Android developers use Media Store API only, what you said is valid.

But there’s another URI called Document URI , which can be obtained using SAF .

Android developers are now forced to use Google’s native file browser, and SAF is the framework that provides the system file picker.

Of course, we can still try implementing our own file browser with Media Store API , but there are a lot of limitations and it also ruins the user experience because it needs READ_EXTERNAL_STORAGE permission to access other app’s media files. (Asking this permission defeats the initial purpose of the new Android’s Scoped Storage.)

SAF simplifies all of these and no need for us to ask for any permissions.

But the problem is Document URI provides very limited information.

We can get only a file name and file size.

No absolute/relative path at all.

MediaStore class has the getMediaUri() method but it’s totally useless as said here.

With Document Uri , we can get either an InputStream or file descriptor, so if FMOD_System_CreateSound() supports one of them, it’ll be a big help to us.

Currently, I’m thinking of loading a whole file to RAM and then copying the Java side bytes to the native side.

After that, will pass it to FMOD_System_CreateSound() .

But this will take a lot of time to load and be wasteful if a user selects an uncompressed large .wav file.

So I don’t really want to do this.

Please help with this!

Adding a file descriptor support seems the best.

As explained here, we can get a file descriptor integer value via ParcelFileDescriptor.getFd() or detachFd() , and pass it to C’s fdopen() .

Question and answers in this thread may be helpful.

MobileFFmpeg , which is the older version of FFmpegKit , had to go through the same issue last year.

Reading all these comments may be helpful too.
After a long discussion above, one of the contributors added the Uri support to the library.

But as I said earlier, File Descriptor support would be more than enough for FMOD.

Thanks for the extra information. We will look to make sure the storage access framework is also supported.

1 Like

Please.
We will need to migrate to another Audio API otherwise.
If you think it’ll take too much time, please let us know so that we can explain the situation to our users.

It should be in the next release (2.02.06). We will be adding support to createSound for file descriptors on android, which should cover the use case you need.

Edit: support for Uris will be added instead of file descriptors. Still coming in the next release.

1 Like

It’s the document URI support for Storage Access Framework , not Media Store URI, right?

Thank you so much!

CAN’T WAIT!

Yes, document URI, you pass the content:// prefixed path into FMOD like a normal file path. Internally we use the file descriptor method to allow file access.

1 Like

Great! :slight_smile:
But I think you should check if it works with removable SD cards too.
I don’t know how you implemented it, but directly accessing “/proc/self/fd/” fails if the file resides in an external SD card.

I don’t know how MobileFFmpeg worked around it, but they successfully added the document Uri support as you can see from the links above.
I hope it’s also the case with FMOD.

Thanks, I’ll get QA to do another pass over the feature to make sure this is working.

1 Like

Just checked and found the new version now supports document Uris on Android!
Thanks a lot for the effort :slight_smile:

I also checked the documentation but couldn’t find any new lines related to the Uris.
So I assume we can just pass a “content://” style string, which can be obtained by Uri.toString(), to FMOD_System_CreateSound(), just like we did with “file:///android_asset/” strings.

Is this correct?

Yes that’s correct.

1 Like

Oops, I deleted by mistake.
Just tested it and it works like a charm even with files on external SD cards.
Thank you so so much :slight_smile: