Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MediaStore.MediaColumns.DATA is deprecated, and I want to load images from gallery to my app

Tags:

I want to load all the pictures from the media provider to my app by using MediaStore API, but this column MediaStore.MediaColumns.DATA is deprecated. So, what can I use as an alternative?

I want to update the following code to get rid of the deprecated MediaStore.MediaColumns.DATA column:

fun ContentResolver.loadImagesPaths(): List<String> {
    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val images = mutableListOf<String>()
    val projection = arrayOf(MediaStore.MediaColumns.DATA)
    query(uri, projection, null, null, null)?.use { cursor ->
        val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
        while (cursor.moveToNext()) {
            images += cursor.getString(dataColumn)
        }
    }
    return images
}

Edit:

Updated code:

fun ContentResolver.loadImagesUris(): List<Uri> {
    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val images = mutableListOf<Uri>()
    val projection = arrayOf(MediaStore.Images.Media._ID)
    query(uri, projection, null, null, null)?.use { cursor ->
        val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
        while (cursor.moveToNext()) {
            images += ContentUris.withAppendedId(uri, cursor.getLong(idColumn))
        }
    }
    return images
}

Check out this link for further details on how to access media files from shared storage: https://developer.android.com/training/data-storage/shared/media

like image 869
Said Oubella Avatar asked Aug 28 '19 05:08

Said Oubella


People also ask

Is MediaStore deprecated?

The filesystem and mediastore modules are deprecated. You should use the new storage module which is relying on Okio Filesystem API. On Android, every files on the shared storage (files visible when using a file manager) are indexed by MediaStore, to allow apps to query them by type, date, size, etc.

What is Bucket display name?

// BUCKET_DISPLAY_NAME is a string like "Camera" which is the directory // name of where an image or video is in.


2 Answers

I was able to replace MediaStore.MediaColumns.Data with its own file ID (incredibly, files have IDs) and correctly constructing its URI, like this:

fun getAllShownImagesPath(activity: Activity): MutableList<Uri> {
    val uriExternal: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val cursor: Cursor?
    val columnIndexID: Int
    val listOfAllImages: MutableList<Uri> = mutableListOf()
    val projection = arrayOf(MediaStore.Images.Media._ID)
    var imageId: Long
    cursor = activity.contentResolver.query(uriExternal, projection, null, null, null)
    if (cursor != null) {
        columnIndexID = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
        while (cursor.moveToNext()) {
            imageId = cursor.getLong(columnIndexID)
            val uriImage = Uri.withAppendedPath(uriExternal, "" + imageId)
            listOfAllImages.add(uriImage)
        }
        cursor.close()
    }
    return listOfAllImages
}

and then with Uri you build it in your Views!

like image 133
Daniel Bentes Avatar answered Sep 17 '22 19:09

Daniel Bentes


I managed to come up with the following solution, its kind of an addition to the previous answer

but there I still couldn't load images with the obtained Uri. Documentation suggested to use openFileDescriptor() which I did and then decoded images' bitmaps from it:

override fun loadImagesFromStorage(): List<AdapterImage> {

    val uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val cursor: Cursor?
    val columnIndexId: Int
    val listOfAllImages = mutableListOf<AdapterImage>()
    val projection = arrayOf(MediaStore.Images.Media._ID)
    cursor = context.contentResolver
        .query( uri, projection, null, null, null)

    if ( cursor != null ){
        columnIndexId = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
        while (cursor.moveToNext()){

            val contentUri = ContentUris.withAppendedId(uri, cursor.getLong(columnIndexId))

            //here I open FileDescriptor and then decode it into Bitmap
            var image: Bitmap
            context.contentResolver.openFileDescriptor(contentUri, "r").use { pfd ->
                if( pfd != null ){
                    image = BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor)
                    listOfAllImages.add(AdapterImage(image))
                }
            }

        }
        cursor.close()
    }

    return listOfAllImages
}

P.S. My method will return a list of AdapterImage objects that I use later in app but you can put anything you need there at this point

like image 35
Daniil Antsyferov Avatar answered Sep 21 '22 19:09

Daniil Antsyferov