@@ -46,7 +46,8 @@ internal class MediaStoreFile @JvmOverloads constructor(
4646 private val context : Context ,
4747 private val path : String , // relative to rootDir
4848 private val rootDir : String = context.packageName,
49- private val publicDirType : String = Environment .DIRECTORY_DOCUMENTS
49+ private val publicDirType : String = Environment .DIRECTORY_DOCUMENTS ,
50+ private val mimeType : String = " application/octet-stream" // generic file, only for Documents/Download
5051) {
5152 private var cachedUri: Uri ? = null
5253
@@ -73,18 +74,18 @@ internal class MediaStoreFile @JvmOverloads constructor(
7374 private fun findUri (): Uri ? {
7475 if (cachedUri != null ) return cachedUri
7576
76- val projection = arrayOf(MediaStore .Files . FileColumns ._ID )
77+ val projection = arrayOf(MediaStore .MediaColumns ._ID )
7778
7879 val selection =
79- " ${MediaStore .Files . FileColumns . DISPLAY_NAME } =? AND ${MediaStore .Files . FileColumns .RELATIVE_PATH } =?"
80+ " ${MediaStore .MediaColumns . DISPLAY_NAME } =? AND ${MediaStore .MediaColumns .RELATIVE_PATH } =?"
8081
8182 val selectionArgs = arrayOf(
8283 name(),
8384 relativePath() + " /"
8485 )
8586
8687 resolver.query(
87- MediaStore . Files .getContentUri( " external " ),
88+ collectionUri( ),
8889 projection,
8990 selection,
9091 selectionArgs,
@@ -93,7 +94,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
9394 if (cursor.moveToFirst()) {
9495 val id = cursor.getLong(0 )
9596 cachedUri = Uri .withAppendedPath(
96- MediaStore . Files .getContentUri( " external " ),
97+ collectionUri( ),
9798 id.toString()
9899 )
99100 return cachedUri
@@ -112,16 +113,16 @@ internal class MediaStoreFile @JvmOverloads constructor(
112113 * So if you want a folder to “exist” even if it’s empty, you create a hidden placeholder file called .dir inside that folder.
113114 */
114115 fun isDirectory (): Boolean {
115- val dirMarker = MediaStoreFile (context, " $path /.dir" , rootDir)
116+ val dirMarker = MediaStoreFile (context, " $path /.dir" , rootDir, publicDirType )
116117 if (dirMarker.exists()) return true
117118
118- val projection = arrayOf(MediaStore .Files . FileColumns ._ID )
119+ val projection = arrayOf(MediaStore .MediaColumns ._ID )
119120 val selection =
120- " ${MediaStore .Files . FileColumns .RELATIVE_PATH } LIKE ?"
121+ " ${MediaStore .MediaColumns .RELATIVE_PATH } LIKE ?"
121122 val selectionArgs = arrayOf(fullRelativeDir() + " /%" )
122123
123124 resolver.query(
124- MediaStore . Files .getContentUri( " external " ),
125+ collectionUri( ),
125126 projection,
126127 selection,
127128 selectionArgs,
@@ -137,13 +138,13 @@ internal class MediaStoreFile @JvmOverloads constructor(
137138 if (exists()) return false
138139
139140 val values = ContentValues ().apply {
140- put(MediaStore .Files . FileColumns .DISPLAY_NAME , name())
141- put(MediaStore .Files . FileColumns . MIME_TYPE , " application/octet-stream " )
142- put(MediaStore .Files . FileColumns .RELATIVE_PATH , relativePath())
141+ put(MediaStore .MediaColumns .DISPLAY_NAME , name())
142+ put(MediaStore .MediaColumns . MIME_TYPE , mimeType )
143+ put(MediaStore .MediaColumns .RELATIVE_PATH , relativePath())
143144 }
144145
145146 val uri = resolver.insert(
146- MediaStore . Files .getContentUri( " external " ),
147+ collectionUri( ),
147148 values
148149 )
149150
@@ -160,7 +161,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
160161 for (part in parts) {
161162 if (part.isEmpty()) continue
162163 current = if (current.isEmpty()) part else " $current /$part "
163- val dummy = MediaStoreFile (context, " $current /.dir" , rootDir)
164+ val dummy = MediaStoreFile (context, " $current /.dir" , rootDir, publicDirType )
164165 if (! dummy.exists()) {
165166 dummy.createNewFile()
166167 }
@@ -178,18 +179,18 @@ internal class MediaStoreFile @JvmOverloads constructor(
178179 val list = mutableListOf<MediaStoreFile >()
179180
180181 val projection = arrayOf(
181- MediaStore .Files . FileColumns .DISPLAY_NAME
182+ MediaStore .MediaColumns .DISPLAY_NAME
182183 )
183184
184185 val selection =
185- " ${MediaStore .Files . FileColumns .RELATIVE_PATH } =?"
186+ " ${MediaStore .MediaColumns .RELATIVE_PATH } =?"
186187
187188 val selectionArgs = arrayOf(
188189 fullRelativeDir() + " /"
189190 )
190191
191192 resolver.query(
192- MediaStore . Files .getContentUri( " external " ),
193+ collectionUri( ),
193194 projection,
194195 selection,
195196 selectionArgs,
@@ -198,7 +199,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
198199 while (cursor.moveToNext()) {
199200 val fileName = cursor.getString(0 )
200201 if (fileName != " .dir" ) {
201- list.add(MediaStoreFile (context, " $path /$fileName " , rootDir))
202+ list.add(MediaStoreFile (context, " $path /$fileName " , rootDir, publicDirType ))
202203 }
203204 }
204205 }
@@ -258,9 +259,9 @@ internal class MediaStoreFile @JvmOverloads constructor(
258259 */
259260 fun child (name : String ): MediaStoreFile {
260261 return if (path.isEmpty())
261- MediaStoreFile (context, name, rootDir)
262+ MediaStoreFile (context, name, rootDir, publicDirType )
262263 else
263- MediaStoreFile (context, " $path /$name " , rootDir)
264+ MediaStoreFile (context, " $path /$name " , rootDir, publicDirType )
264265 }
265266
266267 fun resolve (): String {
@@ -284,8 +285,8 @@ internal class MediaStoreFile @JvmOverloads constructor(
284285 val uri = findUri() ? : return false
285286
286287 val values = ContentValues ().apply {
287- put(MediaStore .Files . FileColumns .DISPLAY_NAME , dest.name())
288- put(MediaStore .Files . FileColumns .RELATIVE_PATH , dest.relativePath())
288+ put(MediaStore .MediaColumns .DISPLAY_NAME , dest.name())
289+ put(MediaStore .MediaColumns .RELATIVE_PATH , dest.relativePath())
289290 }
290291
291292 val updated = resolver.update(uri, values, null , null ) > 0
@@ -297,7 +298,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
297298
298299 fun length (): Long {
299300 val uri = findUri() ? : return 0
300- val projection = arrayOf(MediaStore .Files . FileColumns .SIZE )
301+ val projection = arrayOf(MediaStore .MediaColumns .SIZE )
301302
302303 resolver.query(uri, projection, null , null , null )?.use { cursor ->
303304 if (cursor.moveToFirst()) {
@@ -311,7 +312,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
311312
312313 fun lastModified (): Long {
313314 val uri = findUri() ? : return 0
314- val projection = arrayOf(MediaStore .Files . FileColumns .DATE_MODIFIED )
315+ val projection = arrayOf(MediaStore .MediaColumns .DATE_MODIFIED )
315316
316317 resolver.query(uri, projection, null , null , null )?.use { cursor ->
317318 if (cursor.moveToFirst()) {
@@ -325,7 +326,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
325326 val uri = findUri() ? : return false
326327
327328 val values = ContentValues ().apply {
328- put(MediaStore .Files . FileColumns .DATE_MODIFIED , timeMillis / 1000 ) // seconds
329+ put(MediaStore .MediaColumns .DATE_MODIFIED , timeMillis / 1000 ) // seconds
329330 }
330331
331332 val updated = resolver.update(uri, values, null , null ) > 0
@@ -337,7 +338,7 @@ internal class MediaStoreFile @JvmOverloads constructor(
337338 */
338339 fun getStoredName (): String? {
339340 val uri = findUri() ? : return null
340- val projection = arrayOf(MediaStore .Files . FileColumns .DISPLAY_NAME )
341+ val projection = arrayOf(MediaStore .MediaColumns .DISPLAY_NAME )
341342 resolver.query(uri, projection, null , null , null )?.use { cursor ->
342343 if (cursor.moveToFirst()) return cursor.getString(0 )
343344 }
@@ -380,4 +381,17 @@ internal class MediaStoreFile @JvmOverloads constructor(
380381 false
381382 }
382383 }
384+
385+ private fun collectionUri (): Uri {
386+ return when (publicDirType) {
387+ Environment .DIRECTORY_MUSIC ->
388+ MediaStore .Audio .Media .EXTERNAL_CONTENT_URI
389+ Environment .DIRECTORY_MOVIES ->
390+ MediaStore .Video .Media .EXTERNAL_CONTENT_URI
391+ Environment .DIRECTORY_PICTURES ->
392+ MediaStore .Images .Media .EXTERNAL_CONTENT_URI
393+ else ->
394+ MediaStore .Files .getContentUri(" external" )
395+ }
396+ }
383397}
0 commit comments