Android native file browser returned file path using 'Downloads' smart filter

On most Android devices, loading a file from the native file choose using the ‘Downloads’ smart filter will return a URL (using getURLResult()) that looks something like this:

content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FJen-mozart-andante.wav

However, on the Pixel 2, loading the same file using the ‘Downloads’ smart filter gives a URL of the form:

content://com.android.providers.downloads.documents/document/681

The former resolves correctly when a call to isLocalFile() or getLocalFile() is made on the URL. The latter does not correctly resolve, and isLocalFile() returns false instead of true as it should. Currently, on the Pixel 2, the user is thus unable to use the ‘Downloads’ smart filter in the file chooser.

I have the exact same issue as @jemur does. My app supports file import and export. Recently a number of users say the import doesn’t work on their Android devices. This issue not only happens on Pixel 2, but also on some Samsung devices.

When I select a file from ‘Internal storage/download’, the URL of this file is something like:

content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FGUITAR.tide

which will be parsed in the method AndroidContentUriResolver::getLocalFileFromContentUri (const URL& url) from the class juce_android_Files.cpp to something like:

/storage/emulated/0/Download/GUITAR.tide

However, if I pick the same file in the ‘Downloads’, which will show the same files that are in ‘Internal storage/download’, the URL becomes something like:

content://com.android.providers.downloads.documents/document/1093

which cannot be recognized so FileChooser::getResults() returns nothing.

I’ve pushed a new class, AndroidDocument, which should allow input/output streams to be created for arbitrary content:// URLs, as long as the application has been granted access:

To use this class, call AndroidDocument::fromDocument, passing the URL result from a native file chooser. Then, you can call createInputStream or createOutputStream to read/write to the file.

Note that it’s important to use a native file chooser when allowing the user to select a file, as this integrates with the Storage Access Framework, and will automatically grant the application access to the selected file.