I'm using SqliteImportExporter library
Note that this library does not appear to be being maintained.
Is there something magic about the URI returned by this process
Yes. For example, you could wrap it in a DocumentFile
using DocumentFile.fromTreeUri()
, then use that DocumentFile
to get DocumentFile
objects representing the documents directly in the root of that tree, etc.
Personally, I used ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
and ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
in this sample project demonstrating importing and exporting databases (covered in this book, FWIW).
How can one simply copy a file to/from the shared folders (e.g. documents folder)
You already have code for this. Your issue is with an uninstall/reinstall cycle and losing permissions to that file. You have a few choices for dealing with that.
First, you could ask the user to remove that file created by your old app installation, so you can write your hard-coded(?) filename to your hard-coded destination again. The user could do this with a pre-installed file manager, for example, if the user has one.
Second, you could let the user choose a filename. If they choose one that you cannot use due to this permissions issue, tell the user and ask the user to give you another filename. Or, you could automatically adjust the filename, the way that Web browsers do when downloading files (e.g., add (1)
to the name).
Third, you could stop writing to Documents/
and instead write to getExternalFilesDir()
(method on Context
). The two main downsides is that this directory is not as convenient and that its contents get removed when your app is uninstalled.
Fourth, you could do what I do in that sample: use ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
to let the user choose where to create the exported database and what to call it. You can then use ContentResolver
and openOutputStream()
to get an OutputStream
for the Uri
that you get back, and you can copy the bytes of the database to that OutputStream
. For a later import, use ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
to let the user choose an exported database for you to use, and use ContentResolver
and openInputStream()
to reverse the process. This gives the user maximum flexibility, as you are not locking them into a particular location and a particular filename. It does mean that the user will need to choose a location and confirm your suggestion of a filename.
There are other possibilities, such as fussing with ACTION_OPEN_DOCUMENT_TREE
, but that one in particular is cumbersome IMHO.