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

前端 未结 4 1688
遥遥无期
遥遥无期 2021-02-03 11:05

I want to load all the pictures from the galley to my app by using MediaStore.MediaColumns.DATA , but it is deprecated. So, what is the other way to load them?

I use this

相关标签:
4条回答
  • 2021-02-03 11:18

    Loading images from internal store.Reading all folders which has images and videos using MediaStore class.

    And returning result as ArrayList.

    private fun getAllShownImagesPath(activity: Activity): ArrayList<Albums> {
    
    val uri: Uri
    val cursor: Cursor
    var cursorBucket: Cursor
    val column_index_data: Int
    val column_index_folder_name: Int
    val listOfAllImages = ArrayList<String>()
    var absolutePathOfImage: String? = null
    var albumsList = ArrayList<Albums>()
    var album: Albums? = null
    
    
    val BUCKET_GROUP_BY = "1) GROUP BY 1,(2"
    val BUCKET_ORDER_BY = "MAX(datetaken) DESC"
    
    uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    
    val projection = arrayOf(MediaStore.Images.ImageColumns.BUCKET_ID,
            MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DATE_TAKEN,
            MediaStore.Images.ImageColumns.DATA)
    
    cursor = activity.contentResolver.query(uri, projection, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY)
    
    if (cursor != null) {
        column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
        column_index_folder_name = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
        while (cursor.moveToNext()) {
            absolutePathOfImage = cursor.getString(column_index_data)
            Log.d("title_apps", "bucket name:" + cursor.getString(column_index_data))
    
            val selectionArgs = arrayOf("%" + cursor.getString(column_index_folder_name) + "%")
            val selection = MediaStore.Images.Media.DATA + " like ? "
            val projectionOnlyBucket = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
    
            cursorBucket = activity.contentResolver.query(uri, projectionOnlyBucket, selection, selectionArgs, null)
            Log.d("title_apps", "bucket size:" + cursorBucket.count)
    
            if (absolutePathOfImage != "" && absolutePathOfImage != null) {
                listOfAllImages.add(absolutePathOfImage)
                albumsList.add(Albums(cursor.getString(column_index_folder_name), absolutePathOfImage, cursorBucket.count, false))
            }
        }
    }
    return getListOfVideoFolders(albumsList)
    }
    

    // This function is resposible to read all videos from all folders.

    private fun getListOfVideoFolders(albumsList: ArrayList<Albums>): ArrayList<Albums> {
    var cursor: Cursor
    var cursorBucket: Cursor
    var uri: Uri
    val BUCKET_GROUP_BY = "1) GROUP BY 1,(2"
    val BUCKET_ORDER_BY = "MAX(datetaken) DESC"
    val column_index_album_name: Int
    val column_index_album_video: Int
    
    uri = android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI
    
    val projection1 = arrayOf(MediaStore.Video.VideoColumns.BUCKET_ID,
            MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Video.VideoColumns.DATE_TAKEN,
            MediaStore.Video.VideoColumns.DATA)
    
    cursor = this.contentResolver.query(uri, projection1, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY)
    
    if (cursor != null) {
        column_index_album_name = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
        column_index_album_video = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
        while (cursor.moveToNext()) {
            Log.d("title_apps", "bucket video:" + cursor.getString(column_index_album_name))
            Log.d("title_apps", "bucket video:" + cursor.getString(column_index_album_video))
            val selectionArgs = arrayOf("%" + cursor.getString(column_index_album_name) + "%")
    
            val selection = MediaStore.Video.Media.DATA + " like ? "
            val projectionOnlyBucket = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
    
            cursorBucket = this.contentResolver.query(uri, projectionOnlyBucket, selection, selectionArgs, null)
            Log.d("title_apps", "bucket size:" + cursorBucket.count)
    
            albumsList.add(Albums(cursor.getString(column_index_album_name), cursor.getString(column_index_album_video), cursorBucket.count, true))
        }
    }
    return albumsList
    }
    
    0 讨论(0)
  • 2021-02-03 11:23

    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

    0 讨论(0)
  • 2021-02-03 11:25

    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!

    0 讨论(0)
  • 2021-02-03 11:26

    I finally solved the problem by creating this class

    class FileHelper {
    val mediaType = "multipart/form-data".toMediaTypeOrNull()
    
    fun getPartBodyFromUri(context: Context, uri: Uri): MultipartBody.Part {
        val realPath = getPathFromURI(context, uri)
        val fileImage = createFile(realPath)
        val requestBody = createRequestBody(fileImage)
        return createPart(fileImage, requestBody)
    }
    
    private fun createFile(realPath: String): File {
        return File(realPath)
    }
    
    private fun createRequestBody(file: File): RequestBody {
        return file.asRequestBody(mediaType)
    }
    
    private fun createPart(file: File, requestBody: RequestBody): MultipartBody.Part {
        return MultipartBody.Part.createFormData("imageFile", file.name, requestBody)
    }
    
    private fun getPathFromURI(context: Context, uri: Uri): String {
        var realPath = String()
        uri.path?.let { path ->
    
            val databaseUri: Uri
            val selection: String?
            val selectionArgs: Array<String>?
            if (path.contains("/document/image:")) { // files selected from "Documents"
                databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                selection = "_id=?"
                selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
            } else { // files selected from all other sources, especially on Samsung devices
                databaseUri = uri
                selection = null
                selectionArgs = null
            }
            try {
                val column = "_data"
                val projection = arrayOf(column)
                val cursor = context.contentResolver.query(
                    databaseUri,
                    projection,
                    selection,
                    selectionArgs,
                    null
                )
                cursor?.let {
                    if (it.moveToFirst()) {
                        val columnIndex = cursor.getColumnIndexOrThrow(column)
                        realPath = cursor.getString(columnIndex)
                    }
                    cursor.close()
                }
            } catch (e: Exception) {
                println(e)
            }
        }
        return realPath
    }
    

    }

    Media.DATA it's deprecate and "MediaStore.Images.Media._ID" to get the correct column, not working so I create column I need

    val column = "_data"
    val projection = arrayOf(column)
    

    then I use getColumnIndexOrThrow() method to get correct index

    val columnIndex = cursor.getColumnIndexOrThrow(column)
    realPath = cursor.getString(columnIndex)
    
    0 讨论(0)
提交回复
热议问题