B4A Class ExternalStorage - Access SD cards and USB sticks

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User


Before we start:

1. External storage means a real sd card or a connected mass storage USB device.
2. It has nothing to do with File.DirRootExternal / DirDefaultExternal which actually point to an internal storage.
3. It has nothing to do with runtime permissions.
4. You can use RuntimePermissions.GetAllSafeDirsExternal to directly access a specific folder on the SD card.
5. The minimum version for this class is Android 5. It might work with Android 4.4 (change minSdkVersion if you like to try it).

Starting from Android 4.4 it is no longer possible to directly access external storages.
The only way to access these storages is through the Storage Access Framework (SAF), which is a quite complex and under-documented framework.

The ExternalStorage class makes it simpler to work with SAF.

Usage:

1. Call ExternalStorage.SelectDir. This will open a dialog that will allow the user to select the root folder. Once selected the uri of the root folder is stored and can be later used without requiring the user to select the folder again. Even after the device is booted.

2. Wait For the ExternalFolderAvailable event.
Now you can access the files under Storage.Root, including inside subfolders.

3. Files are represented as a custom type named ExternalFile.

4. The following operations are supported: ListFiles, Delete, CreateNewFile, FindFile, OpenInputStream and OpenOutputStream.

See the attached example.

Depends on: ContentResolver and JavaObject libraries.
Add:
B4X:
#AdditionalJar: com.android.support:support-core-utils
Updates

- V1.03: New CreateDir and FindOrCreateDir subs. Thank you @ac9ts and @DonManfred.
- V1.02: Fix for issue related to the conversion of URIs to strings.
- V1.01: Fixes an issue with Storage.ListFiles. Credit goes to @agraham !
 

Attachments

Last edited:

Claudio Oliveira

Active Member
Licensed User
@Erel,

I'm trying your sample project "as is", and I'm getting this error.
Did I miss something?

B4A Version: 7.80
Parsing code. (0.01s)
Compiling code. (0.05s)
Compiling layouts code. (0.00s)
Organizing libraries. (0.00s)
Generating R file. Error
ERROR: In <declare-styleable> FontFamilyFont, unable to find attribute android:font
ERROR: In <declare-styleable> FontFamilyFont, unable to find attribute android:fontStyle
ERROR: In <declare-styleable> FontFamilyFont, unable to find attribute android:fontWeight
 

RB Smissaert

Well-Known Member
Licensed User
The posted project has a lot of files.
Would it be possible to condense all that in a library or add it to the Files library?

RBS
 

DonManfred

Expert
Licensed User
he posted project has a lot of files.
Would it be possible to condense all that in a library or add it to the Files library?
You are talking about WHICH FILES exactly? There is only ONE Classfile used.....
Additionally you should have started a NEW THREAD for your question.
 

Meigionel TS

Member
Licensed User
How would you detect programmatically if a usb mass storage is attached to the device? Consider this scenario, I have used
B4X:
storage.SelectDir(True)
where the directory I selected was of a usb mass storage, then I removed the mass storage, and try
B4X:
Wait For Storage_ExternalFolderAvailable
    storage.CreateNewFile(storage.Root,"t" & Rnd(1,55555) & ".txt")
instead of throwing a new dialog to select a new path (because the old path no longer exists), it still uses the old path and does not throw any error.

This is a reason why I am looking for a way to detect if the usb mass storage is still there and if it is then use the previous path else ask user to select a new directory again.
 

RB Smissaert

Well-Known Member
Licensed User
> You are talking about WHICH FILES exactly?

All the files in the posted file ExternalStorage.zip.
As they were in the .zip I presumed they were somehow used.

RBS
 

Erel

Administrator
Staff member
Licensed User
ll the files in the posted file ExternalStorage.zip.
As they were in the .zip I presumed they were somehow used.
You only need to add the ExternalStorage class to your code.

instead of throwing a new dialog to select a new path (because the old path no longer exists), it still uses the old path and does not throw any error.
What is the output of CreateNewFile?

What happens if you try to list the files after the USB was removed?
 

Meigionel TS

Member
Licensed User
What is the output of CreateNewFile
The program runs without throwing any error but since the path does not exists, no file is created anywhere.

What happens if you try to list the files after the USB was removed?
I get an null pointer exception (app crashes), and that is what I need to solve. If the user removes the usb storage, I need to detect the change and show a new dialog to select the path again. But I could not understand how to. :/
 

boon2

Member
Licensed User
upload_2018-9-1_13-22-1.png

error
#AdditionalJar: com.android.support:support-core-utils
1.i want link to download .jar
2.and save in where is folder
thanks.
 
Status
Not open for further replies.
Top