Skip to content

Commit 9a89cb4

Browse files
author
LaksCastro
committed
(#10, #11) Add base to read data given uri
1 parent 6cce130 commit 9a89cb4

File tree

4 files changed

+81
-65
lines changed

4 files changed

+81
-65
lines changed

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

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import kotlinx.coroutines.CoroutineScope
1717
import kotlinx.coroutines.Dispatchers
1818
import kotlinx.coroutines.launch
1919
import java.io.BufferedReader
20-
import java.io.FileInputStream
2120
import java.io.InputStreamReader
2221

2322
internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
@@ -67,7 +66,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
6766
if (Build.VERSION.SDK_INT >= API_21) {
6867
result.success(
6968
createDocumentFileMap(
70-
documentFromTreeUri(
69+
documentFromUri(
7170
plugin.context,
7271
call.argument<String?>("uri") as String
7372
)
@@ -77,7 +76,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
7776
CAN_WRITE ->
7877
if (Build.VERSION.SDK_INT >= API_21) {
7978
result.success(
80-
documentFromTreeUri(
79+
documentFromUri(
8180
plugin.context,
8281
call.argument<String?>("uri") as String
8382
)?.canWrite()
@@ -86,7 +85,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
8685
CAN_READ ->
8786
if (Build.VERSION.SDK_INT >= API_21) {
8887
result.success(
89-
documentFromTreeUri(
88+
documentFromUri(
9089
plugin.context,
9190
call.argument<String?>("uri") as String
9291
)?.canRead()
@@ -95,7 +94,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
9594
LENGTH ->
9695
if (Build.VERSION.SDK_INT >= API_21) {
9796
result.success(
98-
documentFromTreeUri(
97+
documentFromUri(
9998
plugin.context,
10099
call.argument<String?>("uri") as String
101100
)?.length()
@@ -104,7 +103,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
104103
EXISTS ->
105104
if (Build.VERSION.SDK_INT >= API_21) {
106105
result.success(
107-
documentFromTreeUri(
106+
documentFromUri(
108107
plugin.context,
109108
call.argument<String?>("uri") as String
110109
)?.exists()
@@ -113,7 +112,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
113112
DELETE ->
114113
if (Build.VERSION.SDK_INT >= API_21) {
115114
result.success(
116-
documentFromTreeUri(
115+
documentFromUri(
117116
plugin.context,
118117
call.argument<String?>("uri") as String
119118
)?.delete()
@@ -122,7 +121,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
122121
LAST_MODIFIED ->
123122
if (Build.VERSION.SDK_INT >= API_21) {
124123
result.success(
125-
documentFromTreeUri(
124+
documentFromUri(
126125
plugin.context,
127126
call.argument<String?>("uri") as String
128127
)?.lastModified()
@@ -135,7 +134,8 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
135134
call.argument<String?>("displayName") as String
136135

137136
val createdDirectory =
138-
documentFromTreeUri(plugin.context, uri)?.createDirectory(displayName) ?: return
137+
documentFromUri(plugin.context, uri)?.createDirectory(displayName)
138+
?: return
139139

140140
result.success(createDocumentFileMap(createdDirectory))
141141
}
@@ -148,30 +148,39 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
148148

149149
result.success(
150150
createDocumentFileMap(
151-
documentFromTreeUri(plugin.context, uri)?.findFile(displayName)
151+
documentFromUri(plugin.context, uri)?.findFile(displayName)
152152
)
153153
)
154154
}
155155
}
156156
COPY -> {
157157
if (Build.VERSION.SDK_INT >= API_21) {
158-
val content = StringBuilder()
159-
val destinationTree = call.argument<String>("destination")!!
160-
val document = documentFromTreeUri(
161-
plugin.context,
162-
Uri.parse(call.argument<String>("uri")!!)
163-
) ?: return
164-
165-
readDocumentContent(document.uri) {
166-
onSuccess = { content.append(this) }
167-
onEnd = {
168-
createFile(
169-
result,
170-
document.type!!,
171-
document.name!!,
172-
destinationTree,
173-
"$content".toByteArray()
174-
)
158+
val destination = Uri.parse(call.argument<String>("destination")!!)
159+
val uri = Uri.parse(call.argument<String>("uri")!!)
160+
161+
if (Build.VERSION.SDK_INT >= API_24) {
162+
DocumentsContract.copyDocument(
163+
plugin.context.contentResolver,
164+
uri,
165+
destination
166+
)
167+
} else {
168+
val content = StringBuilder()
169+
170+
readDocumentContent(uri) {
171+
onEnd = {
172+
val uriDocument = documentFromUri(plugin.context, uri)!!
173+
174+
createFile(
175+
destination,
176+
uriDocument.type!!,
177+
uriDocument.name!!,
178+
content.toString().toByteArray()
179+
) {
180+
result.success(createDocumentFileMap(this))
181+
}
182+
}
183+
onSuccess = { content.append(this) }
175184
}
176185
}
177186
}
@@ -182,13 +191,13 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
182191
val displayName =
183192
call.argument<String?>("displayName") as String
184193

185-
documentFromTreeUri(plugin.context, uri)?.apply {
194+
documentFromUri(plugin.context, uri)?.apply {
186195
val success = renameTo(displayName)
187196

188197
result.success(
189198
if (success)
190199
createDocumentFileMap(
191-
documentFromTreeUri(plugin.context, this.uri)!!
200+
documentFromUri(plugin.context, this.uri)!!
192201
)
193202
else null
194203
)
@@ -198,7 +207,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
198207
PARENT_FILE -> {
199208
if (Build.VERSION.SDK_INT >= API_21) {
200209
val uri = call.argument<String>("uri")!!
201-
val parent = documentFromTreeUri(plugin.context, uri)?.parentFile
210+
val parent = documentFromUri(plugin.context, uri)?.parentFile
202211

203212
result.success(if (parent != null) createDocumentFileMap(parent) else null)
204213
}
@@ -241,29 +250,39 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
241250
directory: String,
242251
content: ByteArray
243252
) {
244-
val documentFile =
245-
documentFromTreeUri(plugin.context, directory)
246-
?: return result.error(
247-
EXCEPTION_PARENT_DOCUMENT_MUST_BE_DIRECTORY,
248-
"You can't create a file inside another file! You can call `createFile` method only on directory documents",
249-
mapOf(
250-
"invalidParentDirectory" to directory,
251-
"displayName" to displayName,
252-
"mimeType" to mimeType
253-
)
254-
)
253+
createFile(
254+
Uri.parse(directory),
255+
mimeType,
256+
displayName,
257+
content
258+
) {
259+
result.success(createDocumentFileMap(this))
260+
}
261+
}
255262

256-
val createdFile = documentFile.createFile(mimeType, displayName)
263+
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
264+
private fun createFile(
265+
treeUri: Uri,
266+
mimeType: String,
267+
displayName: String,
268+
content: ByteArray,
269+
block: DocumentFile?.() -> Unit
270+
) {
271+
272+
val createdFile = documentFromUri(plugin.context, treeUri)!!.createFile(
273+
mimeType,
274+
displayName
275+
)
257276

258277
createdFile?.uri?.apply {
259278
plugin.context.contentResolver.openOutputStream(this)?.apply {
260279
write(content)
261280
flush()
262281

263282
val createdFileDocument =
264-
documentFromTreeUri(plugin.context, createdFile.uri)
283+
documentFromUri(plugin.context, createdFile.uri)
265284

266-
result.success(createDocumentFileMap(createdFileDocument))
285+
block(createdFileDocument)
267286
}
268287
}
269288
}
@@ -374,7 +393,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
374393
if (eventSink == null) return
375394

376395
val document = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
377-
documentFromTreeUri(plugin.context, args["uri"] as String) ?: return
396+
documentFromUri(plugin.context, args["uri"] as String) ?: return
378397
} else {
379398
null
380399
}
@@ -443,11 +462,7 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
443462
) {
444463
val callbacks = CallbackHandler<String>().apply { handler(this) }
445464

446-
val document = documentFromTreeUri(plugin.context, uri)!!
447-
448-
val file = document?.createFile("text/plain", "File created by Shared Storage Sample App") ?: return
449-
450-
plugin.context.contentResolver.openInputStream(file.uri)
465+
plugin.context.contentResolver.openInputStream(uri)
451466
?.use { inputStream ->
452467
BufferedReader(InputStreamReader(inputStream)).use { reader ->
453468
var line = reader.readLine()

android/src/main/kotlin/io/lakscastro/sharedstorage/saf/utils/DocumentCommon.kt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,25 @@ fun documentFromSingleUri(context: Context, uri: Uri): DocumentFile? {
4747
* Generate the `DocumentFile` reference from string `uri`
4848
*/
4949
@RequiresApi(API_21)
50-
fun documentFromTreeUri(context: Context, uri: String): DocumentFile? =
51-
documentFromTreeUri(context, Uri.parse(uri))
50+
fun documentFromUri(context: Context, uri: String): DocumentFile? =
51+
documentFromUri(context, Uri.parse(uri))
5252

5353
/**
5454
* Generate the `DocumentFile` reference from URI `uri`
5555
*/
5656
@RequiresApi(API_21)
57-
fun documentFromTreeUri(context: Context, uri: Uri): DocumentFile? {
58-
val treeUri = if (isTreeUri(uri)) {
59-
uri
57+
fun documentFromUri(context: Context, uri: Uri): DocumentFile? {
58+
return if (isTreeUri(uri)) {
59+
DocumentFile.fromTreeUri(context, uri)
6060
} else {
61-
DocumentsContract.buildDocumentUriUsingTree(
62-
uri,
63-
DocumentsContract.getDocumentId(uri)
61+
DocumentFile.fromSingleUri(
62+
context,
63+
DocumentsContract.buildDocumentUriUsingTree(
64+
uri,
65+
DocumentsContract.getDocumentId(uri)
66+
)
6467
)
6568
}
66-
67-
return DocumentFile.fromTreeUri(context, treeUri)
6869
}
6970

7071
/**
@@ -207,11 +208,11 @@ fun traverseDirectoryEntries(
207208

208209
val uri = DocumentsContract.buildDocumentUriUsingTree(
209210
parent,
210-
DocumentsContract.getDocumentId(parent)
211+
DocumentsContract.getDocumentId(
212+
DocumentsContract.buildDocumentUri(parent.authority, id)
213+
)
211214
)
212215

213-
Uri.Builder().scheme(uri.scheme)
214-
215216
block(createCursorRowMap(rootUri, parent, uri, data, isDirectory = isDirectory))
216217

217218
if (isDirectory != null && isDirectory) {

example/android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="io.lakscastro.sharedstorage.example">
3-
3+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
44
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
55
<application
66
android:icon="@mipmap/ic_launcher"

lib/src/storage_access_framework/saf.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,5 +500,5 @@ Stream<String> getDocumentContent(Uri uri) {
500500

501501
final onNewLine = kDocumentFileEventChannel.receiveBroadcastStream(args);
502502

503-
return onNewLine.map<String>((event) => event as String);
503+
return onNewLine.map<String>((line) => line as String);
504504
}

0 commit comments

Comments
 (0)