关于 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 设备可能对回收站有不同的实现,但您的方法是最通用的解决方案。

相关推荐
梦想改变生活35 分钟前
《Flutter篇第二章》MasonryGridView瀑布流列表
android·flutter
杨航 AI1 小时前
PHP 5.5 Action Management with Parameters (English Version)
android·开发语言·php
柿蒂2 小时前
一次Android下载优化,CDN消耗占比从50+%到1%
android·android jetpack
Andrew_Ryan3 小时前
gradle set up
android
_祝你今天愉快4 小时前
在安卓中使用 FFmpegKit 剪切视频并添加文字水印
android·ffmpeg
编程乐学6 小时前
网络资源模板--基于Android Studio 实现的新闻App
android·android studio·移动端开发·新闻·安卓大作业·新闻app
-曾牛7 小时前
PHP 与 MySQL 详解实战入门(1)
android·开发语言·mysql·渗透测试·php·php教程·脚本语言
Monkey-旭7 小时前
深入理解 Kotlin Flow:异步数据流处理的艺术
android·开发语言·kotlin·响应式编程·flow
不想迷路的小男孩8 小时前
Android Studio怎么显示多排table,打开文件多行显示文件名
android·ide·android studio
giaoho14 小时前
Android 系统架构
android·系统架构