53

Im adding images to a folder on the SDCARD. Since the images and my folder is not immediately visible in the Gallery im trying to get the MediaScannerConnection to update and show the folder/images in the gallery. This is not working so good for me since nothing shows up in Gallery. Im only testing in Eclipse AVD.

I dont see much talk about this maybe because the scanFile is new since api8. Could someone show how this is done?

Im trying it in both a service and Activity but keep getting uri=null when onScanCompleted.

Erik
  • 5,039
  • 10
  • 63
  • 119
  • 1
    possible duplicate of [Image, saved to sdcard, doesn't appear in Android's Gallery app](http://stackoverflow.com/questions/2170214/image-saved-to-sdcard-doesnt-appear-in-androids-gallery-app) – sarnold Feb 01 '12 at 09:01

8 Answers8

109

I realized that perhaps you were looking for a solution what would work previous to api level 8, and I could not make sense of Mitch's answer. I solved it by building a class for scanning a single file:

import java.io.File;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;

public class SingleMediaScanner implements MediaScannerConnectionClient {

    private MediaScannerConnection mMs;
    private File mFile;

    public SingleMediaScanner(Context context, File f) {
        mFile = f;
        mMs = new MediaScannerConnection(context, this);
        mMs.connect();
    }

    @Override
    public void onMediaScannerConnected() {
        mMs.scanFile(mFile.getAbsolutePath(), null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        mMs.disconnect();
    }

}

and you would use it like this to make the MediaScannerConnection scan a single file:

new SingleMediaScanner(this, file);
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
Petrus
  • 2,611
  • 3
  • 21
  • 21
  • the media scanner connects then sits there, how long is this supposed to take? – hunterp Aug 31 '11 at 08:42
  • @Petrus this works fine. Thanks. But I got an issue. In my application I capture series of images. But finally show only the second image after the scan completed. Can you please tell me what could be the problem. – AnujAroshA Feb 27 '12 at 04:54
  • 1
    May I know why we need to initialize a new MediaScannerConnection, connect it, do the scanFile and then disconnect it everytime? I tried directly using the static method call MediaScannerConnection.scanFile and it works without doing all these.. Update: OK I've asked too early, so the static method only available for API > 8 , thanks! – Bruce Jul 04 '14 at 04:01
  • also working fine on Android 6 Marshmallow. Thank you. – Taifun Nov 14 '15 at 17:28
  • Helpful solution! – Hassan Jamil Nov 19 '19 at 12:07
84

I was looking for the same thing and I found this in the ApiDemos, ExternalStorage. Solved all my problems as it scans a single 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);
      }
 });
Petrus
  • 2,611
  • 3
  • 21
  • 21
  • 4
    exists only since API level 8 – Ivan G. Sep 18 '11 at 16:12
  • 2
    Best solution to add a single file. – leoly May 11 '14 at 06:24
  • 2
    Works like a charm, for multiple files manually add file paths to the string array – Diljeet Jun 04 '14 at 08:49
  • this works like a charm, does this work for KitKat and above? I don't have a Kitkat device so I couldn't test it myself. – Bruce Jul 04 '14 at 04:03
  • Bashing my head to wall for 2 days to get this work on kitkat and it didn't. You can try this out on an emulator running kitkat. let me know if it worked. – M. Reza Nasirloo Jul 04 '14 at 12:23
  • @Pedram did you find out a way to make it run on kitkat? – Pdksock Sep 01 '14 at 13:59
  • @Samidh T actually it's working on kitkat but my situation was tricky. I was renaming a bunch of photos. Adding photos and videos is as simple as above code. – M. Reza Nasirloo Sep 04 '14 at 16:57
  • Works like a spell – X09 Oct 13 '16 at 13:26
  • Working for API 24 as well! – amitavk Apr 07 '17 at 14:42
  • 4
    Uri is not null and showing path but image won't appear in gallery on emulator in Android 7.1 API 25 – dakshbhatt21 Jul 18 '17 at 08:02
  • On API<=29, if you set a mimeType array, it must have the same size as the path array. See: https://cs.android.com/android/platform/superproject/+/android10-release:frameworks/base/media/java/android/media/MediaScannerConnection.java;l=215 On API>=30, mimetype doesn't seem considered. See: https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/base/media/java/android/media/MediaScannerConnection.java;l=181 – usilo Feb 07 '23 at 11:14
