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权限不再直接控制公共目录写入。可以:- 在Manifest的
<application>标签中添加android:requestLegacyExternalStorage="true"(临时兼容旧行为); - 确保下载URL返回正确的Content-Type,
DownloadManager依赖该字段识别文件类型。
- 在Manifest的
添加下载状态监听
注册广播监听下载完成事件,确认下载是否执行及失败原因: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
相关产品推荐
相关产品推荐

