16

I have an app where the user creates an image and then I want to save it so it's visible form the default gallery application.

Now I don't want the pictures to be saved in the same folder as the pictures taken from the camera, I want them to be saved in a folder dedicated to the app, just like images from apps like whatsapp or facebook.

I've tried saving them in this two locations:

File imagePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+ File.separator + appDirectoryName + File.separator);

and here

File imagePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ File.separator + appDirectoryName + File.separator);

If I browse through the phone I see that I successfully save the images but they don't show in the gallery app. It is obvious that I'm missing something but I don't know what it is. Maybe adding some kind of metadata to the files or folders so the gallery recognizes them?

Nemesis
  • 1,138
  • 1
  • 14
  • 29

6 Answers6

34

Well I found the answer in the end.

It turned out to be what I suspected. The saved image needs to have some metadata added in order to be seen in the gallery (at least in my device).

This is what I did:

OutputStream fOut = null;
    File file = new File(imagePath,"GE_"+ System.currentTimeMillis() +".jpg");

    try {
        fOut = new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
    try {
        fOut.flush();
        fOut.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    ContentValues values = new ContentValues();
    values.put(Images.Media.TITLE, this.getString(R.string.picture_title));
    values.put(Images.Media.DESCRIPTION, this.getString(R.string.picture_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);
Nemesis
  • 1,138
  • 1
  • 14
  • 29
  • @Nemesis hey buddy, i am also creating a similar flow in my app, addition to this is, i need to open image in image viewer. i did this by passing intent containing uri of clicked image. however it simply displays one image, is there any way where we can browse all images in the specified folder starting from the clicked image. thanks – Calvin Oct 08 '14 at 06:50
  • It works but unfortunately it decreases the size of the Bitmap that is going to be saved but resolution is same. I think that `bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);` is compressing the image. – Shajeel Afzal Apr 04 '15 at 10:49
  • outputStream is continuing to be null even after line fOut = new FileOutputStream(file); – Red M Dec 16 '17 at 22:54
  • 1
    @suv doesn't this work on videos? You'd need to change the file format to a video format, but I think most of the metadata would be very similar – Nemesis Apr 10 '19 at 10:21
  • @Nemesis ya it worked , it was not updating in the gallery :) – suv Apr 10 '19 at 11:19
3

I have had the same problem. The second way is the correct way, but you don't see the images in the Gallery because the gallery needs to be refreshed. So, you can wait a while until it refreshes itself, or you can use the MediaScanner - look here

Hope this helped!

gilonm
  • 1,829
  • 1
  • 12
  • 22
2

Try this

private void createDirectoryAndSaveFile(Bitmap imageToSave, String fileName) {

    File direct = new File(Environment.getExternalStorageDirectory() + "/DirName");

    if (!direct.exists()) {
        File wallpaperDirectory = new File("/sdcard/DirName/");
        wallpaperDirectory.mkdirs();
    }

        File file = new File(new File("/sdcard/DirName/"), fileName);
        if (file.exists())
            file.delete();
        try {
            FileOutputStream out = new FileOutputStream(file);
            imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
            out.flush();
            out.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
 }
Dharmishtha
  • 1,313
  • 10
  • 21
jstn
  • 504
  • 4
  • 14
2

I did the following to get it to work:

public void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED);
    String mCurrentPhotoPath = "file:" + image.getAbsolutePath(); // image is the created file image
    File file = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(file);
    mediaScanIntent.setData(contentUri);
    sendBroadcast(mediaScanIntent);
}
Prince
  • 81
  • 5
1

I tried this it works perfectly.

private Uri imageUri;
String getimgname, getimgpath;
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photo = new File(Environment.getExternalStorageDirectory(),  "IMG"+System.currentTimeMillis()+".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photo));
imageUri = Uri.fromFile(photo);
getimgname = photo.getName();
getimgpath = photo.getAbsolutePath();
Tunaki
  • 132,869
  • 46
  • 340
  • 423
0

Try this

MediaScannerConnection.scanFile(context,
                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);
                    }
                });
Devendra Vaja
  • 3,836
  • 2
  • 19
  • 14