31
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
            + Environment.getExternalStorageDirectory()))); 
meizilp
  • 3,911
  • 3
  • 28
  • 11
  • oh was there an Intent to do this. Is this also API8?. Thank you! – Erik Jan 10 '11 at 13:14
  • not working really Uri.parse("/mnt/sdcard/PTPPservice/IMAG1175.jpg") Or is it a waiting time if scanner is busy? – Erik Jan 10 '11 at 14:08
  • 2
    I got it working now, wanted to update and show one picture only not the hole SD Card. Thinking it would take long time to re-mount the SD if there is much on it. Is there a way to only update a single item? – Erik Jan 10 '11 at 20:09
  • This is old but it may be of help to someone - a more specified path: sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)))); –  Apr 11 '13 at 16:17
  • 4
    Actually with Android 4.4 you will even get a java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED for trying this. Using MediaScannerConnection.scanFile is the right way to go. See example in one of the other answers . – Holger Dec 02 '14 at 07:24
  • From API 19, application needs system privilege to send ACTION_MEDIA_MOUNTED intent – anhtuannd Aug 16 '18 at 03:09
  • 1
    Do not do this anymore for: 1. Not working on almost every current devices. 2. Api < 8 no need to be supported now. 3. **Huge waste for only coding-time convenience**. – Meow Cat 2012 Mar 04 '19 at 12:33
  • deprecated method – Thorny84 Sep 13 '21 at 08:24
30

Or you can use following method:

private void scanFile(String path) {

        MediaScannerConnection.scanFile(MainActivity.this,
                new String[] { path }, null,
                new MediaScannerConnection.OnScanCompletedListener() {

                    public void onScanCompleted(String path, Uri uri) {
                        Log.i("TAG", "Finished scanning " + path);
                    }
                });
    }

Call file scan as:

scanFile(yourFile.getAbsolutePath());
Kapil Jituri
  • 1,241
  • 14
  • 25
11

Do not do the sendBroadcast if you only want one image to appear in the gallery. That'd be a huge waste of resources. You'll need to make a MediaScannerConnectionClient and then call connect() on the MediaScannerConnection you make from it to scan the file. Here's an example:

private MediaScannerConnectionClient mediaScannerConnectionClient = 
    new MediaScannerConnectionClient() {

    @Override
    public void onMediaScannerConnected() {
        mediaScannerConnection.scanFile("pathToImage/someImage.jpg", null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        if(path.equals("pathToImage/someImage.jpg"))
            mediaScannerConnection.disconnect();
    }
};
new MediaScannerConnection(context, mediaScannerConnectionClient).connect();
Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
Mitch
  • 481
  • 1
  • 4
  • 5
5

Let your activity implement 'MediaScannerConnectionClient' and add this to your activity:

private void startScan() 
{ 
    if(conn!=null) conn.disconnect();  
    conn = new MediaScannerConnection(YourActivity.this,YourActivity.this); 
    conn.connect(); 
} 

@Override 
public void onMediaScannerConnected() { 
    try{
        conn.scanFile(yourImagePath, "image/*");
       } catch (java.lang.IllegalStateException e){
       }
}

@Override 
public void onScanCompleted(String path, Uri uri) { 
    conn.disconnect(); 
} 
TOMKA
  • 1,096
  • 13
  • 24
0
File file = new File(absolutePath);
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
sendBroadcast(intent);
abhi5306
  • 134
  • 1
  • 7
0

Use Intent instead of MediaScannerConnection. MediaScannerConnection will make your app gc error with IMediaScannerListener.Stub mListener.

Intent mediaScannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri fileContentUri = Uri.parseFile(permFile); // With 'permFile' being the File object
mediaScannerIntent.setData(fileContentUri);
sendBroadcast(mediaScannerIntent);
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Pan
  • 1