Android Change the Gallery Album name of stored Images - android

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....

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!

It is because you are using Environment.DIRECTORY_PICTURES
You should create a custom directory instead, here is an example:
String path = Environment.getExternalStorageDirectory().toString();
File appDirectory = new File(path + "/" + "FolderName");
appDirectory.mkdirs();

Related

Copying or moving a file inside Internal storage on Android

In an Android app the user can record his voice. The sound recording is saved in a file defined by:
audioTempFile = File(getFilesDir(), "Audio_Temp_File")
Then I want to give the user the choice of the final folder and file name for the file to be saved.
So the audioTempFile above can be used for a possible next recording without destroying the current one.
For example let us assume I want the file to be saved in this file called finalFile :
val rootDir = getFilesDir()
val storeDir = File(rootDir, "MyStorageDirectory")
val finalFile = File(storeDir, "MyFinalFileName")
How can I move or possibly copy audioTempFile to finalFile?
I did not find any clear answer by searching the net.
I don't know about saving to a specific location, but this is the way I'm saving the recordings in my app.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
try{
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, allFiles[position].name)
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_MUSIC)
val savedAudio = context.contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values)
val outputStream = savedAudio?.let {
context.contentResolver.openOutputStream(it)
}
val fis = FileInputStream(allFiles[position])
var length : Int
val buffer = ByteArray(8192)
while (fis.read(buffer).also { length = it } > 0) {
outputStream?.write(buffer, 0,length)
}
Toast.makeText(context, "Audio Saved to Music Folder", Toast.LENGTH_SHORT).show()
}catch (e : IOException){
Toast.makeText(
context,
"There was an error saving the file",
Toast.LENGTH_SHORT
).show()
e.printStackTrace()
}
}else{
try {
val audioDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
val audio = File(audioDir, allFiles[position].name)
val fis = FileInputStream(allFiles[position])
val fos = FileOutputStream(audio)
var length : Int
val buffer = ByteArray(8192)
while (fis.read(buffer).also { length = it } > 0){
fos.write(buffer,0,length)
}
Toast.makeText(context, "Audio Saved to Music Folder", Toast.LENGTH_SHORT).show()
}catch (e : IOException){
Toast.makeText(
context,
"There was an error saving the file",
Toast.LENGTH_SHORT
).show()
e.printStackTrace()
}
}
You would need MANAGE_EXTERNAL_STORAGE permission if u want to save files other than public directories. It's recommended to use MediaStore API to save your files.
Do correct me if I'm wrong as I'm still learning.
Hope this helps u :)

Delete a image from InternalStorage using ImagePath

I am working with Android version 10.
I have enabled Permissions to Read & Write Storage
Device Name : Poco F1
Scenario: I have to capture a screenshot of the current layout and save it to internalStorage and preview that image to the user. Here users have an option to delete the image.
Here are the codes I am using to save & delete
Saving a screenshot:
//I will pass the bitmap here
fun saveBitmapToInternalStorage(bitmap: Bitmap?) {
bitmap?.let {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
saveBitmapToOlderDevice(it)
} else {
saveBitmapToNewerDevice(it)
}
}
}
//This method is to save image to newerdevice >= Q
#RequiresApi(Build.VERSION_CODES.Q)
private fun saveBitmapToNewerDevice(bitmap: Bitmap) {
val uri = generateUri()
context.contentResolver.openOutputStream(uri ?: return).use { outputStream ->
outputStream?.let {
writeBitmapToJpeg(bitmap, outputStream, uri.toString())
}
}
}
//This is to generate the URI.
#RequiresApi(Build.VERSION_CODES.Q)
private fun generateUri(): Uri? {
val dateFormat = getDateFormat()
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "${dateFormat}.jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/${context.resources.getString(R.string.app_name)}")
}
return context.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
}
// To save images to olderDevice
private fun saveBitmapToOlderDevice(bmp: Bitmap) {
val filename = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)?.absolutePath +
"/${context.resources.getString(R.string.app_name)}/${getDateFormat()}.jpg"
createDirectory(filename)
val outputStream = FileOutputStream(filename)
writeBitmapToJpeg(bmp, outputStream, filename)
}
//This method is to save the image to InternalStorage
private fun writeBitmapToJpeg(bmp: Bitmap, outputStream: OutputStream, imagePath: String) {
try {
val outputData = ByteArrayOutputStream()
bmp.compress(CompressFormat.JPEG, 100, outputData)
outputData.writeTo(outputStream)
outputStream.flush()
outputStream.close()
} catch (e: IOException) {
showBitmapWriteErrorMessage()
}
}
I save the path while storing the image in internalStorgae
the path looks like
/storage/emulated/0/Pictures/TGP AR/20211011142001.jpg
and i pass this path into below method
To delete the image :
private fun deleteImage(imagePath: String) {
val file = File(imagePath)
file.delete()
}
file.exists() is returning true.
file.delete() is returning false.
I think, there might be two different ways to delete ( > & < Q ).
Please help me
You can delete the image by modifying your method to the following:
private fun deleteImage(imagePath: Uri) {
getContentResolver().delete(imagePath, null, null)
}
Then pass the Uri created in generateUri() to delete the file.

