关于 Android 系统回收站的实现

您的观察非常正确。Android 系统的回收站实现通常是通过以下几种方式:

  • 文件名添加 .Trash 前缀,使文件在文件浏览器中被隐藏

  • 在 MediaStore 中将文件标记为 IS_TRASHED = 1

  • 有些设备会将文件移动到特定的 .Trash 目录

    // 创建文件条目时使用 .Trash 前缀 put(MediaStore.MediaColumns.DISPLAY_NAME, ".Trash-"+System.currentTimeMillis()/1000+"-"+fileName)

    // 然后在所有 URI 上设置 IS_TRASHED 标记 val values = ContentValues().apply { put(MediaStore.MediaColumns.IS_TRASHED, 1) } contentResolver.update(uri, values, null, null)

回收站实现的关键点

  • 文件名前缀:.Trash-[时间戳]-[原文件名] 是一种常见的格式

  • IS_TRASHED 标记:在 Android 11+ 上,这个标记告诉系统该文件已被移到回收站

  • 相对路径:将文件放在应用专属目录下,如 Pictures/应用名称/

  • 保留元数据:保存原始文件名和删除时间,以便将来可以恢复

    /**

    • 从回收站恢复文件 */ @RequiresApi(Build.VERSION_CODES.Q) suspend fun restoreFromTrash(context: Context, uri: Uri) = withContext(Dispatchers.IO) { try { val contentResolver = context.contentResolver

      kotlin 复制代码
       // 1. 获取当前文件名
       var fileName = ""
       contentResolver.query(
           uri,
           arrayOf(MediaStore.MediaColumns.DISPLAY_NAME),
           null,
           null,
           null
       )?.use { cursor ->
           if (cursor.moveToFirst()) {
               fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME))
           }
       }
       
       if (fileName.startsWith(".Trash-")) {
           // 2. 提取原始文件名
           val originalFileName = fileName.substringAfter("-", "").substringAfter("-", "")
           
           // 3. 更新文件属性
           val values = ContentValues().apply {
               put(MediaStore.MediaColumns.DISPLAY_NAME, originalFileName)
               put(MediaStore.MediaColumns.IS_TRASHED, 0)
           }
           
           // 4. 应用更新
           contentResolver.update(uri, values, null, null)
           LogMG.e("tagyy", "文件已从回收站恢复: $originalFileName")
           return@withContext true
       }

      } catch (e: Exception) { LogMG.e("tagyy", "从回收站恢复失败: ${e.message}") e.printStackTrace() } return@withContext false }

    /**

    • 获取回收站中的所有文件 */ @RequiresApi(Build.VERSION_CODES.Q) suspend fun getTrashFiles(context: Context) = withContext(Dispatchers.IO) { val trashFiles = mutableListOf() val contentResolver = context.contentResolver

      // 查询所有已标记为回收站的文件 val selection = " <math xmlns="http://www.w3.org/1998/Math/MathML"> M e d i a S t o r e . M e d i a C o l u m n s . I S T R A S H E D = ? O R {MediaStore.MediaColumns.IS_TRASHED} = ? OR </math>MediaStore.MediaColumns.ISTRASHED=?OR{MediaStore.MediaColumns.DISPLAY_NAME} LIKE ?" val selectionArgs = arrayOf("1", ".Trash-%")

      // 查询不同类型的媒体 val uriTypes = listOf( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MediaStore.Downloads.EXTERNAL_CONTENT_URI )

      for (uri in uriTypes) { contentResolver.query( uri, arrayOf(MediaStore.MediaColumns._ID), selection, selectionArgs, null )?.use { cursor -> while (cursor.moveToNext()) { val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) trashFiles.add(ContentUris.withAppendedId(uri, id)) } } }

      return@withContext trashFiles }

总结

Android 系统回收站的实现主要依赖于:

  • 文件名前缀(.Trash-)

  • MediaStore 中的 IS_TRASHED 标记

  • 将文件放在特定目录

您的实现已经涵盖了这些关键点,应该能够正常工作。记住,不同厂商的 Android 设备可能对回收站有不同的实现,但您的方法是最通用的解决方案。

相关推荐
wy3136228212 分钟前
android——开发中的常见Bug汇总与解决方案(闪退)
android·bug
小小测试开发1 小时前
实战派SQL性能优化:从语法层面攻克项目中的性能瓶颈
android·sql·性能优化
QuantumLeap丶2 小时前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios
StarShip3 小时前
从Activity.setContentView()开始
android
千里马学框架3 小时前
重学SurfaceFlinger之Layer显示区域bounds计算剖析
android·智能手机·sf·安卓framework开发·layer·surfaceflinger·车载开发
nono牛4 小时前
安卓休眠与唤醒流程
android
二流小码农5 小时前
鸿蒙开发:个人开发者如何使用华为账号登录
android·ios·harmonyos
StarShip6 小时前
Android View框架概览
android·计算机图形学
愤怒的代码6 小时前
解析Android内存分析的指标
android·app
summerkissyou19876 小时前
android-hardware/interfaces/automotive和hardware/libhardware/include/hardware区别
android