@@ -31,33 +31,87 @@ import okhttp3.MediaType
31
31
import okhttp3.MediaType.Companion.toMediaTypeOrNull
32
32
import okhttp3.RequestBody
33
33
import okio.BufferedSink
34
+ import okio.Source
34
35
import okio.source
36
+ import timber.log.Timber
35
37
import java.io.IOException
36
38
37
39
class ContentUriRequestBody (
38
40
private val contentResolver : ContentResolver ,
39
41
private val contentUri : Uri
40
- ) : RequestBody() {
42
+ ) : RequestBody(), ProgressiveDataTransferer {
43
+
44
+ private val dataTransferListeners: MutableSet <OnDatatransferProgressListener > = HashSet ()
45
+
46
+ val fileSize: Long = contentResolver.query(contentUri, null , null , null , null )?.use { cursor ->
47
+ val sizeIndex = cursor.getColumnIndex(OpenableColumns .SIZE )
48
+ cursor.moveToFirst()
49
+ cursor.getLong(sizeIndex)
50
+ } ? : - 1
41
51
42
52
override fun contentType (): MediaType ? {
43
53
val contentType = contentResolver.getType(contentUri) ? : return null
44
54
return contentType.toMediaTypeOrNull()
45
55
}
46
56
47
57
override fun contentLength (): Long {
48
- contentResolver.query(contentUri, null , null , null , null )?.use { cursor ->
49
- val sizeIndex = cursor.getColumnIndex(OpenableColumns .SIZE )
50
- cursor.moveToFirst()
51
- return cursor.getLong(sizeIndex)
52
- } ? : return - 1
58
+ return fileSize
53
59
}
54
60
55
61
override fun writeTo (sink : BufferedSink ) {
56
62
val inputStream = contentResolver.openInputStream(contentUri)
57
63
? : throw IOException (" Couldn't open content URI for reading: $contentUri " )
58
64
59
- inputStream.source().use { source ->
60
- sink.writeAll(source)
65
+ val previousTime = System .currentTimeMillis()
66
+
67
+ sink.writeAndUpdateProgress(inputStream.source())
68
+ inputStream.source().close()
69
+
70
+ val laterTime = System .currentTimeMillis()
71
+
72
+ Timber .d(" Difference - ${laterTime - previousTime} milliseconds" )
73
+ }
74
+
75
+ private fun BufferedSink.writeAndUpdateProgress (source : Source ) {
76
+ var iterator: Iterator <OnDatatransferProgressListener >
77
+
78
+ try {
79
+ var totalBytesRead = 0L
80
+ var read: Long
81
+ while (source.read(this .buffer, BYTES_TO_READ ).also { read = it } != - 1L ) {
82
+ totalBytesRead + = read
83
+ this .flush()
84
+ synchronized(dataTransferListeners) {
85
+ iterator = dataTransferListeners.iterator()
86
+ while (iterator.hasNext()) {
87
+ iterator.next().onTransferProgress(read, totalBytesRead, fileSize, contentUri.toString())
88
+ }
89
+ }
90
+ }
91
+ } catch (e: Exception ) {
92
+ Timber .e(e)
61
93
}
62
94
}
95
+
96
+ override fun addDatatransferProgressListener (listener : OnDatatransferProgressListener ) {
97
+ synchronized(dataTransferListeners) {
98
+ dataTransferListeners.add(listener)
99
+ }
100
+ }
101
+
102
+ override fun addDatatransferProgressListeners (listeners : MutableCollection <OnDatatransferProgressListener >) {
103
+ synchronized(dataTransferListeners) {
104
+ dataTransferListeners.addAll(listeners)
105
+ }
106
+ }
107
+
108
+ override fun removeDatatransferProgressListener (listener : OnDatatransferProgressListener ) {
109
+ synchronized(dataTransferListeners) {
110
+ dataTransferListeners.remove(listener)
111
+ }
112
+ }
113
+
114
+ companion object {
115
+ private const val BYTES_TO_READ = 4_096L
116
+ }
63
117
}
0 commit comments