35

I am deleting an image file from my application. I was doing

new  File(filename).delete ();

This was actually deleting the file. But the image was still visible in the gallery.

On search i found that we should use

getContentResolver().delete(Uri.fromFile(file), null,null); to delete

But here i am getting the exception:

Unknown file URL. java.lang.IllegalArgumentException: Unknown URL file:///mnt/sdcard/DCIM/Camera/IMG_20120523_122612.jpg

When i see with any file browser, this particular image is present. Please help me to fix this issue. Is there any other way to update gallery when image is physically deleted

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
png
  • 4,368
  • 7
  • 69
  • 118

11 Answers11

37

Use the code below, it may help you.

File fdelete = new File(file_dj_path);
if (fdelete.exists()) {
    if (fdelete.delete()) {
        System.out.println("file Deleted :" + file_dj_path);
    } else {
        System.out.println("file not Deleted :" + file_dj_path);
    }
}

to refresh gallery after deleting image use below code for send Broadcast

(for < KITKAT API 14)

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

For >= KITKAT API 14 use below code

MediaScannerConnection.scanFile(this, new String[] { Environment.getExternalStorageDirectory().toString() }, 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);
              }
            });

Because:

ACTION_MEDIA_MOUNTED

is deprecated in KITKAT(API 14).


EDITED 04-09-2015

its working fine check below code

public void deleteImage() {
        String file_dj_path = Environment.getExternalStorageDirectory() + "/ECP_Screenshots/abc.jpg";
        File fdelete = new File(file_dj_path);
        if (fdelete.exists()) {
            if (fdelete.delete()) {
                Log.e("-->", "file Deleted :" + file_dj_path);
                callBroadCast();
            } else {
                Log.e("-->", "file not Deleted :" + file_dj_path);
            }
        }
    }

    public void callBroadCast() {
        if (Build.VERSION.SDK_INT >= 14) {
            Log.e("-->", " >= 14");
            MediaScannerConnection.scanFile(this, new String[]{Environment.getExternalStorageDirectory().toString()}, 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.e("ExternalStorage", "Scanned " + path + ":");
                    Log.e("ExternalStorage", "-> uri=" + uri);
                }
            });
        } else {
            Log.e("-->", " < 14");
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
                    Uri.parse("file://" + Environment.getExternalStorageDirectory())));
        }
    }

below is logs

09-04 14:27:11.085    8290-8290/com.example.sampleforwear E/-->﹕ file Deleted :/storage/emulated/0/ECP_Screenshots/abc.jpg
09-04 14:27:11.085    8290-8290/com.example.sampleforwear E/-->﹕ >= 14
09-04 14:27:11.152    8290-8290/com.example.sampleforwear E/﹕ appName=com.example.sampleforwear, acAppName=/system/bin/surfaceflinger
09-04 14:27:11.152    8290-8290/com.example.sampleforwear E/﹕ 0
09-04 14:27:15.249    8290-8302/com.example.sampleforwear E/ExternalStorage﹕ Scanned /storage/emulated/0:
09-04 14:27:15.249    8290-8302/com.example.sampleforwear E/ExternalStorage﹕ -> uri=content://media/external/file/2416
Dhaval Parmar
  • 18,812
  • 8
  • 82
  • 177
  • will this broadcast work even id the image is not in external memory ? – png May 23 '12 at 09:11
  • Thank you. Does it work for videos also ? Sorry for too many questions. I tried for video and see that sometime its not getting reflected. Wanted to get a confirmation if you have already tried – png May 23 '12 at 09:22
  • 2
    it works for files it doesn't matter what is the extension of file. – Trikaldarshiii May 23 '12 at 09:48
  • android.intent.action.MEDIA_MOUNTED is protected starting from kitkat. so this solution won't work in the latest devices – venkat May 01 '15 at 16:44
  • 8
    This solution does not work (or no longer works). Images remain in the gallery using both of these methods. – Bisclavret Sep 02 '15 at 05:15
  • @Bisclavret: this solution is working fine check my edited answer you can also try with that code (also in latest devices) – Dhaval Parmar Sep 04 '15 at 09:00
  • Why would you rescan the entire external storage dir? (this could take a while), you should specify the exact path to be rescanned. – stealthcopter Oct 26 '15 at 12:24
  • you can use exact folder path. – Dhaval Parmar Oct 26 '15 at 12:46
  • 1
    For some reason this does not work for me. The log says the image is deleted but I can still find it in gallery. – jlively May 24 '17 at 08:43
  • 1
    The "EDITED 04-09-2015" version works for individual files(4.4 & 6.0) but NOT directory path. If you want to delete a directory, you'll need to send a list of file paths to MediaScannerConnection. – LEO Jul 10 '17 at 22:39
