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

如何使用Media Store API访问/WhatsApp/Media/.Statuses文件夹适配Android SDK 30及以上

Android 30+ 访问WhatsApp .Statuses文件夹实现方案

1. 权限配置(AndroidManifest.xml)

  • SDK 30~32 需声明权限:android.permission.READ_EXTERNAL_STORAGE
  • SDK >=33 需声明权限:android.permission.READ_MEDIA_IMAGES、android.permission.READ_MEDIA_VIDEO
  • 无需申请MANAGE_EXTERNAL_STORAGE权限,避免上架应用商店被驳回
  • 应用启动时先动态申请对应版本的存储权限,用户授权后再执行查询逻辑

2. MediaStore核心查询逻辑

Android 30+ 无需直接访问/WhatsApp/Media/.Statuses物理路径,通过MediaStore.Files表过滤相对路径即可拿到所有状态文件:

// 定义查询需要返回的字段
val projection = arrayOf(
    MediaStore.Files.FileColumns._ID,
    MediaStore.Files.FileColumns.DISPLAY_NAME,
    MediaStore.Files.FileColumns.MIME_TYPE,
    MediaStore.Files.FileColumns.DATE_MODIFIED
)

// 过滤规则:匹配普通WhatsApp和商业版WhatsApp的状态目录
val selection = "${MediaStore.Files.FileColumns.RELATIVE_PATH} LIKE ? OR ${MediaStore.Files.FileColumns.RELATIVE_PATH} LIKE ?"
val selectionArgs = arrayOf(
    "%WhatsApp/Media/.Statuses%",
    "%WhatsApp Business/Media/.Statuses%"
)

// 执行查询,按修改时间倒序排列
contentResolver.query(
    MediaStore.Files.getContentUri("external"),
    projection,
    selection,
    selectionArgs,
    "${MediaStore.Files.FileColumns.DATE_MODIFIED} DESC"
)?.use { cursor ->
    val statusList = mutableListOf<StatusMedia>()
    while (cursor.moveToNext()) {
        val mediaId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
        val mediaName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME))
        val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE))
        // 生成可直接访问的Content Uri
        val contentUri = if (mimeType.startsWith("image")) {
            ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediaId)
        } else {
            ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, mediaId)
        }
        statusList.add(StatusMedia(mediaName, mimeType, contentUri))
    }
}

3. 后续操作说明

  • 拿到contentUri后可直接加载到ImageView、VideoView中预览
  • 需要保存状态时,直接通过contentResolver.openInputStream(contentUri)拿到输入流,写入到应用专属目录或者公共DCIM/StatusSaver目录即可,无需额外权限

4. 兼容注意事项

  • 不要使用MediaStore.Images或MediaStore.Video单表查询,隐藏目录的媒体文件不会被收录到这两个表中,必须用MediaStore.Files表查询
  • 部分区域版本的WhatsApp可能修改路径,可根据实际情况扩展selectionArgs的匹配规则
  • 若查询结果为空,先检查是否已拿到存储权限,以及用户的WhatsApp是否已经生成过状态文件

内容的提问来源于stack exchange,提问作者Ambreen Zubari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:45:08