Skip to content

Commit 9eba51d

Browse files
author
Laks Castro
authored
Merge pull request #59 from EternityForest/fix-subdir-list
Enable listing contents of subfolders on the SAF
2 parents adc9e16 + b8a58a5 commit 9eba51d

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/lib/DocumentCommon.kt

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ fun documentFromSingleUri(context: Context, uri: Uri): DocumentFile? {
4343
return DocumentFile.fromSingleUri(context, documentUri)
4444
}
4545

46+
47+
4648
/**
4749
* Generate the `DocumentFile` reference from string `uri`
4850
*/
@@ -161,12 +163,24 @@ fun traverseDirectoryEntries(
161163
rootOnly: Boolean,
162164
block: (data: Map<String, Any>, isLast: Boolean) -> Unit
163165
): Boolean {
164-
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
165-
rootUri,
166-
DocumentsContract.getTreeDocumentId(rootUri)
167-
)
168166

169-
/// Keep track of our directory hierarchy
167+
var childrenUritmp: Uri?;
168+
169+
// https://stackoverflow.com/questions/41096332/issues-traversing-through-directory-hierarchy-with-android-storage-access-framew
170+
// Credit to user: Foobnix
171+
// If we were to always use getTreeDocumentId, it would apparently always only list the top level folder even if you request a subfolder
172+
try {
173+
// for childs and sub child dirs
174+
childrenUritmp = DocumentsContract.buildChildDocumentsUriUsingTree(rootUri, DocumentsContract.getDocumentId(rootUri));
175+
} catch (e: Exception) {
176+
// for parent dir
177+
childrenUritmp = DocumentsContract.buildChildDocumentsUriUsingTree(rootUri, DocumentsContract.getTreeDocumentId(rootUri));
178+
}
179+
180+
// TODO(@EternityForest, @lakscastro): Remove this variable and use: `val childrenUri = try { ... } catch (e: Exception) { ... }`
181+
val childrenUri = childrenUritmp as Uri;
182+
183+
// Keep track of our directory hierarchy
170184
val dirNodes = mutableListOf<Pair<Uri, Uri>>(Pair(rootUri, childrenUri))
171185

172186
while (dirNodes.isNotEmpty()) {
@@ -187,7 +201,7 @@ fun traverseDirectoryEntries(
187201
val cursor = contentResolver.query(
188202
children,
189203
projection,
190-
/// TODO: Add support for `selection`, `selectionArgs` and `sortOrder`
204+
// TODO: Add support for `selection`, `selectionArgs` and `sortOrder`
191205
null,
192206
null,
193207
null
@@ -267,7 +281,7 @@ fun bitmapToBase64(bitmap: Bitmap): String {
267281
}
268282

269283
/**
270-
* Trick to verify if is a tree URi even not in API 26+
284+
* Trick to verify if is a tree URI even not in API 26+
271285
*/
272286
fun isTreeUri(uri: Uri): Boolean {
273287
if (Build.VERSION.SDK_INT >= API_24) {

docs/Usage/Storage Access Framework.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ This method list files lazily **over a granted uri:**
7171
> **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`).
7272
7373
```dart
74-
/// *Must* be a granted uri from `openDocumentTree`
74+
/// *Must* be a granted uri from `openDocumentTree`, or a URI representing a child under such a granted uri.
7575
final Uri myGrantedUri = ...
7676
final DocumentFile? documentFileOfMyGrantedUri = await myGrantedUri.toDocumentFile();
7777
@@ -598,6 +598,7 @@ This class represents but is not the mirror of the original [`DocumentFile`](htt
598598

599599
This class is not intended to be instantiated, and it is only used for typing and convenient purposes.
600600

601+
601602
### <samp>QueryMetadata</samp>
602603

603604
This class wraps useful metadata of the source queries returned by the `PartialDocumentFile`.

0 commit comments

Comments
 (0)