35

I've seen a lot of answers suggesting the use of

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

This works but causes the Media Scanner to re-scan the media on the device. A more efficient approach would be to query/delete via the Media Store content provider:

// 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();
Tanner Perrien
  • 3,133
  • 1
  • 28
  • 35
  • 1
    Delete before you rename... the media scanner will automatically/eventually pick up your new (renamed) file. – Tanner Perrien Jul 10 '14 at 19:56
  • I thinks it's kinda dangerous, what if it fails to rename the file? It simply loses the user data! I should experiment some combinations, like hold last name of the file, try to rename if successful call the `MedaiScannerConnection`(force add the new file) and then deleting old path with querying `MediaStore`. Any idea? – M. Reza Nasirloo Jul 11 '14 at 06:06
  • Still this is not good too, imagine deleting a folder. Then loop through all deleted paths and remove them from content resolver. Sounds a very slow process. – xmen Jan 08 '15 at 15:57
  • 1
    This was the only answer that worked for me on all Android devices; [this answer](http://stackoverflow.com/a/25991695/4751173) worked for most devices but not on a Samsung S4. Long live device fragmentation! – Glorfindel Feb 25 '16 at 08:59
  • Sorry but `c.moveToFirst()` returns `false` – Hamzeh Soboh Jun 30 '18 at 20:20
  • @xmen The OP asked about deleting an image, not a folder. If deleting a directory I would suggest looking more into [ContentProviderOperation](https://developer.android.com/reference/android/content/ContentProviderOperation) – Tanner Perrien Jul 25 '18 at 21:37
  • `MediaStore.Images.Media.DATA` is now deprecated. You will need a different way of obtaining the ID from the File. – Kyle R Aug 26 '20 at 00:18
  • `Deleting the item via the content provider will also remove ` - but only from specific Android version, so for older version of Android you still need `File.delete` method! – user924 Dec 22 '20 at 21:53
24
File file = new File(photoUri);
file.delete();

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(photoUri))));

This code works for me and I think it better than remount whole SD card with Intent.ACTION_MEDIA_MOUNTED

Cody
  • 4,353
  • 4
  • 39
  • 42
  • Good answer. I used it for my solution http://stackoverflow.com/a/26519238/1621111 – Konstantin Konopko Oct 23 '14 at 00:15
  • This is definitely the best solution unless you keep track of the content's ID when you inserted it into the content resolver. Appears to work faster than querying the content resolver for the content id, and then deleting it though `getContentResolver().delete`. – sixones Mar 12 '15 at 13:32
19

To delete image,

ContentResolver contentResolver = getContentResolver();
contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            MediaStore.Images.ImageColumns.DATA + "=?" , new String[]{ imagePath });
Darshan Dorai
  • 659
  • 8
  • 10
  • This is the only true answer the deletes the image file and also removes the entry from media store, so that the image does not show up on MTP. – tingyik90 Feb 02 '18 at 12:24
  • 1
    Nice and simple, works on Android P... can use it for Video content too if you replace Images with Video. – Billy May 28 '18 at 02:26
  • Just to clarify that this removes the SQL DATA field, pointing the MediaStore to that File, you must still `file.delete()` it. It is possible for one operation to fail, and the other succeed – Bonatti Oct 26 '18 at 12:26
