You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11+相册应用中如何用Kotlin获取回收站媒体列表

Android 11+ 相册应用回收站媒体获取与恢复实现

问题背景

已实现通过MediaStore.createTrashRequest将选中媒体移至系统回收站的功能,但原查询代码通过文件路径匹配.trashed无法获取回收站中的媒体项:

fun getHiddenMediaFiles(context: Context): List<String> {
    val hiddenMediaList = mutableListOf<String>()
    val contentResolver: ContentResolver = context.contentResolver
    val uri: Uri = MediaStore.Files.getContentUri("external")
    val projection = arrayOf(
        MediaStore.Files.FileColumns.DATA,
        MediaStore.Files.FileColumns.DISPLAY_NAME
    )

    val selection = "${MediaStore.Files.FileColumns.DATA} LIKE ?"
    val selectionArgs = arrayOf("%.trashed%")
    
    val cursor: Cursor? = contentResolver.query(
        uri,
        projection,
        selection,
        selectionArgs,
        null
    )

    cursor?.use {
        val dataColumnIndex = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)
        while (it.moveToNext()) {
            val filePath = it.getString(dataColumnIndex)
            hiddenMediaList.add(filePath)
        }
    }
    cursor?.close()

    for (ab in hiddenMediaList){
        Log.e("data", "-----------size-----------------${hiddenMediaList.size}")
    }
    return hiddenMediaList
}

解决方案

Android 11及以上版本中,系统回收站的媒体是通过MediaStore.MediaColumns.IS_TRASHED字段标记的(值为1表示已移入回收站),而非通过文件路径的.trashed标识。以下是正确的实现方式:

1. 查询回收站中的媒体项

data class TrashedMedia(
    val id: Long,
    val uri: Uri,
    val displayName: String,
    val mimeType: String
)

fun getTrashedMedia(context: Context): List<TrashedMedia> {
    val trashedMediaList = mutableListOf<TrashedMedia>()
    val contentResolver = context.contentResolver

    // 可根据需求选择查询图片、视频或所有文件
    val contentUri = MediaStore.Files.getContentUri("external")
    
    val projection = arrayOf(
        MediaStore.Files.FileColumns._ID,
        MediaStore.Files.FileColumns.DISPLAY_NAME,
        MediaStore.Files.FileColumns.MIME_TYPE,
        MediaStore.MediaColumns.IS_TRASHED
    )

    // 筛选条件:仅查询已移入回收站的媒体
    val selection = "${MediaStore.MediaColumns.IS_TRASHED} = ?"
    val selectionArgs = arrayOf("1")

    contentResolver.query(
        contentUri,
        projection,
        selection,
        selectionArgs,
        "${MediaStore.Files.FileColumns.DATE_MODIFIED} DESC" // 按修改时间倒序
    )?.use { cursor ->
        val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
        val displayNameColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)
        val mimeTypeColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE)

        while (cursor.moveToNext()) {
            val id = cursor.getLong(idColumn)
            val displayName = cursor.getString(displayNameColumn)
            val mimeType = cursor.getString(mimeTypeColumn)
            val uri = ContentUris.withAppendedId(contentUri, id)

            trashedMediaList.add(TrashedMedia(id, uri, displayName, mimeType))
        }
    }

    return trashedMediaList
}

2. 恢复回收站中的媒体项

和移入回收站的逻辑类似,使用MediaStore.createRestoreRequest触发系统权限弹窗,完成恢复操作:

fun restoreTrashedMedia(activity: Activity, mediaUris: List<Uri>) {
    try {
        val pendingIntent = MediaStore.createRestoreRequest(
            activity.contentResolver,
            mediaUris
        )

        activity.startIntentSenderForResult(
            pendingIntent.intentSender,
            102, // 自定义请求码
            null,
            0,
            0,
            0,
            null
        )
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

注意事项

  • 确保应用已申请READ_EXTERNAL_STORAGE权限(Android 11+中访问媒体库需要此权限)
  • 若针对Android 13+,可使用更细化的READ_MEDIA_IMAGES/READ_MEDIA_VIDEO权限替代READ_EXTERNAL_STORAGE
  • 查询时可分别使用MediaStore.Images.Media.EXTERNAL_CONTENT_URI或MediaStore.Video.Media.EXTERNAL_CONTENT_URI来单独查询图片或视频,提升查询效率

内容的提问来源于stack exchange,提问作者Viral Radadiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:31:00