B4A Class ExternalStorage - Access SD cards and USB sticks

Status
Not open for further replies.
SS-2018-03-05_11.16.42.png


Before we start:
  1. External storage means a real sd card or a connected mass storage USB device.
  2. This class can also be used to access the secondary storage (File.DirRootExternal). This becomes relevant with newer versions of Android that restrict direct access.
  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. You can use RuntimePermissions.GetSafeDirDefaultExternal to directly access a specific folder on the secondary storage.
  6. The minimum version for this class is Android 5.

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.04: Packed as a b4xlib. New PreviousUriFileName field that can be used if you need multiple instances of ExternalStorages. This field defines the file where the URI will be written to for future uses.
- 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

  • ExternalStorage.b4xlib
    2 KB · Views: 1,264
  • ExternalStorageExample.zip
    10.4 KB · Views: 1,422
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.
 

boon2

Member
Licensed User
Please post errors as text instead of a screenshot.

There is no such thing.

You need to use B4A Sdk Manager. This resource is probably included in the recommended items list. If not then search for support-core-utils and install it.
Thanks.
 

Attachments

  • upload_2018-9-3_13-50-45.png
    upload_2018-9-3_13-50-45.png
    13.9 KB · Views: 295
Status
Not open for further replies.
Top