Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly notify MediaScanner about a folder, even on Nexus/Kitkat devices?

Background

I'm making an app that downloads some images from the Internet into a specific folder that is defined as:

final String pathToPutFiles = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
            + File.separator + DOWNLOAD_FOLDER_NAME;

I wish to make the gallery and any app that shows media, to be notified of those images and be able to show them.

Sadly I'm having problems on Nexus 4, which has Kitkat version (4.4.2 to be exact). Sometimes it works and sometimes it doesn't.

The problem

There are plenty of posts about this issue, and I've tried many of them and none worked using a simple folder path:

  • using an intent of Intent.ACTION_MEDIA_SCANNER_SCAN_FILE , as shown here . This didn't work on any device
  • creating an instance of MediaScannerConnectionClient and call scan once the connection was done, as shown here and here . Not sure what's wrong with this, as it does succeed to connect.
  • call scanFile , as shown here , with and without a listener. This worked fine on Galaxy S3, but not on Nexus 4. This is what I've chosen to do, but I've noticed that it can't work with a single folder path. Instead, it need an array of files to notify about.

What I've tried

This is what I've done (again, it works fine on Galaxy S3 which has Android 4.3, but sometimes doesn't work on Nexus 4 which has Android 4.4.2) :

protected void notifyMediaScannerOfNewImageFiles(final String folderPathToScan) {
        final ArrayList<String> newFilesToScan = new ArrayList<String>();
        preparePaths(folderPathToScan, newFilesToScan, true);
        final String[] newFilesToScanArr = newFilesToScan.toArray(new String[newFilesToScan.size()]);
        MediaScannerConnection.scanFile(getApplicationContext(), newFilesToScanArr, null, null);
}

public static void preparePathsForMediaScanning(final String folderPathToScan, final Collection<String> pathsToFill,
        final boolean recursive) {
    if (TextUtils.isEmpty(folderPathToScan))
        return;
    final File folderToScan = new File(folderPathToScan);
    if (!folderToScan.exists())
        return;
    pathsToFill.add(folderPathToScan);
    if (!folderToScan.isDirectory())
        return;
    final File[] childrenFiles = folderToScan.listFiles();
    if (childrenFiles == null || childrenFiles.length == 0)
        return;
    for (final File childFile : childrenFiles) {
        if (childFile.exists()) {
            final String childFilePath = childFile.getAbsolutePath();
            pathsToFill.add(childFilePath);
            if (recursive && childFile.isDirectory())
                preparePathsForMediaScanning(childFilePath, pathsToFill, true);
        }
    }
}

The question

How should I notify of an entire folder to scan?

Why does this method work only sometimes on Kitkat ? Is it just Nexus devices, or other devices too?

What should be used to support all devices and Android versions?

like image 305
android developer Avatar asked Jan 19 '14 12:01

android developer


1 Answers

I have banged my head around this problem for a good deal of time by now. As posted on this SO anwser, it seems like it is a bug that occurs on KitKat.

The issue is being tracked both externally and internally by the Android team.

In the meantime, this is what I've found out: https://stackoverflow.com/a/23078323/1367571

like image 166
Sebastiano Avatar answered Sep 19 '22 06:09

Sebastiano