Android开发:如何正确使用DownloadManager的COLUMN_ID等列字段
嘿,我完全懂你的困惑——刚从C#转Android开发,碰到DownloadManager的这些COLUMN_*字段确实容易摸不着头脑!你现在看到Toast显示_id、total_size是正常的,因为这些常量本质是DownloadManager内部数据库的列名称字符串,不是直接能拿到下载数据的字段。下面我给你掰明白怎么正确用它们:
先搞懂核心逻辑
DownloadManager.COLUMN_ID、COLUMN_TOTAL_SIZE_BYTES这些常量,是用来给ContentProvider查询做“索引标记”的——你得先拿到具体下载任务的ID,再用这些常量去查询数据库,才能获取到对应的实际数值(比如任务ID、总大小、已下载进度)。
第一步:保存下载任务的ID
当你调用manager.enqueue(request)时,这个方法会返回当前下载任务的唯一ID(Long类型),这是你后续查询的关键!你的原代码里没保存这个ID,所以根本没法关联到具体的下载任务。
修改你的下载方法,先把ID存下来:
fun download(url: String, name: String) { val request = DownloadManager.Request(Uri.parse(url)) .setVisibleInDownloadsUi(true) .allowScanningByMediaScanner() .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) // 建议用系统提供的目录常量,更适配不同版本 .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "$name.pdf") val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager // 保存下载任务ID!这是核心 val downloadId = manager.enqueue(request) // 现在可以用这个ID去查询下载数据了 val downloadInfo = getDownloadDetails(downloadId) Toast.makeText(applicationContext, downloadInfo, Toast.LENGTH_SHORT).show() }
第二步:用ID + COLUMN_*常量查询实际数据
写一个工具方法,通过下载ID查询任务的详细信息,这里就会用到那些COLUMN_*常量:
fun getDownloadDetails(downloadId: Long): String { val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager // 创建查询对象,过滤出当前ID的下载任务 val query = DownloadManager.Query().setFilterById(downloadId) val cursor = manager.query(query) return if (cursor.moveToFirst()) { // 用COLUMN_*常量获取列的索引,再拿到对应数值 val totalSize = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)) val downloadedSize = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)) val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) // 把状态转成可读文本 val statusText = when(status) { DownloadManager.STATUS_PENDING -> "等待下载" DownloadManager.STATUS_RUNNING -> "下载中:$downloadedSize/$totalSize Bytes" DownloadManager.STATUS_SUCCESSFUL -> "下载完成!总大小:$totalSize Bytes" DownloadManager.STATUS_FAILED -> "下载失败" else -> "未知状态" } statusText } else { "未找到该下载任务" }.also { // 务必关闭Cursor,避免内存泄漏 cursor.close() } }
关键细节解释
cursor.getColumnIndex(DownloadManager.COLUMN_XXX):这个方法会根据你传入的列名称(也就是COLUMN_*常量的值),找到该列在Cursor中的位置索引,然后你才能用getLong/getInt等方法拿到实际数据。- 权限注意:别忘了在
AndroidManifest.xml里添加必要权限:<uses-permission android:name="android.permission.INTERNET" /> <!-- Android 10及以下需要,11+用Scoped Storage可省略 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> - 监听下载完成:如果想在下载完成时自动获取结果,可以注册广播接收器监听
DownloadManager.ACTION_DOWNLOAD_COMPLETE,然后从Intent里取出DownloadManager.EXTRA_DOWNLOAD_ID再查询数据。
内容的提问来源于stack exchange,提问作者evals




