Home > Software design >  How do you use a Uri opened with ActivityResultContracts.OpenDocumentTree() and query the MediaStore
How do you use a Uri opened with ActivityResultContracts.OpenDocumentTree() and query the MediaStore

Time:08-14

I am trying to get all audio contained in a folder that the user picks.

The user is asked to pick a folder like this

        getUri = registerForActivityResult(
            ActivityResultContracts.OpenDocumentTree(),
            activityResultCallback
        )
        getUri.launch(null)

I am trying to query the folder like this

        var selection = MediaStore.Audio.Media.DISPLAY_NAME   " != ?"
        val selectionArgs = arrayListOf("")
        if (data != null){
            selection  = " AND "
            selection  = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                MediaStore.MediaColumns.RELATIVE_PATH   " LIKE ? "
            } else {
                MediaStore.Audio.Media.DATA   " LIKE ? "
            }
            selectionArgs.add("%$data%")
        }

I have tried the following for data

uri.path.toString()
uri.encodedPath.toString()
uri.pathSegments.last().toString()
uri.pathSegments.joinToString ("/")

None of that is working. The query is empty when there should be three files. These files are in the MediaStore, as a query of all audio files in the MediaStore contains them. The docs are not very helpful (as usual). The stack overflow posts I found leave out how to get a path.

Perhaps I should ask how to get the user to pick a folder and get all the music from the folder they chose? The docs lead me to both code snippets above, so I would be floored if there was no way to connect them (except this is Android I am dealing with, so nothing surprises me anymore).

CodePudding user response:

OpenDocumentTree gives you access to only the Uri you receive and its children. It does not give you access to any path at all, much less one you could use with the MediaStore APIs (nor would you want it to, given that the MediaStore APIs are terrible to begin with).

Instead, the easiest way to deal with the Uri returned by OpenDocumentTree is to pass it to DocumentFile.fromTreeUri(), which gives a DocumentFile object that you can call listFiles() on and use getType() to search for mime types starting with audio/:

// Assuming you have your uri returned by OpenDocumentTree
val rootDirectoryFile = DocumentFile.fromTreeUri(uri)
val directories = ArrayDeque(rootDirectoryFile)
val audioFileUris = mutableListOf<Uri>()

// Loop through all of the subdirectories, starting with the root
while (directories.isNotEmpty()) {
    val currentDirectory = directories.removeFirst()

    // List all of the files in the current directory
    val files = currentDirectory.listFiles()
    for (file in files) {
        if (file.isDirectory) {
            // Add subdirectories to the list to search through
            directories.add(file)
        } else if (file.type?.startsWith("audio/")) {
            // Add Uri of the audio file to the list
            audioFileUris  = file.uri
        }
    }
}
// Now audioFileUris has the Uris of all audio files
  • Related