Select a non-own (non)media file from anywhere on Android 11+ and get full access without SAF or MANAGE_EXTERNAL_STORAGE

Pick a non-own (not created by the app) media/non-media file from any location on Android 11+, copy/move it to a Shared folder, and gain full access to it without SAF or MANAGE_EXTERNAL_STORAGE.

Test this app on your Andorid 11+ devices and give feedback:

Blocks

Screenshot

If it works on your test devices, I will publish the extension.


Note:
On Android < 11 devices the FilePicker component appears. However, I haven't added any blocks for this case, as it's widely known how it works. Therefore, the app is only designed for testing on Android 11+.

Works on my Pixel 7a with Android 16.

2 Likes

Note:
I just noticed that the File component requests READ permission to photos and media to read a text file on Android 11. This must be granted in order to read the text file. This is, of course, a bug that I've already reported several times. I should have used my MFile extension to rule out this bug. However, this bug doesn't occur on Android 13+.

:+1:

Works fine on Samsung Galaxy A54 running Android 15

Before publishing the extension please remember the naming conventions Naming Conventions for Extension Developers

copyFile --> CopyFile

Taifun

2 Likes

I've added a few more methods, including listing all copied/moved files, to which the app then has full access. This lists the file names and paths. If text/* (mime) files are selected, the text is automatically displayed.

Please test on Android 11+ and provide feedback.

Blocks

All files were selected from the root directory of the external storage:
/storage/emulated/0/. However, it should work from any location on the external storage. Since all these files can be listed, the app has full access to them, which was/is the main purpose of this extension. (Tested on Android 13 and 16, Companion & APK.)

Tested successfully on Samsung Galaxy A54 running Android 15

This is somehow surprising... my understanding was, we can't access the root directory anymore? How do you access it then? See also Gemini's opinion below

Taifun


No, it's not possible to use the standard system file picker (Storage Access Framework) to pick a file directly from the root directory of the emulated shared storage, which is commonly referred to as /storage/emulated/0/ on Android SDK 35 (Android 15). :lock:
This restriction has been in place since Android 11 (API level 30) due to Scoped Storage security enhancements.

Key Restrictions and Workarounds
The Root Directory Restriction

  • System File Picker (SAF): When using the Storage Access Framework (SAF) with the ACTION_OPEN_DOCUMENT or ACTION_OPEN_DOCUMENT_TREE intents, Android explicitly blocks the user from selecting the root directory of the internal storage volume (/storage/emulated/0/) and other high-level shared directories like the Download folder.
  • Purpose: This restriction prevents apps from gaining overly broad access to all files on the device, reinforcing user privacy and data security. The system forces you to request access to more specific locations.

How to Pick Files in SDK 35 (Android 15)
Since you can't access the root, you must direct the user to a more specific, non-restricted location.

  • Use Public Directories (Recommended) :national_park:
    • Instead of the root, ask the user to pick files from well-defined public directories like Documents, Pictures, Music, or Download.
    • You can start the file picker and encourage the user to navigate to a subdirectory.
  • Pick a Single File (Most Common) :page_facing_up:
    • Use the Intent.ACTION_OPEN_DOCUMENT intent. This allows the user to select one or more individual files from any accessible location on their storage.
    • Once a file is picked, your app receives a Content URI for that specific file, granting your app temporary, file-specific access.
  • Pick a Directory (Subfolders Only) :file_folder:
    • Use the Intent.ACTION_OPEN_DOCUMENT_TREE intent to let the user select a persistent directory.
    • The user can select a subfolder within the /storage/emulated/0/ root (e.g., /storage/emulated/0/MyCustomFolder/), and your app will gain access to all files within that selected directory and its subdirectories. Crucially, the root folder itself cannot be selected.
  • Media Files (Photos/Videos) :camera_flash:
    • For accessing shared media, the modern, privacy-friendly approach is to use the MediaStore API and the system Photo Picker. This allows the user to grant one-time, limited access to specific images or videos without needing broad storage permissions.

The system is designed to move developers away from direct file paths like /storage/emulated/0/ and towards using Content URIs and the Storage Access Framework (SAF), which manages access on the app's behalf.

Just tested SAF on Android 6, you can select a file from /storage/emulated/0.

I am sending you the AIA file with the extension via PM so you can examine it more closely.

My extension is ONLY for Android 11+ (i.e., Scoped Storage). On Android < 11, neither SAF nor anything else is needed.

I have four devices running Android 11, 12, 13, and 16. Everything works perfectly on them. Three Google Pixel devices and one OnePlus 8 (Android 12). On all devices, I pick all files from the root directory of the external storage. Companion & APK.

If anyone has an Android 11+ device on which it doesn't work, please let me/us know the Android version and device name.

Also works for Android 13 in companion, and compiled if you request permission for filetype...

Hmm, my app (extension) doesn't need any permission at all.

I have tried this solution and it works on all versions of Android...

his app was compiled online. Using the offline compiler may produce unreliable results.
copy_to_ASD.aia (8.4 KB)

Interesting that the File component can read the text via a contentUri. But how do we get direct access to any file not owned by the app, not just text files, but all possible file types like PDF, JPG, PNG, MP4, MOV, etc.)?

Because that's what my topic is about.

Sorry for my English. I'm testing it with excellent results. Without opening the file, I use the copyfile from sharing with ResultUri. However, you need to specify the dataType, such as application/PDF or image/*. This way, the copy will occur without corrupting the files. I'll publish the blocks as soon as possible. P.S. Use an advanced explorer and not the default one to obtain correct resultUri, such as cxFileExplorer.

:question:

All formats work without corruption. If you don't use an advanced explorer, the resulting file name won't be the original one, but you can edit it and it will still work.



copy_file_to_ASD.aia (8.6 KB)

Yes, strange that this works with FileScope=Shared on Android 11+. I've noticed that before, too. Try copying to one of the Shared folders this way (e.g., /Download). In any case, on Android < 11 it doesn't work like this (i.e. via a contentUri).

It doesn't work with any other FileScope, especially not with Legacy.
Why? @ewpatton

You will notice that storage permissions are requested (of course, incorrectly).

True, it accepts SHARED as the starting point, but the file can be copied from any folder you select. So that's fine by me.