B4A Class Manage External Storage - access internal external storage >= SDK 30

Google seems intent on dumbing down Android to the point of uselessnes to me. I think of my devices as little computers and I want a proper file system on them, not the limited tortuous things that Google offers and that I don't understand, ContentChooser, FileProvider, ... o_O I'm getting old and can't cope with complications like that! :(

So here is a class that lets apps on SDK 30 and higher devices treat the file store as a real file store and not some dumbed down abstracted thing. ?

It uses a new permission that Google will not allow for most Play Store apps.
Manage all files on a storage device | Android Developers
As I will never have apps in the Play Store this worries me not one jot :p


The class uses code stolen from Erel's ExternalStorage class to provide a similar API - thank you Erel ?
ExternalStorage - Access SD cards and USB sticks | B4X Programming Forum

EDIT: Note the minor convenience code modification to Sub GetPermission in the ManageExternalStorage class suggested in post #3 below.
in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION", "package:" & Application.PackageName)

EDIT: If for some reason you need to access folders under Android/data or Android/obb there is a loophole in post #35 here. Note that this is probably not intentional on Googles part and may be may closed in the future. If your File Explorer on your device can access these folders this is how it is doing it.
FURTHER EDIT: This loophole now seems to be closed in Android14
 

Attachments

  • ManageExternalStorage_1.00.zip
    13.4 KB · Views: 2,901
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User

Xfood

Expert
Licensed User
Small change to read the package name
Thank you @agraham
Thank you @Erel

B4X:
Public Sub GetPermission
    If HasPermission Then
        RaiseEvent
        Return
    End If
    Dim in As Intent
    ' Be sure to reference your app package name in "pakageg:xxx"                                             ^^^^^^^^^^^^^^^^^
    in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION", "package:" & Application.PackageName)
    StartActivityForResult(in)
End Sub
 

scottie

Member
Licensed User
Longtime User
Using your great example. I'm still not able to do simple file operations
I checked app setting and I do have permission: Allow management of all file
running Android 11
Just to test, All I did was add a button and textbox to this example.


example:
B4X:
Private Sub Button2_Click
edittext1.text = "/Android/data/lb.myapp.lbochs/files"   NOTE:  this is NOT my app folder!

    Try
    File.WriteString(File.DirRootExternal & EditText1.Text,"scott.txt","scott was here")
    Catch
        MsgboxAsync("didn't work: " & File.DirRootExternal & EditText1.Text & "/scott.txt","")
    End Try
End Sub

file.copy(...) wont work either

What am I doing wrong?

-Scott
 

agraham

Expert
Licensed User
Longtime User

scottie

Member
Licensed User
Longtime User
Thanks for your reply. I read your link. Basically that says we cant access /Android/data anymore. but I really want to. Haa
apps like x-plore can do it, so why cant we? I've even tried adding
permissions
REQUEST_INSTALL_PACKAGES
MANAGE_UNKNOWN_APP_SOURCES

and enabled it in app settings
didn't work
 

agraham

Expert
Licensed User
Longtime User

scottie

Member
Licensed User
Longtime User
Good thing I'm off from work today :)
This works in Android 10, but not Android 11.
 
Hi
Thanks for your useful source. This source works fine, but I still have trouble copying a file to the Android / data folder, and Android 11 does not allow access to this folder. What can I do about this problem?
Please help
 

ziwalig

Member
Licensed User
Longtime User
Hello Agraham

I put your example in my app and I can share everything too. Now how can I access my database in a folder? When initializing it comes this error. Sorry for the bad English it is a deepl.com translation.

android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/storage/emulated/0/Test/dbRE.db3': File /storage/emulated/0/Test/dbRE.db3 is not readable
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:365)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:226)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:737)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:284)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:251)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:1392)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:1337)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:946)
at anywheresoftware.b4a.sql.SQL.Initialize(SQL.java:44)
at ch.ziwalig.replikateinrichten.msqlitedb._dbinitialisieren(msqlitedb.java:35)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
at anywheresoftware.b4a.shell.DebugResumableSub$RemoteResumableSub.resume(DebugResumableSub.java:22)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:137)
at anywheresoftware.b4a.BA$2.run(BA.java:387)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8587)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 2062 SQLITE_CANTOPEN_EACCES[2062]): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:337)
... 28 more
 

drgottjr

Expert
Licensed User
Longtime User
attn: @zwalig
android 11, sdk30

for what it's worth,
1) i put an sqlite3 db in dir.assets
2) i copied it to dir.rootexternal
3) i opened it and made a simple query
cap1.png image attached.

4) i created a "Test" folder in dirrootexternal
5) i copied the db from assets to the Test folder
6) i opened it and made a simple query
cap2.png image attached.

cap3 shows the db in dirrootexternal
cap4 shows the db in dirrootexternal/Test


not sure how you implemented the example.
 

Attachments

  • cap.png
    cap.png
    24.7 KB · Views: 554
  • cap2.png
    cap2.png
    21.9 KB · Views: 557
  • cap3.png
    cap3.png
    26.9 KB · Views: 524
  • cap4.PNG
    cap4.PNG
    30.2 KB · Views: 548
Last edited:

swChef

Active Member
Licensed User
Longtime User
Google seems intent on dumbing down Android to the point of uselessnes to me. I think of my devices as little computers and I want a proper file system on them, not the limited tortuous things that Google offers and that I don't understand, ContentChooser, FileProvider, ... o_O I'm getting old and can't cope with complications like that! :(

So here is a class that lets apps on SDK 30 and higher devices treat the file store as a real file store and not some dumbed down abstracted thing. ?

It uses a new permission that Google will not allow for most Play Store apps.
Manage all files on a storage device | Android Developers
As I will never have apps in the Play Store this worries me not one jot :p


The class uses code stolen from Erel's ExternalStorage class to provide a similar API - thank you Erel ?
ExternalStorage - Access SD cards and USB sticks | B4X Programming Forum
FYI just tried this on my Pixel 6 on Android 12. B4A is using android-30\android.jar.
/storage/emulated/0 returns -1
the File Dialog list is empty.
Tried targeting 28 and dropping the 'legacy' (which as I understand it only helps if the specific app had been installed earlier and had access), didn't work.

X-Plore can still access s/e/0, and Android/data/[etc] however.
I've never used X-Plore before on any device.
 
Last edited:

swChef

Active Member
Licensed User
Longtime User
No idea I'm afraid. As far as I know it should just work - as it seems to for me.

Not sure what you mean by this but -1 is the dialog OK code so you pressed the OK button.
minor. just the toast message after hitting ok with no file selected in the example. there were no files to select.
 

Peter Simpson

Expert
Licensed User
Longtime User
Google seems intent on dumbing down Android to the point of uselessnes to me. I think of my devices as little computers and I want a proper file system on them, not the limited tortuous things that Google offers and that I don't understand, ContentChooser, FileProvider, ... o_O I'm getting old and can't cope with complications like that! :(
Hear hear Andrew.
I understand securing internal drives and folders etc, but that's about it. But once I plug in a standard everyday USB dive of one sort or another, I want just want it to act like a normal external drive and not like a highly secure online bank account where you need to jump through all these new fangled bells and whistles just to load a basic bitmap in a imageview.

I'm going to give your class a quick blast just too see what it does exactly...
 
Last edited:
Top