Store Image via Android Media Store in new Folder

Viewed 3807

I am using the following to store images created in my app in the gallery of Android:

    MediaStore.Images.Media.insertImage(contentResolver, bitmap, "SomeTitle", "Description");

This will store the images in the Picture-Device-Folder and add them to the Gallery.

I now want to create a specific image folder for my app, so that images are stored in the folder "MyApp" instead of "Picture". How can I do that?

1 Answers

I found the solution hidden here: https://stackoverflow.com/a/57265702/289782

I will quote it here since the original question is rather old and the great answer by User Bao Lei is ranked rather low.

There were several different ways to do it before API 29 (Android Q) but all of them involved one or a few APIs that are deprecated with Q. In 2019, here's a way to do it that is both backward and forward compatible:

(And since it is 2019 so I will write in Kotlin)

/// @param folderName can be your app's name
private fun saveImage(bitmap: Bitmap, context: Context, folderName: String) {
    if (android.os.Build.VERSION.SDK_INT >= 29) {
        val values = contentValues()
        values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + folderName)
        values.put(MediaStore.Images.Media.IS_PENDING, true)
        // RELATIVE_PATH and IS_PENDING are introduced in API 29.

        val uri: Uri? = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        if (uri != null) {
            saveImageToStream(bitmap, context.contentResolver.openOutputStream(uri))
            values.put(MediaStore.Images.Media.IS_PENDING, false)
            context.contentResolver.update(uri, values, null, null)
        }
    } else {
        val directory = File(Environment.getExternalStorageDirectory().toString() + separator + folderName)
        // getExternalStorageDirectory is deprecated in API 29

        if (!directory.exists()) {
            directory.mkdirs()
        }
        val fileName = System.currentTimeMillis().toString() + ".png"
        val file = File(directory, fileName)
        saveImageToStream(bitmap, FileOutputStream(file))
        if (file.absolutePath != null) {
            val values = contentValues()
            values.put(MediaStore.Images.Media.DATA, file.absolutePath)
            // .DATA is deprecated in API 29
            context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        }
    }
}

private fun contentValues() : ContentValues {
    val values = ContentValues()
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/png")
    values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
    return values
}

private fun saveImageToStream(bitmap: Bitmap, outputStream: OutputStream?) {
    if (outputStream != null) {
        try {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
            outputStream.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

Also, before calling this, you need to have WRITE_EXTERNAL_STORAGE first.

Related