Trigger mediascanner on specific path (folder), how to?

北城以北 提交于 2019-11-26 13:06:59

The Story

Before Android 4.4, we could just send a broadcast to trigger the media scanner on any particular file, or folder or even on the root of the storage. But from 4.4 KitKat, this have been fixed by the Android Developers.

Why do I say fixed? The reason is simple. Sending a broadcast using MEDIA_MOUNTED on the root directory is very expensive. Running the Media Scanner is an expensive operation and the situation gets even worse when the user has got a lot of files in the storage and deep folder structures.

Before Android 4.4

Keep it straight and simple. If you are targeting your app before Android 4.4. But keep in mind not to use it on the root directory unless absolutely necessary.

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

From Android 4.4

There are two ways for you.

i) The first one is very similar to the previous example, but may not work efficiently and is not recommended too.

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

ii) Now, let us move on to the most recommended and efficient solution to this problem.

Add the file paths of the files which have been updated, like this, in a String type ArrayList

ArrayList<String> toBeScanned = new ArrayList<String>();
toBeScanned.add(item.getFilePath());

Now you need to run scanFile() static method of the MediaScannerConnection class and pass the String array containing the list of all the files which have been updated and needs to be media scanned.

You can also put a listener to respond when the scanning has been finished for individual files.

String[] toBeScannedStr = new String[toBeScanned.size()];
                toBeScannedStr = toBeScanned.toArray(toBeScannedStr);

                MediaScannerConnection.scanFile(getActivity(), toBeScannedStr, null, new OnScanCompletedListener() {

                    @Override
                    public void onScanCompleted(String path, Uri uri) {
                        System.out.println("SCAN COMPLETED: " + path);

                    }
                });

Hey I found out how to do it with a very simple code.

Just call this line of code:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

This should trigger mediascanner.

bluefalcon

In Android, there is a content database which is used by the media scanner to keep track of all the media content present on the device.

When Android boots up, the mediascanner service is launched and runs through the entire external storage to find if there is any new media content if it finds one then,

  • It adds an entry of that media content into the content database
  • Each entry in the content database contains metadata of the media content like Name, date, file size, type of file, etc..
  • So when you make a modification to a media content, you will need to update the content database also.
  • If the content database is not update then other applications also will not be able to access that particular media content.
  • Running the media scanner just updates the content database

Instead of running the media scanner, you can update the content database yourself and it should resolve the problem.

Here is an explanation on how to insert, delete, update using the content resolver. (Search for the section "Inserting, Updating, and Deleting Data")

Edit: There is a sample code in this answer. Check for the answer by Janusz.

   File file = new File(absolutePath);
   Uri uri = Uri.fromFile(file);
   Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
   sendBroadcast(intent);
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}

Reference: http://developer.android.com/training/camera/photobasics.html#TaskGallery

The Add the Photo to a Gallery Section

As @Aritra Roy's answer, i decide to make an experiment about this issue. What i got here are:

  • Intent.ACTION_MEDIA_MOUNTED and Intent.ACTION_MEDIA_SCANNER_SCAN_FILE can accept individual file path, so sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse(filePath))); or sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(filePath))); will be valid.
  • If you use individual file path with Intent.ACTION_MEDIA_MOUNTED on Kitkat or above, your application will still crash
  • If you use Intent.ACTION_MEDIA_SCANNER_SCAN_FILE or MediaScannerConnection on device lower than Kitkat, your application will not force close, but the method will just simply not working as you want.

From that experiment, i think the best method to handle is

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    MediaScannerConnection.scanFile(context, new String[]{imagePath}, null, new MediaScannerConnection.OnScanCompletedListener() {
        public void onScanCompleted(String path, Uri uri) {
            //something that you want to do
        }
    });
} else {
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
            Uri.parse("file://" + imagePath)));
}

Let me know if i missed something

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!