diff --git a/android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/lib/DocumentCommon.kt b/android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/lib/DocumentCommon.kt index 8e49462..a3d6f9a 100644 --- a/android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/lib/DocumentCommon.kt +++ b/android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/lib/DocumentCommon.kt @@ -43,6 +43,8 @@ fun documentFromSingleUri(context: Context, uri: Uri): DocumentFile? { return DocumentFile.fromSingleUri(context, documentUri) } + + /** * Generate the `DocumentFile` reference from string `uri` */ @@ -161,12 +163,24 @@ fun traverseDirectoryEntries( rootOnly: Boolean, block: (data: Map, isLast: Boolean) -> Unit ): Boolean { - val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree( - rootUri, - DocumentsContract.getTreeDocumentId(rootUri) - ) - /// Keep track of our directory hierarchy + var childrenUritmp: Uri?; + + // https://stackoverflow.com/questions/41096332/issues-traversing-through-directory-hierarchy-with-android-storage-access-framew + // Credit to user: Foobnix + // If we were to always use getTreeDocumentId, it would apparently always only list the top level folder even if you request a subfolder + try { + // for childs and sub child dirs + childrenUritmp = DocumentsContract.buildChildDocumentsUriUsingTree(rootUri, DocumentsContract.getDocumentId(rootUri)); + } catch (e: Exception) { + // for parent dir + childrenUritmp = DocumentsContract.buildChildDocumentsUriUsingTree(rootUri, DocumentsContract.getTreeDocumentId(rootUri)); + } + + // TODO(@EternityForest, @lakscastro): Remove this variable and use: `val childrenUri = try { ... } catch (e: Exception) { ... }` + val childrenUri = childrenUritmp as Uri; + + // Keep track of our directory hierarchy val dirNodes = mutableListOf>(Pair(rootUri, childrenUri)) while (dirNodes.isNotEmpty()) { @@ -187,7 +201,7 @@ fun traverseDirectoryEntries( val cursor = contentResolver.query( children, projection, - /// TODO: Add support for `selection`, `selectionArgs` and `sortOrder` + // TODO: Add support for `selection`, `selectionArgs` and `sortOrder` null, null, null @@ -267,7 +281,7 @@ fun bitmapToBase64(bitmap: Bitmap): String { } /** - * Trick to verify if is a tree URi even not in API 26+ + * Trick to verify if is a tree URI even not in API 26+ */ fun isTreeUri(uri: Uri): Boolean { if (Build.VERSION.SDK_INT >= API_24) { diff --git a/docs/Usage/Storage Access Framework.md b/docs/Usage/Storage Access Framework.md index 41cd5d7..1b0c535 100644 --- a/docs/Usage/Storage Access Framework.md +++ b/docs/Usage/Storage Access Framework.md @@ -71,7 +71,7 @@ This method list files lazily **over a granted uri:** > **Note** `DocumentFileColumn.id` is optional. It is required to fetch the file list from native API. So it is enabled regardless if you include this column or not. And this applies only to this API (`listFiles`). ```dart -/// *Must* be a granted uri from `openDocumentTree` +/// *Must* be a granted uri from `openDocumentTree`, or a URI representing a child under such a granted uri. final Uri myGrantedUri = ... final DocumentFile? documentFileOfMyGrantedUri = await myGrantedUri.toDocumentFile(); @@ -598,6 +598,7 @@ This class represents but is not the mirror of the original [`DocumentFile`](htt This class is not intended to be instantiated, and it is only used for typing and convenient purposes. + ### QueryMetadata This class wraps useful metadata of the source queries returned by the `PartialDocumentFile`.