I am trying to make a file tree with DrawerLayout and NaviagtionView. The NavigationView’s Menu is populated by the method below, which is initialy called on the directory provided by the user via Intent.ACTION_OPEN_DOCUMENT_TREE
with FLAG_GRANT_READ_URI_PERMISSION
, FLAG_GRANT_WRITE_URI_PERMISSION
, FLAG_GRANT_PREFIX_URI_PERMISSION
and FLAG_GRANT_PERSISTABLE_URI_PERMISSION
intent flags set.
private fun addMenuFilesFromDirectory(directoryUri: Uri, subMenu: SubMenu?){
val childDocuments = DocumentFile.fromTreeUri(applicationContext, directoryUri)!!.listFiles()
val dirs = mutableListOf<DocumentFile>()
val scripts = mutableListOf<DocumentFile>()
for (file in childDocuments){
if (contentResolver.getType(file!!.uri) == DocumentsContract.Document.MIME_TYPE_DIR && file.name != ".godot"){
dirs.add(file)
}
else if (MimeTypeMap.getFileExtensionFromUrl(file.uri.toString()) == "gd"){
scripts.add(file)
}
}
...
if (subMenu == null)
{
for (script in scripts)
{
Log.d("","${script.name}, ${script.exists()}") // correct file name and "true" is logged for every item
viewDocumentTable[navigationView.menu.add(script.name)] = script
}
}
else{
for (script in scripts){
Log.d("","${script.name}, ${script.exists()}")
viewDocumentTable[subMenu.add(script.name)] = script
}
}
for (dir in dirs){
val sMenu: SubMenu = navigationView.menu.addSubMenu(dir.name)
addMenuFilesFromDirectory(dir.uri, sMenu)
}
}
When a MenuItem is clicked, the following code is executed.
for (script in viewDocumentTable.elements()){ // Debug purpose
Log.d("", "${script.name}, ${script.exists()}") // "null, false" is logged for every item;
// A warning is also logged: "Permission Denial: opening provider com.android.externalstorage.ExternalStorageProvider requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs"
}
val stream = contentResolver.openInputStream(viewDocumentTable[it]!!.uri) // Logs exception "fail to open file: No such file or directory"
val reader = InputStreamReader(stream)
myEditText.setText(reader.readText())
stream!!.close()
reader.close()
I have tried storing Uri instead of DocumentFile, which yielded the same result.
All testing was done on an Android 11 device. Permissions to read, write and manage external storage are specified in the manifest and are also requested during runtime if needed. minSdk
is set to 28, and targetSdk
is set to 34.
Yaroslav Malakhovskiy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.