Refresh the Gallery after deleting an image file?

user2184013 picture user2184013 · Mar 18, 2013 · Viewed 7.3k times · Source

I always found the following answer for my Question:

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

but it do not work on my System (Nexus4 Android 4. ...)

I can create a File and add it to the Media-DB whith this code

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

Where "file" is the new image-file i want to add.

after deleting the File I try to refresch the gallery by

Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED);
    Uri contentUri = Uri.parse("file://" + Environment.getExternalStorageDirectory());
    intent.setData(contentUri);
    context.sendBroadcast(intent);

or

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

but there are still empty placeholder in the Galery.

I do not know why?...

To be on the safe side I add too my Activity in the AndroidManifest.xml

<intent-filter>
            <action android:name="android.intent.action.MEDIA_MOUNTED" />
            <data android:scheme="file" /> 
        </intent-filter>

but the result is the same. Any idea to solve the problem?

Answer

M. Reza Nasirloo picture M. Reza Nasirloo · Jan 23, 2015

After the KitKat you can't send the Intent to run the MediaScanner on whole device's storage, because it is a CPU I\O intensive task and if every single app that download an image or delete one, call that intent battery would drain easily, hence they have decided to block that operation. Here are your options:

Use the old way for pre-KitKat

Pass your filePath:

if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
    mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
                Uri.parse("file://" + Environment.getExternalStorageDirectory())));
} else{


    MediaScannerConnection.scanFile(mContext,  filePath, null, new MediaScannerConnection.OnScanCompletedListener() {
        /*
         *   (non-Javadoc)
         * @see android.media.MediaScannerConnection.OnScanCompletedListener#onScanCompleted(java.lang.String, android.net.Uri)
         */
        public void onScanCompleted(String path, Uri uri) 
        {
        Log.i("ExternalStorage", "Scanned " + path + ":");
        Log.i("ExternalStorage", "-> uri=" + uri);
        }
    });

}

A more reliable approach is to update the MediaStore directly:

// Set up the projection (we only need the ID)
String[] projection = { MediaStore.Images.Media._ID };

// Match on the file path
String selection = MediaStore.Images.Media.DATA + " = ?";
String[] selectionArgs = new String[] { file.getAbsolutePath() };

// Query for the ID of the media matching the file path
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver contentResolver = getContentResolver();
Cursor c = contentResolver.query(queryUri, projection, selection, selectionArgs, null);
if (c.moveToFirst()) {
    // We found the ID. Deleting the item via the content provider will also remove the file
    long id = c.getLong(c.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
    Uri deleteUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
    contentResolver.delete(deleteUri, null, null);
} else {
    // File not found in media store DB
}
c.close();