How to save a bitmap to external storage(kotlin)?

I am making a project that generates qr code. When user generates a qr code, A download button appears on the screen. If the user clicks this button. Application should save the image(qr code) to external storage. I only want to create a function to save the qr code. But i could not find any useful source. How can i save a bitmap to external storage?
use this function and pass bitmap on button click
from fragment
saveBitmapInStorage(bitmap!!, requireContext())
from activity
saveBitmapInStorage(bitmap!!, this)
main function
open fun saveBitmapInStorage(bitmap: Bitmap, context: Context) {
val filename = "QR_"+"${System.currentTimeMillis()}.jpg"
var fos: OutputStream? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
context.contentResolver?.also { resolver ->
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
}
val imageUri: Uri? =
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
}
} else {
val imagesDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val image = File(imagesDir, filename)
fos = FileOutputStream(image)
}
fos?.use {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
}
}
why I share because I'm using this code in my current project and its working for me
hope helpful for you.

Media Store record Not creating while saving image to Picture Folder in Android 10

So, I need to save image to the Picture folder. There will be some subfolders too. But every time I want to save an image it is giving this error:
Failed to create new mediaStore record
This is what I tried:
#RequiresApi(Build.VERSION_CODES.Q)
#Throws(IOException::class)
fun saveMediaToStorage(context: Context, bitmap: Bitmap, format: CompressFormat, fName: String, folderName: String, extension: String) {
//Generating a file name
val filename = if (fName.contains("png")) fName.replace(".png", "") else fName.replace(".jpg", "")
//Output stream
var fos: OutputStream? = null
val relativePath = Environment.DIRECTORY_PICTURES + File.separator + folderName
Log.d(TAG, "saveMediaToStorage: Relative Path: $relativePath")
//getting the contentResolver
context.contentResolver?.also { resolver ->
//Content resolver will process the contentvalues
val contentValues = ContentValues().apply {
//putting file information in content values
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/$extension")
put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath)
}
//Inserting the contentValues to contentResolver and getting the Uri
val imageUri= resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) ?:
throw IOException("Failed to create new mediaStore record") // This line is triggering every time
//Opening an outputstream with the Uri that we got
fos = imageUri.let { resolver.openOutputStream(it) }
}
fos?.use {
//Finally writing the bitmap to the output stream that we opened
bitmap.compress(format, 100, it)
}
}
What I can understand is, the imageUri is coming null. But why so, afaik I am doing ok..
What can be the reason, where I am doing wrong.. Any help would be highly appreciated.

Kotlin saving video to gallery

I tried saving video to gallery like i found on example:
private fun saveVideoToInternalStorage3(filePath: String) {
val newfile: File
try {
val currentFile = File(filePath)
val fileName = currentFile.name
val cw = ContextWrapper(applicationContext)
val directory = cw.getDir("videoDir", Context.MODE_PRIVATE)
newfile = File(directory.absolutePath, fileName)
if(currentFile.exists()) {
val `in`: InputStream = FileInputStream(currentFile)
val out: OutputStream = FileOutputStream(newfile)
// Copy the bits from instream to outstream
val buf = ByteArray(1024)
var len: Int
while(`in`.read(buf).also {len = it} > 0) {
out.write(buf, 0, len)
}
scanner(filePath)
`in`.close()
out.close()
Log.d("", "Video file saved successfully.")
Toast.makeText(this, "Push Video Saved TO Gallery", Toast.LENGTH_SHORT).show()
} else {
Log.d("", "Video saving failed. Source file missing.")
}
} catch(e: java.lang.Exception) {
Log.d("", "EXS " + e.message)
e.printStackTrace()
}
And it works fine it shows message "Video file saved successfully." But there is no video in my gallery.
After searching for problem i found post that says you need a scanner and i tried:
private fun scanner(path: String) {
MediaScannerConnection.scanFile(this, arrayOf(path), null, object: OnScanCompletedListener {
override fun onScanCompleted(path: String, uri: Uri?) {
Log.i("", "Finished scanning $path")
}
})
But still no luck. Does any1 know what is going on? Saving images in gallery works fine btw.

Categories

Resources