Search code examples
androidkotlinfileoutputstream

Android Change the Gallery Album name of stored Images


I am trying to save images to an album with the app name inside the gallery, so far I managed to save the image into the gallery but the problem is that the album name is always "Pictures", I've checked all of the other posts out there and nothing worked for me...

here is my code

val fileName = "abc"
val ImageToSave /*the image that I save, I send it value through method*/

val imageDir = File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES),"appName")
val image = File(imageDir,fileName)

if (!imageDir.exists())
    imageDir.mkdirs()

val contentValues = ContentValues()
contentValues.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
contentValues.put(MediaStore.Images.Media.DATA, image.absolutePath)
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
contentValues.put(MediaStore.Images.Media.BUCKET_DISPLAY_NAME, "appName")

val url = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)!!
val out = contentResolver.openOutputStream(url)

imageFromView.compress(Bitmap.CompressFormat.JPEG, 100, out)

Toast.makeText(activity, "saved", Toast.LENGTH_SHORT).show()

I am saving the image without any problem I just want to change the album name. thank you in advance...

UPDATE

I tried to just create the image file without the contentValue but it appears that something is wrong with the file I keep getting an error that says "File does not exist" here is my code now

val imageDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "appName")

if (!imageDir.exists())
    imageDir.mkdirs()

val image = File(imageDir, fileName)

if (!image.exists()) {

    val out = FileOutputStream(image)
    ImageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out)

    Toast.makeText(activity, "saved", Toast.LENGTH_SHORT).show()
} else
    Toast.makeText(activity, "Already saved", Toast.LENGTH_SHORT).show()

also, I made sure that I have the ask permission in my manifest file, and I am asking for permission when the user presses on the button... I made sure that my application has permission to read and write to files....


Solution

  • After a lot of research, I was able to find a solution for my problem, all I had to do is add

    put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/AppName/")
    

    this will create a folder with your app name inside the pictures folder, in the gallery, it will appear with the app name you entered... for extra detail read this link

    I found out that a huge chunk of the code that I wrote was not needed,I ended up removing all the extra stuff, this is the end result

    UPDATE

    I've updated the code so it works with the old versions of android as well

    fun saveImage(itemImage: View, context: Context) {
        val imageName: String
        val imageToSave = getBitmapFromView(itemImage)
        val exists: Boolean
    
        ByteArrayOutputStream().apply {
            imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, this)
            imageName = "ChatOut_" + UUID.nameUUIDFromBytes(this.toByteArray()).toString().replace("-", "") + ".jpg"
        }
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,arrayOf(MediaStore.Images.Media.DISPLAY_NAME), "${MediaStore.Images.Media.DISPLAY_NAME} = '$imageName' ", null, MediaStore.Images.ImageColumns.DATE_ADDED + " DESC").let {
                exists = it?.count ?: 0 >= 1
                it?.close()
            }
    
    
            if (!exists) {
                val contentValues = ContentValues().apply {
                    put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
                    put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
                    put(MediaStore.Images.Media.DISPLAY_NAME, imageName)
                    put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/ChatOut/")
                }
    
                val url = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)!!
                val out = context.contentResolver.openOutputStream(url)
                imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out)
    
                 Toast.makeText(context, "saved", Toast.LENGTH_SHORT).show()
            } else
                Toast.makeText(context, "Already saved", Toast.LENGTH_SHORT).show()
        }else{
            val imageDir = File("${Environment.getExternalStorageDirectory()}/ChatOut/")
            if (!imageDir.exists())
                imageDir.mkdirs()
    
            val image = File(imageDir,imageName)
    
            if (!image.exists()){
                val outputStream = FileOutputStream(image)
                imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
                outputStream.close()
    
                val contentValues = ContentValues().apply {
                    put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
                    put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
                    put(MediaStore.Images.Media.DISPLAY_NAME, imageName)
                    put(MediaStore.Images.Media.DATA, image.absolutePath)
                }
    
                context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
    
                Toast.makeText(context, "saved", Toast.LENGTH_SHORT).show()
            }else{
                Toast.makeText(context, "Already saved", Toast.LENGTH_SHORT).show()
            }
        }
    }
    
    fun getBitmapFromView(view: View): Bitmap {
        return Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888).apply {
            Canvas(this).apply {
                view.draw(this)
            }
         }
    }
    

    I hope this helps others :) have a good time!