Read/Write files

After investigating, it looks like certain file locations (particularly shared locations on external storage) must now be accessed via the ContentResolver mechanism. Plain file paths don’t seem to work for these locations. This means that JUCE’s File type isn’t really suitable for interacting with such documents on Android - the document is represented by a URL rather than a filepath, and the supported behaviours don’t match those of standard files.

To allow working with files on Android, I’ve added a new class, AndroidDocument, which integrates properly with the Storage Access Framework, and should allow reading/writing to user-selected files. This class works a bit like File, but has a more limited interface that only includes operations that are supported on Android.

To use it, launch a native file chooser so that the user can pick a file to read or write. Then, pass the URL result of the file chooser to AndroidDocument::fromDocument. You can then use createInputStream and createOutputStream to read/write to the file. It’s also possible to query file information with getInfo, and to delete and rename the file.

If you want to allow the user to read/write collections of files in a shared location (e.g. to export stems or presets from a DAW), you can launch the native file chooser in directory-selection mode, then pass the URL result to AndroidDocument::fromTree. Then, you can create new nested directories with createChildDirectory, and nested files with createChildDocumentWithTypeAndName. You can also use AndroidDocumentIterator::make(Non)Recursive to query the contents of a directory.

To enable writing portable programs, AndroidDocument can be constructed from a File. It’s intended that on Android, a program will use fromDocument or fromTree, and on other platforms, the program will use fromFile instead (you might use #if JUCE_ANDROID to select which version to use). After construction, the same AndroidDocument interface will work consistently on all platforms.

3 Likes