Android 11删除媒体文件报错:Uri需关联特定ID
问题
在Android 10及以上系统中,调用MediaStore.createDeleteRequest唤起用户确认删除媒体文件的窗口时,抛出异常:java.lang.IllegalArgumentException: All requested items must be referenced by specific ID,原因是传入的Uri格式不符合接口要求。
当前代码:
if (Build.VERSION.SDK_INT >= 30) { val collection: ArrayList<Uri> = ArrayList() for (i in 0 until Params.dataListPath.size) { collection.add(Params.dataListPath[i].file.path.toUri()) Log.d(TAG, "onShowDialogConfirmDelete: " + collection[i].path) } val pendingIntent = MediaStore.createDeleteRequest(requireActivity().contentResolver, collection).intentSender startIntentSenderForResult(pendingIntent, 100, null, 0, 0, 0, null) }
异常信息:
java.lang.IllegalArgumentException: All requested items must be referenced by specific ID at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142) at android.content.ContentProviderProxy.call(ContentProviderNative.java:732) at android.content.ContentResolver.call(ContentResolver.java:2433) at android.provider.MediaStore.createRequest(MediaStore.java:834) at android.provider.MediaStore.createDeleteRequest(MediaStore.java:997) at com.test.cleanerapp.duplicate_files.view.fragment.DuplicateFindFragment.onShowDialogConfirmDelete(DuplicateFindFragment.kt:119)
解决方案
核心问题:直接通过文件路径转换的
file://格式Uri,不是MediaStore认可的带唯一ID的内容Uri。createDeleteRequest要求传入的Uri必须是MediaStore中存储的、包含媒体文件ID的内容Uri(格式示例:content://media/external/images/media/123)。修正方案:
- 根据文件路径查询MediaStore,获取对应媒体文件的唯一ID。
- 用ID构建符合要求的内容Uri,替换原代码中直接转换路径的逻辑。
修正后的示例代码:
if (Build.VERSION.SDK_INT >= 30) { val collection = mutableListOf<Uri>() val contentResolver = requireActivity().contentResolver Params.dataListPath.forEach { item -> val filePath = item.file.path // 针对全类型媒体文件的查询Uri,也可根据类型用更具体的Uri(如图片用MediaStore.Images.Media.EXTERNAL_CONTENT_URI) val queryUri = MediaStore.Files.getContentUri("external") val projection = arrayOf(MediaStore.Files.FileColumns._ID) val selection = "${MediaStore.Files.FileColumns.DATA} = ?" val selectionArgs = arrayOf(filePath) contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> if (cursor.moveToFirst()) { val mediaId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) // 构建带ID的合法内容Uri val validUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), mediaId) collection.add(validUri) } } } if (collection.isNotEmpty()) { val pendingIntent = MediaStore.createDeleteRequest(contentResolver, collection).intentSender startIntentSenderForResult(pendingIntent, 100, null, 0, 0, 0, null) } }
- 额外说明:
- 针对图片、视频、音频等特定类型的媒体文件,使用对应类型的MediaStore Uri查询(如
MediaStore.Video.Media.EXTERNAL_CONTENT_URI),能提升查询精准度和效率。 - Android 11及以上系统中,通过MediaStore查询无需
MANAGE_EXTERNAL_STORAGE权限,只要文件属于媒体库可识别的类型即可。
- 针对图片、视频、音频等特定类型的媒体文件,使用对应类型的MediaStore Uri查询(如
内容的提问来源于stack exchange,提问作者Armenak Mkhitaryan
相关产品推荐
相关产品推荐

