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

如何使用MediaStore API访问Android 11中的WhatsApp文件夹

Android 11 下使用MediaStore访问外部存储实现方案

前置权限配置

在AndroidManifest.xml中添加对应权限:

<!-- 读取公共媒体文件权限,Android 13+可细化为图片/音频/视频单独权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 写入公共媒体文件权限,Android 10+无需申请该权限即可写入自身创建的媒体文件 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />

如果需要访问非媒体类公共文件,需要额外添加:

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

该权限需要引导用户到系统设置页手动开启,且上架Google Play需要符合特殊应用场景要求。

读取公共媒体文件示例(Kotlin)

以读取外部存储所有图片文件为例:

val contentResolver = context.contentResolver
// 要查询的文件信息列
val projection = arrayOf(
    MediaStore.Images.Media._ID,
    MediaStore.Images.Media.DISPLAY_NAME,
    MediaStore.Images.Media.SIZE,
    MediaStore.Images.Media.DATE_ADDED
)
// 筛选条件,这里查询所有图片
val selection = null
val selectionArgs = null
// 按添加时间倒序排序
val sortOrder = "${MediaStore.Images.Media.DATE_ADDED} DESC"

contentResolver.query(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection,
    selection,
    selectionArgs,
    sortOrder
)?.use { cursor ->
    val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
    val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
    while (cursor.moveToNext()) {
        val fileId = cursor.getLong(idColumn)
        val fileName = cursor.getString(nameColumn)
        // 构建文件访问Uri
        val fileUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, fileId)
        // 后续可通过该Uri打开输入流读取文件内容
        // val inputStream = contentResolver.openInputStream(fileUri)
    }
}

如果要访问其他类型的媒体,只需要替换对应的Uri即可:

  • 视频:MediaStore.Video.Media.EXTERNAL_CONTENT_URI
  • 音频:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
  • 下载文件:MediaStore.Downloads.EXTERNAL_CONTENT_URI

写入公共目录文件示例(Kotlin)

以写入文件到公共下载目录为例:

val contentResolver = context.contentResolver
val contentValues = ContentValues().apply {
    put(MediaStore.Downloads.DISPLAY_NAME, "test_file.txt")
    put(MediaStore.Downloads.MIME_TYPE, "text/plain")
    // Android 10+ 不需要指定路径,系统自动分配到对应公共目录
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
        put(MediaStore.Downloads.DATA, "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/test_file.txt")
    }
}
// 插入文件记录获取Uri
val fileUri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
fileUri?.let { uri ->
    // 打开输出流写入内容
    contentResolver.openOutputStream(uri)?.use { outputStream ->
        outputStream.write("测试内容".toByteArray())
    }
}

注意事项

  • Android 11 分区存储规则下,MediaStore仅能访问公共媒体集合和自身应用专属目录,无法访问其他应用的专属目录文件
  • 仅修改/删除其他应用创建的公共媒体文件时,需要额外申请读写权限,且操作时会触发用户授权弹窗
  • 应用卸载重装后,之前创建的媒体文件会被标记为其他应用所有,需要重新申请权限才能修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:36:03