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

Android(Kotlin)中DownloadManager路径错误及默认缓存文件获取问题

DownloadManager路径问题及解决方案

一、路径错误的原因

DownloadManager是系统级服务,运行在独立进程中,没有权限访问你的App私有内部存储目录(即getDir()返回的/data/data/包名/app_xxx路径)。当你尝试将下载目标设置到这个目录时,就会触发SecurityException。

二、正确设置目标文件的方式

推荐两种合法的存储路径选择:

1. 保存到App专属外部存储目录

这个目录属于App私有空间,其他App无法访问,App卸载时会自动删除,Android 4.4+无需额外权限:

val urlStr = "https://example.net/SomeFolder/SomeFile.mp3"
// 直接指定App专属外部存储的Download子目录
val request = DownloadManager.Request(Uri.parse(urlStr))
    .setDestinationInExternalFilesDir(
        this,
        Environment.DIRECTORY_DOWNLOADS,
        "downloadAudio.mp3"
    )
val dldMgr = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadID = dldMgr.enqueue(request)

也可以手动构建文件对象后设置:

val dldFile = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "downloadAudio.mp3")
val request = DownloadManager.Request(Uri.parse(urlStr))
    .setDestinationUri(Uri.fromFile(dldFile))

2. 保存到公共外部存储目录

如果需要让文件在系统“下载”文件夹中可见,需根据系统版本申请对应存储权限:

// Android 9及以下需提前申请WRITE_EXTERNAL_STORAGE权限
val request = DownloadManager.Request(Uri.parse(urlStr))
    .setDestinationInExternalPublicDir(
        Environment.DIRECTORY_DOWNLOADS,
        "downloadAudio.mp3"
    )
    // 可选:通知栏显示下载进度和完成提示
    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)

三、获取默认共享下载缓存的文件及访问方法

未设置目标路径时,DownloadManager会将文件保存到系统共享下载目录(通常是/storage/emulated/0/Download/),可通过DownloadManager.Query查询文件信息:

// 下载完成后查询文件详情
fun getDownloadedFileInfo(downloadID: Long) {
    val dldMgr = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    val query = DownloadManager.Query().setFilterById(downloadID)
    val cursor = dldMgr.query(query)
    
    if (cursor.moveToFirst()) {
        val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
        if (status == DownloadManager.STATUS_SUCCESSFUL) {
            // 获取文件URI
            val localUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
            // 获取文件名
            val fileName = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE))
            // 获取文件总大小
            val fileSize = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
            
            // 访问文件:通过ContentResolver打开输入流
            val inputStream = contentResolver.openInputStream(Uri.parse(localUri))
            // 转为File对象(仅当URI为file://协议时有效)
            val filePath = Uri.parse(localUri).path
            val file = filePath?.let { File(it) }
        }
    }
    cursor.close()
}

注意:共享目录中的文件不会随App卸载删除,且其他App可访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 11:18:43