下午好🌅🌅🌅
本答案参考通义千问
在 Android 11 及更高版本中,MediaStore.createTrashRequest 是官方推荐的用于将文件移至“回收站”的方式。但根据你的描述,你遇到了两个主要问题:
一、问题分析
1. 文件只是被重命名,并未真正进入回收站
- 你提到文件被重命名为
.trashed-... 格式,这说明系统确实执行了 createTrashRequest 操作,但并未将其放入“回收站”。 - 这可能是由于以下原因:
- 设备厂商(如荣耀 Magic4)对 MediaStore 的实现存在差异,部分设备可能不完全支持标准 API。
- 权限或配置问题:某些设备需要特定设置或权限才能启用“回收站”功能。
2. 无法查询到回收站中的文件
- 你尝试使用
MediaStore.Images.Media.EXTERNAL_CONTENT_URI 查询回收站内容,但返回的是 0 条数据。 - 这是因为 Android 中“回收站”并不是一个统一的存储位置,而是通过
MediaStore.Files.FileColumns.IS_TRASHED 标志来标记的。
二、解决方案
✅ 1. 确保调用正确的方法
确保你使用的是 MediaStore.createTrashRequest,并传入正确的参数:
val uris = it.map { media ->
media.uri
}
val request = MediaStore.createTrashRequest(
context.contentResolver,
uris,
true // 设置为 true 表示移至回收站
)
注意: createTrashRequest 并不会立即删除文件,而是请求系统将文件标记为“已删除”,等待系统处理。
✅ 2. 正确启动 IntentSender
你已经正确地使用了 ActivityResultContracts.StartIntentSenderForResult(),这是正确的做法。
val trashLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartIntentSenderForResult()
) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> Toast.makeText(context, "删除成功", Toast.LENGTH_SHORT).show()
else -> Toast.makeText(context, result.resultCode, Toast.LENGTH_SHORT).show()
}
}
✅ 3. 查询回收站文件的正确方式
要查询“回收站”中的文件,应使用 MediaStore.Files.FileColumns.IS_TRASHED 字段,并且应该使用 MediaStore.Files.getContentUri("external") 或者 MediaStore.Media.EXTERNAL_CONTENT_URI。
✅ 修改后的查询代码如下:
val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(
MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.IS_TRASHED
)
val selection = "${MediaStore.MediaColumns.IS_TRASHED} = ?"
val selectionArgs = arrayOf("1")
context.contentResolver.query(
uri,
projection,
selection,
selectionArgs,
null
)?.use { cursor ->
L.d { "queryMedia: ${cursor.count}" } // 应该返回非零值
val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
while (cursor.moveToNext()) {
val name = cursor.getString(nameColumn)
L.d { "queryMedia: $name" }
}
}
注意: 如果仍然查询不到结果,可能是设备不支持“回收站”功能,或者没有正确启用。
✅ 4. 检查设备是否支持回收站功能
有些设备(尤其是国产手机)可能不支持标准的“回收站”功能,即使使用了 createTrashRequest,也可能只做改名操作。
你可以通过以下方式检查设备是否支持:
val isTrashSupported = MediaStore.isTrashSupported(context.contentResolver)
L.d { "是否支持回收站: $isTrashSupported" }
注意: isTrashSupported 是 Android 13+ 才引入的 API,如果你的目标 SDK < 33,可能不可用。
✅ 5. 其他替代方案(如果设备不支持)
如果设备不支持回收站功能,你可以考虑以下替代方案:
a. 手动将文件移到隐藏目录
将文件移动到 .trash/ 目录,并添加 .trashed-* 前缀。
val file = File(uri.path)
val trashDir = File(context.getExternalFilesDir(null), ".trash")
if (!trashDir.exists()) {
trashDir.mkdirs()
}
val newName = ".trashed-${System.currentTimeMillis()}-${file.name}"
val newFile = File(trashDir, newName)
file.renameTo(newFile)
注意: 这种方式不是官方推荐,但可以模拟“回收站”行为。
b. 使用第三方库或自定义回收站逻辑
你可以自己维护一个“回收站”数据库,记录用户删除的文件路径,并提供恢复功能。
三、总结
| 问题 | 解决方案 |
|------|----------|
| 文件仅被重命名,未进入回收站 | 检查设备是否支持回收站;使用 MediaStore.createTrashRequest 并确保参数正确 |
| 无法查询回收站文件 | 使用 MediaStore.Files.getContentUri("external") 和 IS_TRASHED = 1 查询 |
| 设备不支持回收站 | 考虑使用手动移动文件或自定义回收站逻辑 |
四、最终建议
如果你希望实现真正的“回收站”功能,强烈建议你测试不同设备,因为 不同厂商对 MediaStore 的支持可能存在差异。如果你的目标是兼容性更强的方案,可以结合 createTrashRequest + 自定义回收站逻辑 来实现更稳定的用户体验。
如需进一步帮助,请提供你使用的 Android SDK 版本 和 设备型号/系统版本,我可以帮你进一步排查。