@@ -7,12 +7,18 @@ import android.net.Uri
7
7
import android.os.Environment
8
8
import android.provider.DocumentsContract
9
9
import android.provider.MediaStore
10
+ import android.provider.OpenableColumns
10
11
import androidx.annotation.Keep
12
+ import com.nareshchocha.filepickerlibrary.utilities.appConst.Const
11
13
import com.nareshchocha.filepickerlibrary.utilities.extentions.isDownloadsDocument
12
14
import com.nareshchocha.filepickerlibrary.utilities.extentions.isExternalStorageDocument
15
+ import com.nareshchocha.filepickerlibrary.utilities.extentions.isGoogleDriveUri
13
16
import com.nareshchocha.filepickerlibrary.utilities.extentions.isGooglePhotosUri
14
17
import com.nareshchocha.filepickerlibrary.utilities.extentions.isMediaDocument
18
+ import timber.log.Timber
15
19
import java.io.File
20
+ import java.io.FileOutputStream
21
+ import java.io.InputStream
16
22
17
23
@Keep
18
24
internal object FileUtils {
@@ -32,30 +38,38 @@ internal object FileUtils {
32
38
}
33
39
34
40
uri.isDownloadsDocument() -> {
35
- context.getDownloadsDocumentPath(uri)
41
+ context.getDownloadsDocumentPath(uri) ? : context.copyFileToInternalStorage(
42
+ uri
43
+ )
36
44
}
37
45
38
46
uri.isMediaDocument() -> {
39
- context.getMediaDocumentPath(uri)
47
+ context.getMediaDocumentPath(uri) ? : context.copyFileToInternalStorage(uri)
40
48
}
41
49
42
50
else -> {
43
- null
51
+ context.copyFileToInternalStorage(uri)
44
52
}
45
53
}
46
54
}
47
55
56
+ uri.isGoogleDriveUri() -> {
57
+ context.getDriveFilePath(uri);
58
+ }
59
+
48
60
" content" .equals(uri.scheme, ignoreCase = true ) -> {
49
61
// Return the remote address
50
62
if (uri.isGooglePhotosUri()) {
51
63
uri.lastPathSegment
64
+ } else if (uri.isGoogleDriveUri()) {
65
+ return context.getDriveFilePath(uri);
52
66
} else {
53
67
getDataColumn(
54
68
context,
55
69
uri,
56
70
null ,
57
71
null ,
58
- )
72
+ ) ? : context.copyFileToInternalStorage(uri)
59
73
}
60
74
}
61
75
@@ -64,9 +78,99 @@ internal object FileUtils {
64
78
}
65
79
66
80
else -> {
67
- null
81
+ context.copyFileToInternalStorage(uri)
82
+ }
83
+ }
84
+ }
85
+
86
+
87
+ /* **
88
+ * Used for Android Q+
89
+ * @param uri
90
+ * @param newDirName if you want to create a directory, you can set this variable
91
+ * @return
92
+ */
93
+ private fun Context.copyFileToInternalStorage (
94
+ uri : Uri ? ,
95
+ newDirName : String = Const .copyFileFolder
96
+ ): String? {
97
+ if (uri == null ) {
98
+ return null
99
+ }
100
+ val returnCursor: Cursor ? = this .contentResolver.query(
101
+ uri, arrayOf(
102
+ OpenableColumns .DISPLAY_NAME , OpenableColumns .SIZE
103
+ ), null , null , null
104
+ )
105
+ val nameIndex = returnCursor?.getColumnIndex(OpenableColumns .DISPLAY_NAME ) ? : return null
106
+ returnCursor.moveToFirst()
107
+ val name = returnCursor.getString(nameIndex)
108
+ val output: File = if (newDirName != " " ) {
109
+ val dir = File (cacheDir, newDirName)
110
+ if (! dir.exists()) {
111
+ dir.mkdir()
112
+ }
113
+ File (cacheDir, " $newDirName /$name " )
114
+ } else {
115
+ File (cacheDir, " /$name " )
116
+ }
117
+ try {
118
+ val inputStream: InputStream ? = contentResolver.openInputStream(uri)
119
+ val outputStream = FileOutputStream (output)
120
+ var read: Int? = 0
121
+ val bufferSize = 1024
122
+ val buffers = ByteArray (bufferSize)
123
+ while (inputStream?.read(buffers).also { read = it } != - 1 ) {
124
+ read?.let { outputStream.write(buffers, 0 , it) }
68
125
}
126
+ inputStream?.close()
127
+ outputStream.close()
128
+ } catch (e: Exception ) {
129
+ output.delete()
130
+ Timber .tag(" Exception" ).e(e.message!! )
131
+ return null
69
132
}
133
+ return output.path
134
+ }
135
+
136
+
137
+ private fun Context.getDriveFilePath (uri : Uri ): String? {
138
+ val returnCursor: Cursor ? = contentResolver.query(
139
+ uri,
140
+ null ,
141
+ null ,
142
+ null ,
143
+ null
144
+ )
145
+ /*
146
+ * Get the column indexes of the data in the Cursor,
147
+ * * move to the first row in the Cursor, get the data,
148
+ * * and display it.
149
+ * */
150
+ val nameIndex = returnCursor?.getColumnIndex(OpenableColumns .DISPLAY_NAME ) ? : return null
151
+ returnCursor.moveToFirst()
152
+ val name = returnCursor.getString(nameIndex)
153
+ val file = File (cacheDir, name)
154
+ try {
155
+ val inputStream: InputStream ? = contentResolver.openInputStream(uri)
156
+ val outputStream = FileOutputStream (file)
157
+ var read: Int? = 0
158
+ val maxBufferSize = 1 * 1024 * 1024
159
+ val bytesAvailable = inputStream?.available() ? : 0
160
+
161
+ // int bufferSize = 1024;
162
+ val bufferSize = bytesAvailable.coerceAtMost(maxBufferSize)
163
+ val buffers = ByteArray (bufferSize)
164
+ while (inputStream?.read(buffers).also { read = it } != - 1 ) {
165
+ read?.let { outputStream.write(buffers, 0 , it) }
166
+ }
167
+ inputStream?.close()
168
+ outputStream.close()
169
+ } catch (e: Exception ) {
170
+ Timber .tag(" Exception" ).e(e.message)
171
+ return null
172
+ }
173
+ return file.path
70
174
}
71
175
72
176
@Keep
@@ -88,6 +192,10 @@ internal object FileUtils {
88
192
" audio" -> {
89
193
contentUri = MediaStore .Audio .Media .EXTERNAL_CONTENT_URI
90
194
}
195
+
196
+ else -> {
197
+ contentUri = MediaStore .Audio .Media .EXTERNAL_CONTENT_URI
198
+ }
91
199
}
92
200
val selection = " _id=?"
93
201
val selectionArgs = arrayOf(
@@ -109,11 +217,23 @@ internal object FileUtils {
109
217
val file = File (id)
110
218
if (file.exists()) return id
111
219
}
112
- val contentUri = ContentUris .withAppendedId (
113
- Uri .parse( " content://downloads/public_downloads" ) ,
114
- java.lang. Long .valueOf(id),
220
+ val contentUriPrefixesToTry = arrayOf (
221
+ " content://downloads/public_downloads" ,
222
+ " content://downloads/my_downloads "
115
223
)
116
- return getDataColumn(this , contentUri, null , null )
224
+ for (contentUriPrefix in contentUriPrefixesToTry) {
225
+ return try {
226
+ val contentUri = ContentUris .withAppendedId(
227
+ Uri .parse(contentUriPrefix),
228
+ java.lang.Long .valueOf(id)
229
+ )
230
+ getDataColumn(this , contentUri, null , null )
231
+ } catch (e: NumberFormatException ) {
232
+ // In Android 8 and Android P the id is not a number
233
+ uri.path!! .replaceFirst(" ^/document/raw:" , " " ).replaceFirst(" ^raw:" , " " )
234
+ }
235
+ }
236
+ return null
117
237
}
118
238
119
239
@Keep
@@ -157,6 +277,8 @@ internal object FileUtils {
157
277
selectionArgs,
158
278
null ,
159
279
)
280
+ Timber .tag(" Checked:" ).d(" cursor:: %s" , cursor)
281
+
160
282
if (cursor != null && cursor.moveToFirst()) {
161
283
val index = cursor.getColumnIndexOrThrow(column)
162
284
return cursor.getString(index)
0 commit comments