How to check which StorageVolume we have access to, and which we don't?

Here is an alternate way to get what you want. It is a work-around like you have posted without using reflection or file paths.

On an emulator, I see the following items for which I have permitted access.

persistedUriPermissions array contents (value of URI only):

0 uri = content://com.android.externalstorage.documents/tree/primary%3A
1 uri = content://com.android.externalstorage.documents/tree/1D03-2E0E%3ADownload
2 uri = content://com.android.externalstorage.documents/tree/1D03-2E0E%3A
3 uri = content://com.android.externalstorage.documents/tree/primary%3ADCIM
4 uri = content://com.android.externalstorage.documents/tree/primary%3AAlarms

"%3A" is a colon (":"). So, it appears that the URI is constructed as follows for a volume where "<volume>" is the UUID of the volume.

uri = "content://com.android.externalstorage.documents/tree/<volume>:"

If the uri is a directory directly under a volume, then the structure is:

uri = "content://com.android.externalstorage.documents/tree/<volume>:<directory>"

For directories deeper in the structure, the format is:

uri = "content://com.android.externalstorage.documents/tree/<volume>:<directory>/<directory>/<directory>..."

So, it is just a matter of extracting volumes from URIs in these formats. The volume extracted can be used as a key for StorageManager.storageVolumes. The following code does just this.

It seems to me that there should be an easier way to go about this. There must be a missing linkage in the API between storage volumes and URIs. I can't say that this technique covers all circumstances.

I also question the UUID that is returned by storageVolume.uuid which seems to be a 32-bit value. I thought that UUIDs are 128 bits in length. Is this an alternative format for a UUID or somehow derived from the UUID? Interesting, and it is all about to drop! :(

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
        var storageVolumes = storageManager.storageVolumes
        val storageVolumePathsWeHaveAccessTo = HashSet<String>()

        checkAccessButton.setOnClickListener {
            checkAccessToStorageVolumes()
        }

        requestAccessButton.setOnClickListener {
            storageVolumes = storageManager.storageVolumes
            val primaryVolume = storageManager.primaryStorageVolume
            val intent = primaryVolume.createOpenDocumentTreeIntent()
            startActivityForResult(intent, 1)
        }
    }

    private fun checkAccessToStorageVolumes() {
        val storageVolumePathsWeHaveAccessTo = HashSet<String>()
        val persistedUriPermissions = contentResolver.persistedUriPermissions
        persistedUriPermissions.forEach {
            storageVolumePathsWeHaveAccessTo.add(it.uri.toString())
        }
        val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
        val storageVolumes = storageManager.storageVolumes

        for (storageVolume in storageVolumes) {
            val uuid = if (storageVolume.isPrimary) {
                // Primary storage doesn't get a UUID here.
                "primary"
            } else {
                storageVolume.uuid
            }
            val volumeUri = uuid?.let { buildVolumeUriFromUuid(it) }
            when {
                uuid == null -> 
                    Log.d("AppLog", "UUID is null for ${storageVolume.getDescription(this)}!")
                storageVolumePathsWeHaveAccessTo.contains(volumeUri) -> 
                    Log.d("AppLog", "Have access to $uuid")
                else -> Log.d("AppLog", "Don't have access to $uuid")
            }
        }
    }

    private fun buildVolumeUriFromUuid(uuid: String): String {
        return DocumentsContract.buildTreeDocumentUri(
            "com.android.externalstorage.documents",
            "$uuid:"
        ).toString()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.d("AppLog", "resultCode:$resultCode")
        val uri = data?.data ?: return
        val takeFlags =
            Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(uri, takeFlags)
        Log.d("AppLog", "granted uri: ${uri.path}")
    }
}