Anyone else finding scoped-storage near-impossible to get working? lol.
I've been trying to understand how to allow the user to give my app write permissions to a text file outside of the app's folder. (Let's say allow a user to edit the text of a file in their Documents folder). I have the MANAGE_EXTERNAL_STORAGE permission all set up and can confirm that the app has the permission. But still every time I try
val fileDescriptor = context.contentResolver.openFileDescriptor(uri, "rwt")?.fileDescriptor
I get the Illegal Argument: Media is read-only error.
My manifest requests these three permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
I've also tried using legacy storage:
<application
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
But still running into this read-only issue.
What am I missing?
extra clarification
How I'm getting the URI:
view?.selectFileButton?.setOnClickListener {
val intent =
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
}
startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)
}
and then
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 111 && resultCode == AppCompatActivity.RESULT_OK && data != null) {
val selectedFileUri = data.data;
if (selectedFileUri != null) {
viewModel.saveFilename(selectedFileUri.toString())
val contentResolver = context!!.contentResolver
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(selectedFileUri, takeFlags)
view?.fileName?.text = viewModel.filename
//TODO("if we didn't get the permissions we needed, ask for permission or have the user select a different file")
}
}
}
In terms of your code:
ACTION_OPEN_DOCUMENTIntentbelong thereYour real problem, though, is that you appear to be choosing media, such as from the Audio category.
ACTION_OPEN_DOCUMENTguarantees that we can read from the content identified by theUri, but it does not guarantee a writeable location. Unfortunately,MediaProviderblocks all write access, throwing the exception whose message you cited.Quoting myself from the issue that I filed last year:
I wrote a bit more about this problem in this blog post.
So, use
DocumentFileandcanWrite()to see if you are allowed to write to the location identified by theUri, and ask the user to choose a different document.