8

I am trying to make some pictures that are taken in the app visible in the Gallery (so they can be shared and looked at outside of the app), but I want to keep the images themselves inside the data directory of the app so when the app is deleted they get removed (so they are stored in "{sdcard}/Android/data/{appID}/Pictures/{subfolder}/").

I have looked at a lot of answers and for older versions of Android both of the following solutions work, but they don't seem to work in Lollipop:

MediaScannerConnection.scanFile(this,
    new String[]{file.toString()}, new String[] { "image/jpeg" },
    new MediaScannerConnection.OnScanCompletedListener() {
        public void onScanCompleted(String path, Uri uri) {
            Log.i("ExternalStorage", "Scanned " + path + ":");
            Log.i("ExternalStorage", "-> uri=" + uri);
        }
    });

Uri contentUri = Uri.fromFile(file);
Intent mediaScanIntent = new 
    Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,contentUri);
sendBroadcast(mediaScanIntent);

I have tested this in a Nexus 4 (Android 5.0.1) and a Nexus 6 (Android 5.1) and it doesn't work. In a Nexus 7 (Android 4.2.2) it does work. All 3 devices have a ".onmedia" file in the {sdcard}/Android/data/ folder, so no normal media scan should pick them up...

Does anyone know a work around to get this to work on all devices/Android versions? Should this because of the noMedia file not work in the first place and is Lollipop the only version that does this correctly?

Edit: Note that even a restart of the phone (which should also trigger a rescan of files) doesn't work. And for good reason as the files are in a subfolder of a ".nomedia" directory... So any solution containing a MEDIA_MOUNTED broadcast is kind of useless I assume.

Kasium
  • 985
  • 10
  • 24

5 Answers5

9

Try below code. It working for me in Lollipop, Hope working for you as well

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA,"file path");
values.put(MediaStore.Images.Media.MIME_TYPE,"image/jpeg");
mContext.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);

EDIT: Don't forget to add this to your manifest (although in Lollipop it should no longer be necessary):

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Kasium
  • 985
  • 10
  • 24
Lokesh
  • 3,247
  • 2
  • 33
  • 62
  • 1
    Thanks. I was afraid this answer didn't work for me, but it was because I had the "write external storage" permission only for SDK 18 and lower. Now with the permission for all SDK's it works. Still need to test in lower versions of Android, but this is at least the perfect start! – Kasium May 10 '15 at 15:42
  • I got 100 reputations more just because I surfed the stackoverflow web a lot yesterday, just looking for this AWESOME answer. Thank you @Lokesh – Leebeedev May 24 '15 at 11:32
2

I would suggest you to take a look at my answer here. It wraps up all the findings around MediaScanner that I've made.

Side note: all the KitKat issues seem to be sticking on Lollipop as well.

Community
  • 1
  • 1
Sebastiano
  • 12,289
  • 6
  • 47
  • 80
  • Thanks. But they all don't seem to be the solution. Even the hack of sending the "mounted" broadcast through the shell doesn't work... – Kasium May 04 '15 at 07:41
  • Correct. As I said, there's no working solution for KitKat, and there's none for Lollipop as well. – Sebastiano May 04 '15 at 08:07
0

I am not shure if the media content provider will get read permissions for your local data directory that contain the imagages. Without the permissions your gallery aproach could not work.

To find out if it is possible you can try to put a references to you local images into androids media database yourself via

    mMediaProvider = mContext.getContentResolver().acquireProvider("media");
    mImagesUri = Images.Media.getContentUri(volumeName);
    result = mMediaProvider.insert(mImagesUri, values);

Here is the sourcecode of a media scanner that should contain all neccessary code fragments how to fill the values from a jpg

k3b
  • 14,517
  • 7
  • 53
  • 85
0

After saving the image call the scan method to scan the gallery,it will show the images in gallery.

  scanFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/appfolder/imgname"+imagenumber+".png");


 private void scanFile(String file) {


      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);
                    }
                });


    }
Jithu P.S
  • 1,843
  • 1
  • 19
  • 32
  • you have to refresh that specified file,then only its works,Tested in Nexus 5, 5.0.2.. its working,, – Jithu P.S May 06 '15 at 09:48
  • I thought for a second it might be the difference that you use the absolute path instead of file.toString(), but still with file.getAbsolutePath() it doesn't work on my Nexus 4, 5.0.1 though the log says it did get scanned: I/ExternalStorage﹕ Scanned /storage/emulated/0/Android/data/com.something/files/Pictures/10141/7657/RZ-1430906494186.jpg: I/ExternalStorage﹕ -> uri=content://media/external/file/43992 What application do you use to check the gallery? I tried Googles "Photos" and Telegram (share image). – Kasium May 06 '15 at 10:15
  • Google photos only and after saving photos in post execute am calling the scan method scanFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/dd/dddd"+imagenumber+".png"); – Jithu P.S May 06 '15 at 10:34
  • Ahh.. But you are using the PUBLIC external storage directory? Because what makes this a problem is that the files are stored in the private application directory "externalStorage/Android/data/APP-ID/files/Pictures/...". I want the files to be deleted when the app is deleted, but as long as the app is there I want them to be visible/shareable using other apps/gallery. – Kasium May 06 '15 at 13:27
0

As you have said that {sdcard}/Android/data/ folder contains a .nomedia file, then we can send a broadcast for the MediaScanner to scan the subfolders of the folder which contain .nomedia file by specifying that subfolder path by using bellow code.

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file:// "+"Directory path")));
Kartheek
  • 7,104
  • 3
  • 30
  • 44