Android Question Grief with Access to DB on External SD

GuyBooth

Active Member
Licensed User
Longtime User
For several years I have left my app unmodified, so set on an old sdk (18 I think), and been able to access a database on my external SD card.
Now I need to update it and with SDK30 I have run into problems with accessing a SQLite database, called MusicBase.db, which must reside on an SD card on my new Android tablet.
My program has no problem identifying that the database exists in this path: /storage/9C33-6BBD/tmm_music/Database/MusicBase.db

I have read all I can find about external storage access, but I have found no references to how to initialize a database file on an external SD card.
I have tried to apply the ExtStorage class methods with - so far- no success.

Can anyone point me in the right direction?
 

agraham

Expert
Licensed User
Longtime User
Android is getting tighter and tighter restrictions on memory access capability. You will not be able to use SQLite to directly manipulate a database on an external SD card as it requires random access to the file and External Storage only provides Stream access. If it is not too big you can copy the database to internal storage, use it there then copy it back when done.
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
Android is getting tighter and tighter restrictions on memory access capability. You will not be able to use SQLite to directly manipulate a database on an external SD card as it requires random access to the file and External Storage only provides Stream access. If it is not too big you can copy the database to internal storage, use it there then copy it back when done.
Can I create my own directory and subdirectories in internal storage (that won't be cleaned out if the app is uninstalled)?
What would be the best approach for this?
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
If your app does not need to go in the Play Store then you can either keep targeting SDK 28 and use PERMISSION_WRITE_EXTERNAL_STORAGE to access all the internal storage or target SDK 30 and use MANAGE_EXTERNAL_STORAGE to access most of internal storage.

Manage External Storage - access internal external storage >= SDK 30 | B4X Programming Forum

Android 11 storage FAQ. First introduced in Android 10, scoped… | by nandana | Android Developers | Medium

From my basic IDE
B4X:
    ' DON'T TARGET ABOVE API 28 FOR THE TIME BEING AS WE NEED TO WORK OUT STORAGE ACCESS
    ' Need to get all the first time things done before Wait For as FirstTime is no longer set on re-entry after a wait
    Dim rp As RuntimePermissions
    
    ' Target SDK 28and earlier
    rp.CheckAndRequest(rp.
    ' DON'T TARGET ABOVE API 28 FOR THE TIME BEING AS WE NEED TO WORK OUT STORAGE ACCESS
    ' Need to get all the first time things done before Wait For as FirstTime is no longer set on re-entry after a wait
    Dim rp As RuntimePermissions
    
    ' Target SDK 28and earlier
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE) ' Implicit read capability if granted
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)    
    Log($"PERMISSION_WRITE_EXTERNAL_STORAGE = ${Result}"$)    
    
    ' Target SDK30 and later 
    ' manually add AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE) to manifest
    'Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files.
    'To determine if granted call Environment.isExternalStorageManager()
    'Dim in As Intent
    'in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION", "package:" & Application.PackageName
)
    'StartActivity(in)

) ' Implicit read capability if granted
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)   
    Log($"PERMISSION_WRITE_EXTERNAL_STORAGE = ${Result}"$)   
    
    ' Target SDK30 and later
    ' manually add AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE) to manifest
    'Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files.
    'To determine if granted call Environment.isExternalStorageManager()
    'Dim in As Intent
    'in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION"", "package:my.package.app")
    'StartActivity(in)
If you need to put your app in the Play Store then I don't know a way to ensure that data survives uninstall except to copy it to the SD card. But I could be missing something as I have no apps in the store and use similar code to the above in my apps.
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
If your app does not need to go in the Play Store then you can either keep targeting SDK 28 and use PERMISSION_WRITE_EXTERNAL_STORAGE to access all the internal storage or target SDK 30 and use MANAGE_EXTERNAL_STORAGE to access most of internal storage.
Fortunately I don't need to put my app through the Play Store.

It's annoying that the rules keep changing!
Thanks for your help. It looks as though I have a few days' work ahead to sort all this out (it's a complex app).
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
One other question - you say:
To determine if granted call Environment.isExternalStorageManager()

What collection/library does Environment belong to?
 
Upvote 0
Top