Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android's Media Scanner: How do I remove files?

I'm writing an app that removes files that may or may not be listed in any one of the types of media libraries such as music or pictures. While I can use the MediaScannerConnection.scanFile method to add files to the media library there doesn't seem to be any call to notify the service that the file has been removed. Sending it the path of the file that no longer exists doesn't result in the desired behavior either. How should I go about removing items from the library that no longer exist on the Android storage?

like image 885
Spencer Ruport Avatar asked Dec 05 '11 00:12

Spencer Ruport


4 Answers

The following works well for me. You can delete or add files using this.

MediaScannerConnection.scanFile(
                context,
                new String[]{fileToDelete, fileToAdd},
                null, null);
like image 105
wislo Avatar answered Oct 18 '22 03:10

wislo


I was able to put a method together using bits and pieces from these two questions

  1. What is the String 'volumeName' argument of MediaStore.Audio.Playlists.Members.getContentUri referring to?
  2. How can I refresh MediaStore on Android?

Basically I just run a query on each one of the MediaStore types (Audio, Video and Images) selecting by path and deleting any records I find.

public static void RemoveAllForPaths(String[] paths, Context context)
{
    private static final String[] FIELDS = { MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.TITLE };
    if(paths == null || paths.length == 0) return;
    String select = "";
    for(String path : paths)
    {
        if(!select.equals("")) select += " OR ";
        select += MediaStore.MediaColumns.DATA + "=?";
    }

    Uri uri;
    Cursor ca;

    uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    ca = context.getContentResolver().query(uri, FIELDS, select, paths, null);
    for(ca.moveToFirst(); !ca.isAfterLast(); ca.moveToNext()){
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
        context.getContentResolver().delete(uri, null, null);
    }
    ca.close();

    // More of the same just setting the URI to Video and Images
}

I'm not entirely sure how safe this is to do but it's the only solution I've found so far and some initial testing seems to be working. I invite others to submit other answers if anyone has any further information on this approach or a better method for performing this functionality.

like image 40
Spencer Ruport Avatar answered Oct 18 '22 02:10

Spencer Ruport


Answer of Spencer Ruport is right, but you don't need to query and open a cursor in order to delete. So for one file that is music file the code is simple like that:

public void DeleteMP3FromMediaStore( Context context, String path )
{
    Uri rootUri = MediaStore.Audio.Media.getContentUriForPath( path );

    context.getContentResolver().delete( rootUri, 
        MediaStore.MediaColumns.DATA + "=?", new String[]{ path } );
}

P.S. I wanted to comment answer of Spencer Ruport but don't have enough reputation yet.

like image 8
Sergey Povalyaev Avatar answered Oct 18 '22 02:10

Sergey Povalyaev


Easy as pie: whenever you add a file, let MediaStore ContentProvider knows about it using

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(fileToAddInMediaStore)));

For deletion: just use

getContentResolver().delete(Uri.fromFile(fileToDeleteFromMediaStore), null, null)
like image 8
Pascal Avatar answered Oct 18 '22 01:10

Pascal