Skip to content

Instantly share code, notes, and snippets.

@imandaliya
Last active May 4, 2023 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imandaliya/230e510dc82ddae53040581b5964dac3 to your computer and use it in GitHub Desktop.
Save imandaliya/230e510dc82ddae53040581b5964dac3 to your computer and use it in GitHub Desktop.
// https://stackoverflow.com/questions/66280961/contentresolver-query-method-throws-invalid-token-limit-error
// https://stackoverflow.com/questions/58601599/illegalargumentexception-invalid-column-distinct-bucket-display-name
// https://stackoverflow.com/questions/10390577/limiting-number-of-rows-in-a-contentresolver-query-function
// https://code.luasoftware.com/tutorials/android/android-find-albums-in-photo-gallery
// Cursor with limit call
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import androidx.annotation.RequiresApi
import androidx.core.database.getLongOrNull
import androidx.core.database.getStringOrNull
data class MediaItem(
val id: Long,
val contentUri: Uri,
val data: String?,
val mimeType: String?,
val duration: Long?
)
private fun fetchGalleryImages(
context: Context,
orderBy: String,
orderAscending: Boolean,
limit: Int = 20,
offset: Int = 0
): List<MediaItem> {
val galleryImageUrls = mutableListOf<MediaItem>()
val collection = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE,
MediaStore.Video.Media.DURATION
)
val whereCondition = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?"
val selectionArgs = arrayOf(
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
)
createCursor(
contentResolver = context.contentResolver,
collection = collection,
projection = projection,
whereCondition = whereCondition,
selectionArgs = selectionArgs,
orderBy = orderBy,
orderAscending = orderAscending,
limit = limit,
offset = offset
)?.use { cursor ->
while (cursor.moveToNext()) {
val idIndex = cursor.getColumnIndex(MediaStore.Audio.Media._ID)
if (idIndex < 0) continue
val id = cursor.getLong(idIndex)
galleryImageUrls.add(
MediaItem(
id = id,
contentUri = ContentUris.withAppendedId(collection, id),
data = cursor.getStringOrNull(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)),
mimeType = cursor.getStringOrNull(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE)),
duration = cursor.getLongOrNull(cursor.getColumnIndex(MediaStore.Video.Media.DURATION))
)
)
}
}
return galleryImageUrls
}
private fun createCursor(
contentResolver: ContentResolver,
collection: Uri,
projection: Array<String>,
whereCondition: String,
selectionArgs: Array<String>,
orderBy: String,
orderAscending: Boolean,
limit: Int = 20,
offset: Int = 0
): Cursor? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
val selection = createSelectionBundle(whereCondition, selectionArgs, orderBy, orderAscending, limit, offset)
contentResolver.query(collection, projection, selection, null)
}
else -> {
val orderDirection = if (orderAscending) "ASC" else "DESC"
var order = when (orderBy) {
"ALPHABET" -> "${MediaStore.Audio.Media.TITLE}, ${MediaStore.Audio.Media.ARTIST} $orderDirection"
else -> "${MediaStore.Audio.Media.DATE_ADDED} $orderDirection"
}
order += " LIMIT $limit OFFSET $offset"
contentResolver.query(collection, projection, whereCondition, selectionArgs, order)
}
}
@RequiresApi(Build.VERSION_CODES.O)
fun createSelectionBundle(
whereCondition: String,
selectionArgs: Array<String>,
orderBy: String,
orderAscending: Boolean,
limit: Int = 20,
offset: Int = 0
): Bundle = Bundle().apply {
// Limit & Offset
putInt(ContentResolver.QUERY_ARG_LIMIT, limit)
putInt(ContentResolver.QUERY_ARG_OFFSET, offset)
// Sort function
when (orderBy) {
"ALPHABET" -> putStringArray(ContentResolver.QUERY_ARG_SORT_COLUMNS, arrayOf(MediaStore.Files.FileColumns.TITLE))
else -> putStringArray(ContentResolver.QUERY_ARG_SORT_COLUMNS, arrayOf(MediaStore.Files.FileColumns.DATE_ADDED))
}
// Sorting direction
val orderDirection =
if (orderAscending) ContentResolver.QUERY_SORT_DIRECTION_ASCENDING else ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
putInt(ContentResolver.QUERY_ARG_SORT_DIRECTION, orderDirection)
// Selection
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, whereCondition)
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment