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

Android 11用File类访问下载目录仅显示子目录,如何获取文件?

Android 11下读取Download目录所有文件的可行方案

问题根源

Android 11(API 30)启用分区存储后,公共Download目录的File类访问权限被严格限制:默认仅允许APP读取自身创建的文件,以及系统预留的特定子目录(如你看到的downloaded_rom、Filemail等),其他用户或第三方APP放置的文件无法通过File直接读取。

可行解决办法

1. 使用MANAGE_EXTERNAL_STORAGE权限(需注意合规性)

该权限允许APP访问所有共享存储文件,但Google Play仅对特定类型APP(如文件管理器、系统工具类)开放审核,普通APP使用可能无法通过上架审核。

  • 步骤1:配置Manifest权限

    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        android:minSdkVersion="30" />
    <!-- 兼容Android 10及以下版本 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="29" />
    
  • 步骤2:代码中申请权限

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // 检查是否已获取全存储访问权限
        if (!Environment.isExternalStorageManager()) {
            // 跳转到权限设置页面
            val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
            intent.data = Uri.parse("package:$packageName")
            startActivity(intent)
        } else {
            // 有权限后,即可正常读取Download目录所有内容
            val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
            downloadsDir.listFiles()?.forEach { file ->
                // 处理文件或目录
                Log.d("DownloadContent", file.name)
            }
        }
    }
    

2. 重新评估MediaStore的适用性

你提到MediaStore不适用,但如果仅需读取文件内容、获取文件信息(而非直接操作File对象),MediaStore是符合分区存储规范的合法方案,且无需用户手动选择目录:

val projection = arrayOf(
    MediaStore.Downloads._ID,
    MediaStore.Downloads.DISPLAY_NAME,
    MediaStore.Downloads.RELATIVE_PATH
)

// 筛选Download目录下的文件
val selection = "${MediaStore.Downloads.RELATIVE_PATH} LIKE ?"
val selectionArgs = arrayOf("%Download/%")

contentResolver.query(
    MediaStore.Downloads.EXTERNAL_CONTENT_URI,
    projection,
    selection,
    selectionArgs,
    null
)?.use { cursor ->
    while (cursor.moveToNext()) {
        val fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME))
        val filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.RELATIVE_PATH))
        
        // 读取文件内容
        val fileUri = ContentUris.withAppendedId(
            MediaStore.Downloads.EXTERNAL_CONTENT_URI,
            cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID))
        )
        contentResolver.openInputStream(fileUri)?.use { inputStream ->
            // 处理文件流
        }
    }
}

3. 仅访问APP专属Download目录(限自身创建的文件)

如果你的需求仅涉及读取自身APP下载的文件,可使用APP专属存储目录,无需额外权限:

val appDownloadDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
appDownloadDir?.listFiles()?.forEach { file ->
    // 处理APP自身创建的文件
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:40:29