Skip to content

Commit 05b9d9f

Browse files
author
Laks Castro
authored
Merge pull request #63 from lakscastro/feat/list-subfolder-contents
Fix subfolder contents listing and `openDocumentFile` API
2 parents 9eba51d + f950397 commit 05b9d9f

12 files changed

Lines changed: 157 additions & 435 deletions

File tree

android/src/main/kotlin/io/lakscastro/sharedstorage/storageaccessframework/DocumentFileApi.kt

Lines changed: 86 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import io.lakscastro.sharedstorage.ROOT_CHANNEL
1414
import io.lakscastro.sharedstorage.SharedStoragePlugin
1515
import io.lakscastro.sharedstorage.plugin.*
1616
import io.lakscastro.sharedstorage.storageaccessframework.lib.*
17+
import kotlinx.coroutines.CoroutineScope
18+
import kotlinx.coroutines.Dispatchers
19+
import kotlinx.coroutines.launch
1720
import java.io.FileNotFoundException
1821
import java.io.IOException
1922
import java.io.InputStream
2023
import java.io.OutputStream
21-
import kotlinx.coroutines.CoroutineScope
22-
import kotlinx.coroutines.Dispatchers
23-
import kotlinx.coroutines.launch
2424

2525
/**
2626
* Aimed to implement strictly only the APIs already available from the native and original
@@ -75,57 +75,73 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
7575
)
7676
}
7777
PERSISTED_URI_PERMISSIONS ->
78-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
79-
persistedUriPermissions(result)
80-
}
78+
persistedUriPermissions(result)
8179
RELEASE_PERSISTABLE_URI_PERMISSION ->
82-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
83-
releasePersistableUriPermission(result, call.argument<String?>("uri") as String)
84-
}
80+
releasePersistableUriPermission(
81+
result,
82+
call.argument<String?>("uri") as String
83+
)
8584
FROM_TREE_URI ->
86-
if (Build.VERSION.SDK_INT >= API_21) {
87-
result.success(
88-
createDocumentFileMap(
89-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)
90-
)
85+
if (Build.VERSION.SDK_INT >= API_21) {
86+
result.success(
87+
createDocumentFileMap(
88+
documentFromUri(
89+
plugin.context,
90+
call.argument<String?>("uri") as String
91+
)
9192
)
92-
}
93+
)
94+
}
9395
CAN_WRITE ->
94-
if (Build.VERSION.SDK_INT >= API_21) {
95-
result.success(
96-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)?.canWrite()
97-
)
98-
}
96+
if (Build.VERSION.SDK_INT >= API_21) {
97+
result.success(
98+
documentFromUri(
99+
plugin.context,
100+
call.argument<String?>("uri") as String
101+
)?.canWrite()
102+
)
103+
}
99104
CAN_READ ->
100-
if (Build.VERSION.SDK_INT >= API_21) {
101-
val uri = call.argument<String?>("uri") as String
105+
if (Build.VERSION.SDK_INT >= API_21) {
106+
val uri = call.argument<String?>("uri") as String
102107

103-
result.success(documentFromUri(plugin.context, uri)?.canRead())
104-
}
108+
result.success(documentFromUri(plugin.context, uri)?.canRead())
109+
}
105110
LENGTH ->
106111
if (Build.VERSION.SDK_INT >= API_21) {
107112
result.success(
108-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)?.length()
113+
documentFromUri(
114+
plugin.context,
115+
call.argument<String?>("uri") as String
116+
)?.length()
109117
)
110118
}
111119
EXISTS ->
112120
if (Build.VERSION.SDK_INT >= API_21) {
113121
result.success(
114-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)?.exists()
122+
documentFromUri(
123+
plugin.context,
124+
call.argument<String?>("uri") as String
125+
)?.exists()
115126
)
116127
}
117128
DELETE ->
118129
if (Build.VERSION.SDK_INT >= API_21) {
119130
result.success(
120-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)?.delete()
131+
documentFromUri(
132+
plugin.context,
133+
call.argument<String?>("uri") as String
134+
)?.delete()
121135
)
122136
}
123137
LAST_MODIFIED ->
124138
if (Build.VERSION.SDK_INT >= API_21) {
125-
result.success(
126-
documentFromUri(plugin.context, call.argument<String?>("uri") as String)
127-
?.lastModified()
139+
val document = documentFromUri(
140+
plugin.context,
141+
call.argument<String?>("uri") as String
128142
)
143+
144+
result.success(document?.lastModified())
129145
}
130146
CREATE_DIRECTORY -> {
131147
if (Build.VERSION.SDK_INT >= API_21) {
@@ -146,7 +162,12 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
146162
val displayName = call.argument<String?>("displayName") as String
147163

148164
result.success(
149-
createDocumentFileMap(documentFromUri(plugin.context, uri)?.findFile(displayName))
165+
createDocumentFileMap(
166+
documentFromUri(
167+
plugin.context,
168+
uri
169+
)?.findFile(displayName)
170+
)
150171
)
151172
}
152173
}
@@ -165,9 +186,9 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
165186
}
166187
} else {
167188
result.notSupported(
168-
RENAME_TO,
169-
API_21,
170-
mapOf("uri" to "$uri", "destination" to "$destination")
189+
RENAME_TO,
190+
API_21,
191+
mapOf("uri" to "$uri", "destination" to "$destination")
171192
)
172193
}
173194
}
@@ -180,8 +201,13 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
180201
val success = renameTo(displayName)
181202

182203
result.success(
183-
if (success) createDocumentFileMap(documentFromUri(plugin.context, this.uri)!!)
184-
else null
204+
if (success) createDocumentFileMap(
205+
documentFromUri(
206+
plugin.context,
207+
this.uri
208+
)!!
209+
)
210+
else null
185211
)
186212
}
187213
} else {
@@ -235,9 +261,9 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
235261

236262
if (Build.VERSION.SDK_INT >= API_26) {
237263
putExtra(
238-
if (Build.VERSION.SDK_INT >= API_26) DocumentsContract.EXTRA_INITIAL_URI
239-
else DOCUMENTS_CONTRACT_EXTRA_INITIAL_URI,
240-
tree?.uri
264+
if (Build.VERSION.SDK_INT >= API_26) DocumentsContract.EXTRA_INITIAL_URI
265+
else DOCUMENTS_CONTRACT_EXTRA_INITIAL_URI,
266+
tree?.uri
241267
)
242268
}
243269
}
@@ -380,7 +406,9 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
380406
eventSink = events
381407

382408
when (args["event"]) {
383-
LIST_FILES -> listFilesEvent(eventSink, args)
409+
LIST_FILES -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
410+
listFilesEvent(eventSink, args)
411+
}
384412
}
385413
}
386414

@@ -393,42 +421,41 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
393421
private fun listFilesEvent(eventSink: EventChannel.EventSink?, args: Map<*, *>) {
394422
if (eventSink == null) return
395423

396-
val document =
397-
if (Build.VERSION.SDK_INT >= API_24) {
398-
documentFromUri(plugin.context, args["uri"] as String) ?: return
399-
} else {
400-
null
401-
}
424+
val columns = args["columns"] as List<*>
425+
val uri = Uri.parse(args["uri"] as String)
426+
val document = DocumentFile.fromTreeUri(plugin.context, uri)
402427

403428
if (document == null) {
404429
eventSink.error(
405-
EXCEPTION_NOT_SUPPORTED,
406-
"Android SDK must be greater or equal than [Build.VERSION_CODES.N]",
407-
"Got (Build.VERSION.SDK_INT): ${Build.VERSION.SDK_INT}"
430+
EXCEPTION_NOT_SUPPORTED,
431+
"Android SDK must be greater or equal than [Build.VERSION_CODES.N]",
432+
"Got (Build.VERSION.SDK_INT): ${Build.VERSION.SDK_INT}"
408433
)
409434
} else {
410-
val columns = args["columns"] as List<*>
411-
412435
if (!document.canRead()) {
413436
val error = "You cannot read a URI that you don't have read permissions"
414437

415438
Log.d("NO PERMISSION!!!", error)
416439

417-
eventSink.error(EXCEPTION_MISSING_PERMISSIONS, error, mapOf("uri" to args["uri"]))
440+
eventSink.error(
441+
EXCEPTION_MISSING_PERMISSIONS,
442+
error,
443+
mapOf("uri" to args["uri"])
444+
)
418445

419446
eventSink.endOfStream()
420447
} else {
421448
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
422449
CoroutineScope(Dispatchers.IO).launch {
423450
try {
424451
traverseDirectoryEntries(
425-
plugin.context.contentResolver,
426-
rootOnly = true,
427-
rootUri = document.uri,
428-
columns =
429-
columns
430-
.map { parseDocumentFileColumn(parseDocumentFileColumn(it as String)!!) }
431-
.toTypedArray()
452+
plugin.context.contentResolver,
453+
rootOnly = true,
454+
targetUri = document.uri,
455+
columns =
456+
columns
457+
.map { parseDocumentFileColumn(parseDocumentFileColumn(it as String)!!) }
458+
.toTypedArray()
432459
) { data, _ -> launch(Dispatchers.Main) { eventSink.success(data) } }
433460
} finally {
434461
launch(Dispatchers.Main) { eventSink.endOfStream() }

0 commit comments

Comments
 (0)