Images not showing in gallery - java

I am working on the Whats'up status saver app. The status images are showing in the file manager but are not showing in the gallery.
Here is my code
public void downlaodImage(StatusModel statusModel) throws IOException {
File file = new File(MyContanst.APP_DIRECTORY);
if (!file.exists()){
file.mkdirs();
}
File destFile = new File(file+ File.separator+statusModel.getTitle());
if (destFile.exists()){
destFile.delete();
}
copyFile(statusModel.getPath(), destFile);
Toast.makeText(getActivity(), "File saved", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(destFile));
getActivity().sendBroadcast(intent);
}
private void copyFile(String file, File destFile) throws IOException {
if (!destFile.getParentFile().exists()){
destFile.getParentFile().mkdirs();
}
if (!destFile.exists()){
destFile.createNewFile();
}
FileChannel src = null;
FileChannel dst = null;
src = new FileInputStream(file).getChannel();
dst = new FileOutputStream(destFile).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
What I doing wrong?

You need to call a broadcast to tell Android OS that you have added an Image or Video
So after download image/video just call below method will show your image/video in to gallery.
public void scanMedia(File f, String type) {
if (SDK_INT >= 19) {
if (type.equals("video/*")) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, f.getAbsolutePath());
values.put(MediaStore.Video.Media.MIME_TYPE, type);
values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis());
try{
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context, Uri.parse(f.getAbsolutePath()));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long timeInMillisec = Long.parseLong(time);
values.put(MediaStore.Video.Media.DURATION, timeInMillisec);
retriever.release();
}catch (Exception e){
values.put(MediaStore.Video.Media.DURATION, 0);
}
context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}else if(type.equals("image/*")){
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, f.getAbsolutePath());
values.put(MediaStore.Images.Media.MIME_TYPE, type);
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
} else {
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
}
}
Happy Coding.

Related

Save an Image with TextureView?

