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

Android中RecyclerView项点击下载对应文件失败,求解决方案

文件下载失败问题排查与解决

我通过API获取了包含文件名的记录列表,用RecyclerView展示列表项,点击项内图标时需要将对应文件下载到手机存储,但执行代码后文件未成功下载,相关代码如下:

点击触发的权限检查与下载启动代码

override fun showPrecription(record: Record) {
    if (record.file!=null){
        val context: Context = this

        // Check if the app has the WRITE_EXTERNAL_STORAGE permission
        if (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // Request the permission
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION
            )
            fileNameToDownload=record.file
        } else{
            downloadFile(Helper.RECORDS_URL,record.file)
        }
    }else Toast.makeText(this,"File path is not exist",Toast.LENGTH_LONG).show()
}

下载核心函数

fun downloadFile(fileUrl: String, fileName: String) {
    val request = DownloadManager.Request(Uri.parse(fileUrl))
        .setTitle(fileName)
        .setDescription("Downloading")
        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)

    val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    downloadManager.enqueue(request)
}

问题排查与修复方案

  • 补全权限回调逻辑
    当前代码仅请求权限,但未在用户授予权限后触发下载。需要重写权限回调方法,在用户允许权限时执行下载:

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                fileNameToDownload?.let {
                    downloadFile(Helper.RECORDS_URL, it)
                }
            } else {
                Toast.makeText(this, "需要存储权限才能下载文件", Toast.LENGTH_SHORT).show()
            }
        }
    }
    
  • 验证下载URL完整性
    确认Helper.RECORDS_URL是完整的文件前缀(如https://your-domain.com/files/),与record.file拼接后形成可直接访问的完整URL,避免因URL无效导致下载失败。

  • 适配Android 10+存储规则
    Android 10及以上版本中,WRITE_EXTERNAL_STORAGE权限不再直接控制公共目录写入。可以:

    1. 在Manifest的<application>标签中添加android:requestLegacyExternalStorage="true"(临时兼容旧行为);
    2. 确保下载URL返回正确的Content-Type,DownloadManager依赖该字段识别文件类型。
  • 添加下载状态监听
    注册广播监听下载完成事件,确认下载是否执行及失败原因:

    private val downloadReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val downloadId = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) ?: -1
            if (downloadId == -1) return
    
            val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
            val query = DownloadManager.Query().setFilterById(downloadId)
            val cursor = downloadManager.query(query)
    
            if (cursor.moveToFirst()) {
                val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                when (status) {
                    DownloadManager.STATUS_SUCCESSFUL -> Toast.makeText(context, "下载完成", Toast.LENGTH_SHORT).show()
                    DownloadManager.STATUS_FAILED -> {
                        val failReason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON))
                        Toast.makeText(context, "下载失败,原因码:$failReason", Toast.LENGTH_SHORT).show()
                    }
                }
            }
            cursor.close()
        }
    }
    
    // 在Activity的onCreate中注册广播
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...其他初始化代码
        registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
    }
    
    // 在Activity的onDestroy中注销广播
    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(downloadReceiver)
    }
    
  • 检查文件名合法性
    确认record.file不含非法字符(如/、:、*等),避免因文件名无效导致无法创建文件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:47:46