Android的媒体扫描器:如何删除文件?

11

我正在编写一个应用程序,可以删除可能或可能未列在任何一种媒体库中(例如音乐或图片)的文件。虽然我可以使用MediaScannerConnection.scanFile方法将文件添加到媒体库中,但似乎没有调用通知服务已删除文件的方法。向服务发送不再存在的文件路径也无法产生预期的行为。那么我该如何从Android存储中删除不存在的库项呢?

5个回答

14

我能够根据这两个问题的部分内容编写出一个方法。

  1. 什么是 MediaStore.Audio.Playlists.Members.getContentUri 中字符串 'volumeName' 参数所指的内容?
  2. 如何在安卓上刷新 MediaStore?

基本上,我只是对每种 MediaStore 类型 (音频、视频和图片) 运行一个查询,选择路径并删除找到的任何记录。

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
}

我不完全确定这样做是否安全,但这是我迄今为止找到的唯一解决方案,经过一些初步测试似乎可以工作。如果有人对这种方法有进一步的信息或更好的执行此功能的方法,请提交其他答案。


对于路径通配符,我添加了 select += MediaStore.MediaColumns.DATA + "like ?"; 并在我的路径字符串列表末尾追加了 %。这将返回特定文件夹中的所有文件。 - Diederik

8

Spencer Ruport的答案是正确的,但是为了删除文件,您不需要查询和打开游标。因此,对于一个音乐文件,代码可以简单地写成:

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.我想评论Spencer Ruport的答案,但还没有足够的声望。


更简单、更清晰的方法。谢谢。我还可以通过提供相关的where子句来使用它进行批量删除。 - Sara
似乎是最合适、最直接和最安全的方式。我希望它在所有配置上都能正常工作。 - WindRider

8

易如反掌: 每当你添加一个文件,让MediaStoreContentProvider知道它的存在即可。

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

删除操作:只需使用

getContentResolver().delete(Uri.fromFile(fileToDeleteFromMediaStore), null, null)

2
你试过你的解决方案吗?我试过了,但似乎不起作用。 - clemp6r
是的,它对我有效。唯一的缺陷是当我删除一个文件时,MediaStore 会被通知并在某些设备上重新创建一个空的(0字节)文件。不知道为什么,但之后我将其删除了。 - Pascal
@BerndS,我正在使用Intent.ACTION_MEDIA_SCANNER_SCAN_FILE。你给的链接是关于Intent.ACTION_MEDIA_MOUNTED的。你有在4.4上尝试过我的解决方案吗? - Pascal
1
@Pascal 刚刚尝试了你的解决方案,它有效。不过我得等我的 Nexus 7 更新到 KitKat 版本。 - Bernd S
那么您是先删除文件,然后将已删除文件的文件路径发送到扫描文件中吗?我尝试了该命令,只能添加到媒体库,无法删除。 - nomaam
显示剩余3条评论

7
以下对我来说很有效。您可以使用此方法删除或添加文件。
MediaScannerConnection.scanFile(
                context,
                new String[]{fileToDelete, fileToAdd},
                null, null);

2
这将在某些设备上创建零字节文件。 - Learn OpenGL ES
媒体选择器在删除文件并重新扫描后仍然显示文件存在。 - Someone Somewhere

0

1
你好,我很喜欢你在Github上的帖子,但是我似乎无法让“从媒体库中删除”功能正常工作。我通过程序将文件从sdcard/Tumblr文件夹移动(因为我喜欢它们存储在内存卡而不是内部存储器中)。当我这样做时,我需要更新mediastore以让它知道该图像已从内部存储的Tumblr文件夹中“删除”。但是,无论我如何使用你的代码,我都无法让它正常工作。两个问题:(1)我如何指定内部存储器中的Tumblr路径,(2)我应该使用EXTERNAL_CONTENT_URI还是INTERNAL_CONTENT_URI。提前致谢。 - KickAss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接