I hope you can fix my problem:
I have got a textureview to takes photos but when he capture photos, the file who need to contain the picture is empty. I don't know where and what is the problem. I just think that the problem is when the file is created. Thank you to help me.
This is a part of my code :
private void takePicture() throws CameraAccessException, IOException {
if(cameraDevice == null){
return;
}
CameraManager manager = (CameraManager) Objects.requireNonNull(getContext()).getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
int width = 640;
int height = 480;
if(jpegSizes!=null && jpegSizes.length>0){
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
ImageReader reader = ImageReader.newInstance(width,height, ImageFormat.JPEG, 1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE,CameraMetadata.CONTROL_MODE_AUTO);
int rotation = Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
// First I get the path to gallery and crate new Album to my app
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
mImageFolder = new File(file, "Fluico");
if (!mImageFolder.exists()) {
if (!mImageFolder.mkdirs()) {
Log.d("Fluicophoto", "failed to create directory");
}
}
/*Second I cut mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
from onActivityCreated and add here with the new path from my Album*/
#SuppressLint("SimpleDateFormat") String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "IMAGE_" + timestamp + "_";
file = File.createTempFile(prepend, ".jpg", mImageFolder);
Toast.makeText(getContext(), "file need to be save", Toast.LENGTH_SHORT).show();
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
try {
save(bytes);
} finally {
image.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(getContext(), "saved", Toast.LENGTH_SHORT).show();
try{
createCameraPreview();
}catch (CameraAccessException e){
Toast.makeText(getContext(), "capture not comleted", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured( CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(getContext(), "capture not configured", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onConfigureFailed( CameraCaptureSession session) {
}
},mBackgroundHandler);
}
private void save(byte[] bytes) {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
outputStream.close();
Toast.makeText(getContext(), "it's good", Toast.LENGTH_SHORT).show();
}catch (IOException e){
Toast.makeText(getContext(), "file not found", Toast.LENGTH_SHORT).show();
}
}
Try with below code:
File myDir;
String fname;
String id = "123456";
int count = 0;
String root = Environment.getExternalStorageDirectory().toString();
myDir = new File(root + "/PhotoApp/" + id);
myDir.mkdirs();
count++;
counter.setText(String.valueOf(count));
fname = "" + id + "-" + count + ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete();
This code will create a folder PhotoApp and inside the folder, all the images will store.
You can get full code with the camera in my GitHub:
Link: https://github.com/abhishekhzb/quick_camera

Trying to save images to directory, Saving into an unknown place

I am trying to create a facial/emotion detection application for my dissertation and have hit the wall that has stopped me from progressing and I cant figure out the reason why it is preventing the image saving to the directory of the phone. It seems to be saving to the SD card, but I dont use an SDcard in my phone / an emulated DCIM.
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+ "/" + UUID.randomUUID(), toString()+ ".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes() [0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if (image != null)
image.close();
}
}
}
This is the code I have to create the file and save to the location, I have tried other solutions but they throw out errors.
File folder = new File(Environment.getExternalStorageDirectory() + "/CustomFolder");
File file;
if (!folder.exists()) {
boolean success = folder.mkdir();
if (success){
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}else {
Toast.makeText(FacialDetection.this, "Failed to save file to folder", Toast.LENGTH_SHORT).show();
}
}else{
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes() [0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if (image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(***file***);
outputStream.write(bytes);
}finally {
if (outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(FacialDetection.this, "Saved " + ***file***, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
The updated code, stuff bold and italic is what is throwing errors
I will advise you to create your own custom folder location this way:
File folder = new File(Environment.getExternalStorageDirectory() + "/CustomFolder");
File file;
if (!folder.exists()) {
boolean success = folder.mkdir();
if (success){
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}else {
//Some message
}
}else {
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}
//The rest of your code...
You're calling:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
I would speculate that .getExternalStoragePublicDirectory() means get directory on SD card. Is there a getInternal... method?
//Create folder !exist
String folderPath = Environment.getExternalStorageDirectory() +"/myFoldername";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
//create a new file
newFile = new File(folderPath, newPhoto.getName());
if (newFile != null) {
// save image here
Uri relativePath = Uri.fromFile(newFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, relativePath);
startActivityForResult(intent, CAMERA_REQUEST);
}

How to Save images in an specific folder android

I'm a newbie about android programming
I would like to create folder for store image from my app when user click save
I can save image to my device
but I have no idea to create specific folder ,How to create folder??
thanks for your help!
and sorry my english is not good.
My code
CapturePhotoUtils.insertImage(context.getContentResolver(), myBitmap, title ,des);
and CapturePhotoUtils.java
public class CapturePhotoUtils {
public static final String insertImage(ContentResolver cr,
Bitmap source,
String title,
String description) {
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, title);
values.put(Images.Media.DISPLAY_NAME, title);
values.put(Images.Media.DESCRIPTION, description);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
// Add the date meta data to ensure the image is added at the front of the gallery
values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
Uri url = null;
String stringUrl = null; /* value to be returned */
try {
url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if (source != null) {
OutputStream imageOut = cr.openOutputStream(url);
try {
source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
} finally {
imageOut.close();
}
long id = ContentUris.parseId(url);
// Wait until MINI_KIND thumbnail is generated.
Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
// This is for backward compatibility.
storeThumbnail(cr, miniThumb, id, 50F, 50F,Images.Thumbnails.MICRO_KIND);
} else {
cr.delete(url, null, null);
url = null;
}
} catch (Exception e) {
if (url != null) {
cr.delete(url, null, null);
url = null;
}
}
if (url != null) {
stringUrl = url.toString();
}
return stringUrl;
}
private static final Bitmap storeThumbnail(
ContentResolver cr,
Bitmap source,
long id,
float width,
float height,
int kind) {
// create the matrix to scale it
Matrix matrix = new Matrix();
float scaleX = width / source.getWidth();
float scaleY = height / source.getHeight();
matrix.setScale(scaleX, scaleY);
Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
source.getWidth(),
source.getHeight(), matrix,
true
);
ContentValues values = new ContentValues(4);
values.put(Images.Thumbnails.KIND,kind);
values.put(Images.Thumbnails.IMAGE_ID,(int)id);
values.put(Images.Thumbnails.HEIGHT,thumb.getHeight());
values.put(Images.Thumbnails.WIDTH,thumb.getWidth());
Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
try {
OutputStream thumbOut = cr.openOutputStream(url);
thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
thumbOut.close();
return thumb;
} catch (FileNotFoundException ex) {
return null;
} catch (IOException ex) {
return null;
}
}
try this
addToFav("/Favorite", "add to favoriote");
create this function
public void addToFav(String dirName, String str) {
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
String fileName = "fav" + timeStamp + ".JPG";
File direct = new File(Environment.getExternalStorageDirectory() + dirName);
if (!direct.exists()) {
File wallpaperDirectory = new File(Environment.getExternalStorageDirectory() + dirName);
wallpaperDirectory.mkdirs();
}
File file = new File(new File(Environment.getExternalStorageDirectory() + dirName), fileName);
if (file.exists()) {
file.delete();
}
try {
FileOutputStream out = new FileOutputStream(file);
Bitmap bitmap = BitmapFactory.decodeFile(imagesPathArrayList.get(pos));
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, "title");
values.put(Images.Media.DESCRIPTION, "description");
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
values.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
values.put("_data", file.getAbsolutePath());
ContentResolver cr = getContentResolver();
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
and don't forget to add permission in manifest file

My created root directory is not showing in my gallery in android?

"I have fetch an image from ImageView and save it in root directory but when i go to pic the same image using from gallery , the created folder is not visible in gallery picker . but when i check the folder from file manager it show me the created folder with image",
#I have used this code for saving the image in my directory.#
public void saveImageToSdCard(Bitmap bitmap1) {
File sdCard = Environment.getExternalStorageDirectory();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
if (sdCard != null) {
File directory = new File(sdCard.getAbsolutePath() + "/My_folder");
if (directory.exists()) {
directory.delete();
Log.e("it run","directoty is exists");
}
directory.mkdirs();
String strImageName = File.separator + "IMG_" + timeStamp + ".jpg";
File file = new File(directory, strImageName);
// strFinalImage = file.getAbsolutePath();
// Log.e(TAG + "strFinalImage22", strFinalImage + "");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap1.compress(Bitmap.CompressFormat.JPEG, 60, bytes);
fileOutputStream.write(bytes.toByteArray());
fileOutputStream.flush();
fileOutputStream.close();
// Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
} else {
Toast.makeText(getActivity(),"Sd card mount", Toast.LENGTH_SHORT).show();
}
}
-------------------------------------------------------------------
# Intent code for gallery #
Intent galleryIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, 0);
-------------------------------------------------------------------
# OnActivityResultCode() #
Uri pickedImage = data.getData();
String[] filePath = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(pickedImage, filePath, null, null, null);
cursor.moveToFirst();
String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
Log.e("Gallery", "File URI:" + imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
cursor.close();

how to save bitmap to android gallery

unfortunately the solutions I've found didn't work on android 5.1.1.
I have a bitmap called source. I need to save it directly to my phone's gallery. My manifest contains <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Can you give me a working method to do this?
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.
Use this one:
private void saveImage(Bitmap finalBitmap, String image_name) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root);
myDir.mkdirs();
String fname = "Image-" + image_name+ ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete();
Log.i("LOAD", root + fname);
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Use this code this we help you to store images into a particular folder which is saved_images and that folder images show in gallery immediately.
private void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
// sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
// Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
From Android Q there are changes in saving image to gallery.Thanks to #BaoLei, here is my answer in java if anybody needs it.
private void saveImage(Bitmap bitmap) {
if (android.os.Build.VERSION.SDK_INT >= 29) {
ContentValues values = contentValues();
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + getString(R.string.app_name));
values.put(MediaStore.Images.Media.IS_PENDING, true);
Uri uri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if (uri != null) {
try {
saveImageToStream(bitmap, this.getContentResolver().openOutputStream(uri));
values.put(MediaStore.Images.Media.IS_PENDING, false);
this.getContentResolver().update(uri, values, null, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
} else {
File directory = new File(Environment.getExternalStorageDirectory().toString() + '/' + getString(R.string.app_name));
if (!directory.exists()) {
directory.mkdirs();
}
String fileName = System.currentTimeMillis() + ".png";
File file = new File(directory, fileName);
try {
saveImageToStream(bitmap, new FileOutputStream(file));
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
private ContentValues contentValues() {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
}
return values;
}
private void saveImageToStream(Bitmap bitmap, OutputStream outputStream) {
if (outputStream != null) {
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is a fully working solution in Kotlin:
fun saveToGallery(context: Context, bitmap: Bitmap, albumName: String) {
val filename = "${System.currentTimeMillis()}.png"
val write: (OutputStream) -> Boolean = {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, it)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
put(MediaStore.MediaColumns.RELATIVE_PATH, "${Environment.DIRECTORY_DCIM}/$albumName")
}
context.contentResolver.let {
it.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)?.let { uri ->
it.openOutputStream(uri)?.let(write)
}
}
} else {
val imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString() + File.separator + albumName
val file = File(imagesDir)
if (!file.exists()) {
file.mkdir()
}
val image = File(imagesDir, filename)
write(FileOutputStream(image))
}
}
Do it in One Line
MediaStore.Images.Media.insertImage(applicationContext.getContentResolver(), IMAGE ,"nameofimage" , "description");
Now we have android10 and android11, so here is an updated version, that will work in all android devices.
Make sure you have the WRITE_EXTERNAL_STORAGE permission before calling this function.
private fun saveMediaToStorage(bitmap: Bitmap) {
val filename = "${System.currentTimeMillis()}.jpg"
var fos: OutputStream? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
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)
toast("Saved to Photos")
}
}
Its kotlin, and I think very straight forward and self explaining code. But still if you have a problem, comment below and I will explain.
Reference: Android Save Bitmap to Gallery Tutorial.
I'd like to add Java code based on #Bao Lei 's answer that I used in my app.
private void saveImage(Bitmap bitmap, Context context, String folderName) throws FileNotFoundException {
if (android.os.Build.VERSION.SDK_INT >= 29) {
ContentValues values = new 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.
Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if (uri != null) {
saveImageToStream(bitmap, context.getContentResolver().openOutputStream(uri));
values.put(MediaStore.Images.Media.IS_PENDING, false);
context.getContentResolver().update(uri, values, null, null);
}
} else {
dir = new File(getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES),"");
// getExternalStorageDirectory is deprecated in API 29
if (!dir.exists()) {
dir.mkdirs();
}
java.util.Date date = new java.util.Date();
imageFile = new File(dir.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile = new File(dir.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
saveImageToStream(bitmap, new FileOutputStream(imageFile));
if (imageFile.getAbsolutePath() != null) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, imageFile.getAbsolutePath());
// .DATA is deprecated in API 29
context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
}
}
private ContentValues contentValues() {
ContentValues values = new 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 void saveImageToStream(Bitmap bitmap, OutputStream outputStream) {
if (outputStream != null) {
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This one worked fine in my app.
For Media Scanning, you can simply do
val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
intent.data = Uri.fromFile(path) // path must be of File type
context.sendBroadcast(intent)

Categories

Resources