Android N系统下如何从媒体内容提供程序中删除文件?
解决Android N及以上无法通过
File.delete()删除外置SD卡媒体文件的问题 这个问题的核心是Android 7.0(API 24)开始对外置可移除存储的权限模型做了重大调整,直接用File.delete()操作外置SD卡上的媒体文件已经不再受支持,哪怕你申请了WRITE_EXTERNAL_STORAGE权限。
为什么旧版本有效,Android N失效?
- 在Android N之前,
WRITE_EXTERNAL_STORAGE权限允许你读写整个外置SD卡的文件,所以直接通过File对象操作路径是可行的。 - 从Android N开始,Google收紧了外置存储的访问权限:
WRITE_EXTERNAL_STORAGE仅能访问内部存储和外置SD卡中你的应用私有目录(即getExternalFilesDir()返回的路径)。对于外置SD卡上的公共目录(比如DCIM、Music),你无法再通过File对象直接操作,必须通过系统提供的ContentResolver或者Storage Access Framework来处理。
你看到的/storage/1143-1403/...路径是外置SD卡的真实挂载点,这种路径对应的文件已经不在你的应用权限直接操作范围内了,所以new File(path).delete()会失败。
正确的解决方案:用ContentResolver通过Content URI删除媒体文件
既然是媒体文件,它们已经被系统的媒体库(MediaStore)索引,直接通过Content URI调用ContentResolver.delete()才是合规且跨版本兼容的方式,不需要依赖文件路径。
代码示例1:已知媒体文件的Content URI时直接删除
如果你已经从媒体查询中拿到了目标文件的Content URI(比如MediaStore.Video.Media.EXTERNAL_CONTENT_URI下的具体条目),直接执行:
ContentResolver resolver = getContentResolver(); // mediaUri是你查询到的目标文件的Content URI int rowsDeleted = resolver.delete(mediaUri, null, null); if (rowsDeleted > 0) { // 删除成功 } else { // 删除失败,可能是权限不足或文件不存在 }
代码示例2:通过文件路径匹配Content URI后删除
如果你只有文件路径,需要先匹配到对应的Content URI再删除(注意:Android Q及以上DATA字段可能被限制,建议用文件名、创建时间等其他字段匹配):
String targetPath = "/storage/1143-1403/DCIM/Camera/20171019_185604.mp4"; ContentResolver resolver = getContentResolver(); // 构建查询条件,匹配文件路径 Uri mediaUri = MediaStore.Files.getContentUri("external"); String selection = MediaStore.Files.FileColumns.DATA + " = ?"; String[] selectionArgs = new String[]{targetPath}; // 执行删除 int rowsDeleted = resolver.delete(mediaUri, selection, selectionArgs);
关于权限的额外说明
- 你清单里的
WRITE_INTERNAL_STORAGE和READ_INTERNAL_STORAGE是无效的,Android系统根本没有这两个官方权限,删掉它们就行。 - 确保你已经动态申请并获取了
WRITE_EXTERNAL_STORAGE(Android 6.0+需要动态权限),但如前所述,这个权限已经不足以直接操作外置SD卡的公共目录文件了。
额外建议
尽量避免依赖文件路径来操作媒体文件,因为不同Android版本的存储路径可能变化,而且权限限制会越来越严格。始终优先通过MediaStore的Content URI来增删改查媒体文件,这是官方推荐的跨版本兼容方案。
内容的提问来源于stack exchange,提问作者Robin Davies
相关产品推荐
相关产品推荐