5

I tried all those solutions but had no luck in Android 6.
In the end, I found this snipped of code that worked fine.

public static void deleteFileFromMediaStore(final ContentResolver contentResolver, final File file) {
    String canonicalPath;
    try {
        canonicalPath = file.getCanonicalPath();
    } catch (IOException e) {
        canonicalPath = file.getAbsolutePath();
    }
    final Uri uri = MediaStore.Files.getContentUri("external");
    final int result = contentResolver.delete(uri,
            MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
    if (result == 0) {
        final String absolutePath = file.getAbsolutePath();
        if (!absolutePath.equals(canonicalPath)) {
            contentResolver.delete(uri,
                    MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
        }
    }
}

I also tested this in Android 4.4 and 5.1 and it works perfectly.

Marco Menardi
  • 481
  • 6
  • 20
  • I am deleting some media files(images & videos). Above code take too much time for each media file to remove from media store. 5 files in 176 ms. How can i speed it up? – hasnain_ahmad Aug 11 '16 at 10:43
5

In Kotlin you can do this :

private fun deleteImage(path: String) {
    val fDelete = File(path)
    if (fDelete.exists()) {
        if (fDelete.delete()) {
            MediaScannerConnection.scanFile(this, arrayOf(Environment.getExternalStorageDirectory().toString()), null) { path, uri ->
                Log.d("debug", "DONE")
            }
        } 
    }
}
Jéwôm'
  • 3,753
  • 5
  • 40
  • 73
4
sendBroadcast(new Intent(
           Intent.ACTION_MEDIA_MOUNTED,
           Uri.parse("file://" +  Environment.getExternalStorageDirectory())));

This code works, but it is very resource expensive. It unmounts & then mounts the SDCard which may affect some applications or take huge system resources in order to refresh the gallery. I am still looking for a best alternative & will post if i get one.

Ron
  • 24,175
  • 8
  • 56
  • 97
Rajiv
  • 41
  • 1
1

I had the same issue, and I tried three different methods to delete an image. Sometimes it was working sometimes it wasn't. After too much time spent now every method that I have will delete the image.What I wanna say is: BE CAREFUL WITH PROCESSING BITMAP. I was taking a picture persist it and then rotate if needed:

public static Bitmap rotatePictureToPortraitMode(String filePath, Bitmap myBitmap) {
try {
    ExifInterface exif = new ExifInterface(filePath);
    int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
    Log.d("EXIF", "Exif: " + orientation);
    Matrix matrix = new Matrix();
    if (orientation == 6) {
        matrix.postRotate(90);
    } else if (orientation == 3) {
        matrix.postRotate(180);
    } else if (orientation == 8) {
        matrix.postRotate(270);
    }
    myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true); // rotating bitmap
} catch (Exception e) {

}
return myBitmap;
}

after that I tried to delete the image but as I said previously it wasn't working. Removing this method helped to me to solve the issue.

Maybe this was only my issue but as soon as I removed this it helped me a lot, so I wanna say careful how you are processing the image. For my case I used the answer that is previously mentioned :

File file = new File(photoUri);
file.delete();

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, 
Uri.fromFile(new File(photoUri)))); 

Hope it helps!

f.trajkovski
  • 794
  • 9
  • 24
0
public static boolean deltefolderwithimages(File dir) {
    if (dir.isDirectory()) {
        String[] children = dir.list();
        for (int i=0; i<children.length; i++) {
            boolean success = deltefolderwithimages(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
    }
    return dir.delete();
}
Gopal Reddy
  • 36
  • 1
  • 5
0

DocumentFile.fromSingleUri(context, uri).delete();

Working great for me

Azhar Ali
  • 1,961
  • 3
  • 13
  • 24
0

this all method deprecated for Android 11+, for Delete any media file in Android11+ you can send request for delete., for this i found one dependency for this just check i hope your issue is resolve using this method.

https://github.com/jcredking/Delete1